3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-2000,
7 * Copyright (C) Jean François Micouleau 1998-2000.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern int DEBUGLEVEL;
27 extern pstring global_myname;
28 extern DOM_SID global_sid_World;
30 static TDB_CONTEXT *tdb; /* used for driver files */
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define PRINTERS_PREFIX "PRINTERS/"
36 #define DATABASE_VERSION 1
38 /* Map generic permissions to printer object specific permissions */
40 struct generic_mapping printer_generic_mapping = {
47 /* We need one default form to support our default printer. Msoft adds the
48 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
49 array index). Letter is always first, so (for the current code) additions
50 always put things in the correct order. */
51 static nt_forms_struct default_forms[] = {
52 {"Letter", 0x2, 0x34b5b, 0x44367, 0x0, 0x0, 0x34b5b, 0x44367},
56 /****************************************************************************
57 open the NT printing tdb
58 ****************************************************************************/
59 BOOL nt_printing_init(void)
61 static pid_t local_pid;
62 char *vstring = "INFO/version";
64 if (tdb && local_pid == sys_getpid()) return True;
65 tdb = tdb_open(lock_path("ntdrivers.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
67 DEBUG(0,("Failed to open nt drivers database\n"));
71 local_pid = sys_getpid();
73 /* handle a Samba upgrade */
74 tdb_lock_bystring(tdb, vstring);
75 if (tdb_fetch_int(tdb, vstring) != DATABASE_VERSION) {
76 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
77 tdb_store_int(tdb, vstring, DATABASE_VERSION);
79 tdb_unlock_bystring(tdb, vstring);
85 /****************************************************************************
86 get a form struct list
87 ****************************************************************************/
88 int get_ntforms(nt_forms_struct **list)
90 TDB_DATA kbuf, newkey, dbuf;
96 for (kbuf = tdb_firstkey(tdb);
98 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
99 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
101 dbuf = tdb_fetch(tdb, kbuf);
102 if (!dbuf.dptr) continue;
104 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
105 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
106 &i, &form.flag, &form.width, &form.length, &form.left,
107 &form.top, &form.right, &form.bottom);
108 safe_free(dbuf.dptr);
109 if (ret != dbuf.dsize) continue;
111 /* allocate space and populate the list in correct order */
113 *list = Realloc(*list, sizeof(nt_forms_struct)*(i+1));
119 /* we should never return a null forms list or NT gets unhappy */
121 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
122 n = sizeof(default_forms) / sizeof(default_forms[0]);
129 /****************************************************************************
130 write a form struct list
131 ****************************************************************************/
132 int write_ntforms(nt_forms_struct **list, int number)
139 for (i=0;i<number;i++) {
140 /* save index, so list is rebuilt in correct order */
141 len = tdb_pack(buf, sizeof(buf), "dddddddd",
142 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
143 (*list)[i].left, (*list)[i].top, (*list)[i].right,
145 if (len > sizeof(buf)) break;
146 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[i].name);
147 dos_to_unix(key, True); /* Convert key to unix-codepage */
148 kbuf.dsize = strlen(key)+1;
152 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) break;
158 /****************************************************************************
159 add a form struct at the end of the list
160 ****************************************************************************/
161 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
168 * NT tries to add forms even when
169 * they are already in the base
170 * only update the values if already present
175 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
176 for (n=0; n<*count; n++) {
177 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
178 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
185 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
187 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
191 (*list)[n].flag=form->flags;
192 (*list)[n].width=form->size_x;
193 (*list)[n].length=form->size_y;
194 (*list)[n].left=form->left;
195 (*list)[n].top=form->top;
196 (*list)[n].right=form->right;
197 (*list)[n].bottom=form->bottom;
202 /****************************************************************************
203 delete a named form struct
204 ****************************************************************************/
205 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
216 * Don't delete the last form (no empty lists).
217 * CHECKME ! Is this correct ? JRA.
219 *ret = ERROR_INVALID_PARAMETER;
223 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
225 for (n=0; n<*count; n++) {
226 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
227 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
233 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
234 *ret = ERROR_INVALID_PARAMETER;
238 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[n].name);
239 dos_to_unix(key, True); /* Convert key to unix-codepage */
240 kbuf.dsize = strlen(key)+1;
242 if (tdb_delete(tdb, kbuf) != 0) {
243 *ret = ERROR_NOT_ENOUGH_MEMORY;
250 /****************************************************************************
252 ****************************************************************************/
253 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
257 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
259 DEBUG(106, ("[%s]\n", form_name));
260 for (n=0; n<count; n++)
262 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
263 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
267 if (n==count) return;
269 (*list)[n].flag=form->flags;
270 (*list)[n].width=form->size_x;
271 (*list)[n].length=form->size_y;
272 (*list)[n].left=form->left;
273 (*list)[n].top=form->top;
274 (*list)[n].right=form->right;
275 (*list)[n].bottom=form->bottom;
278 /****************************************************************************
279 get the nt drivers list
281 traverse the database and look-up the matching names
282 ****************************************************************************/
283 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
288 TDB_DATA kbuf, newkey;
290 get_short_archi(short_archi, architecture);
291 slprintf(key, sizeof(key), "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
293 for (kbuf = tdb_firstkey(tdb);
295 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
296 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
298 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
301 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
308 /****************************************************************************
309 function to do the mapping between the long architecture name and
311 ****************************************************************************/
312 BOOL get_short_archi(char *short_archi, char *long_archi)
319 struct table archi_table[]=
321 {"Windows 4.0", "WIN40" },
322 {"Windows NT x86", "W32X86" },
323 {"Windows NT R4000", "W32MIPS" },
324 {"Windows NT Alpha_AXP", "W32ALPHA" },
325 {"Windows NT PowerPC", "W32PPC" },
331 DEBUG(107,("Getting architecture dependant directory\n"));
334 } while ( (archi_table[i].long_archi!=NULL ) &&
335 StrCaseCmp(long_archi, archi_table[i].long_archi) );
337 if (archi_table[i].long_archi==NULL) {
338 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
342 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
344 DEBUGADD(108,("index: [%d]\n", i));
345 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
346 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
351 /****************************************************************************
352 Determine the correct cVersion associated with an architecture and driver
353 ****************************************************************************/
354 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
355 struct current_user *user, uint32 *perr)
361 char buf[PE_HEADER_SIZE];
366 files_struct *fsp = NULL;
370 connection_struct *conn;
374 /* If architecture is Windows 95/98, the version is always 0. */
375 if (strcmp(architecture, "WIN40") == 0) {
376 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
381 pass = getpwuid(user->uid);
383 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
384 (unsigned int)user->uid ));
386 *perr = ERROR_ACCESS_DENIED;
391 /* connect to the print$ share under the same account as the user connected
393 fstrcpy(user_name, pass->pw_name );
394 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
396 /* Null password is ok - we are already an authenticated user... */
398 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
401 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
402 *perr = (uint32)ecode;
406 /* Save who we are - we are temporarily becoming the connection user. */
409 if (!become_user(conn, conn->vuid)) {
410 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
411 *perr = ERROR_ACCESS_DENIED;
416 /* Open the driver file (Portable Executable format) and determine the
417 * deriver the cversion. */
418 slprintf(driverpath, sizeof(driverpath), "%s/%s", architecture, driverpath_in);
420 unix_convert(driverpath,conn,NULL,&bad_path,&st);
422 fsp = open_file_shared(conn, driverpath, &st,
423 SET_OPEN_MODE(DOS_OPEN_RDONLY),
424 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
425 0, 0, &access_mode, &action);
427 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
429 *perr = ERROR_ACCESS_DENIED;
433 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
434 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
435 driverpath, byte_count));
436 *perr = NT_STATUS_FILE_INVALID;
440 /* Is this really a DOS header? */
441 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
442 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
443 driverpath, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
444 *perr = NT_STATUS_FILE_INVALID;
448 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
449 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
450 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
452 *perr = NT_STATUS_FILE_INVALID;
456 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
457 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
458 driverpath, byte_count));
459 *perr = NT_STATUS_FILE_INVALID;
463 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
464 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
465 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) == PE_HEADER_MACHINE_I386) {
467 switch (SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)) {
468 case 4: cversion = 2; break; /* Win NT 4 */
469 case 5: cversion = 3; break; /* Win 2000 */
471 DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
472 driverpath, SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)));
473 *perr = NT_STATUS_FILE_INVALID;
477 DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
478 driverpath, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
479 *perr = NT_STATUS_FILE_INVALID;
483 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
484 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) == NE_HEADER_TARGOS_WIN ) {
486 switch (CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)) {
487 case 3: cversion = 0; break; /* Win 3.x / Win 9x / Win ME */
488 /* case ?: cversion = 1; break;*/ /* Win NT 3.51 ... needs research JRR */
490 DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
491 driverpath, CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)));
492 *perr = NT_STATUS_FILE_INVALID;
496 DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
497 driverpath, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
498 *perr = NT_STATUS_FILE_INVALID;
503 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
504 driverpath, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
505 *perr = NT_STATUS_FILE_INVALID;
509 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
510 driverpath, cversion));
512 fsp->conn->vfs_ops.close(fsp, fsp->fd);
514 close_cnum(conn, user->vuid);
522 fsp->conn->vfs_ops.close(fsp, fsp->fd);
526 close_cnum(conn, user->vuid);
531 /****************************************************************************
532 ****************************************************************************/
533 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
534 struct current_user *user)
536 fstring architecture;
542 /* clean up the driver name.
543 * we can get .\driver.dll
544 * or worse c:\windows\system\driver.dll !
546 /* using an intermediate string to not have overlaping memcpy()'s */
547 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
548 fstrcpy(new_name, p+1);
549 fstrcpy(driver->driverpath, new_name);
552 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
553 fstrcpy(new_name, p+1);
554 fstrcpy(driver->datafile, new_name);
557 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
558 fstrcpy(new_name, p+1);
559 fstrcpy(driver->configfile, new_name);
562 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
563 fstrcpy(new_name, p+1);
564 fstrcpy(driver->helpfile, new_name);
567 if (driver->dependentfiles) {
568 for (i=0; *driver->dependentfiles[i]; i++) {
569 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
570 fstrcpy(new_name, p+1);
571 fstrcpy(driver->dependentfiles[i], new_name);
576 get_short_archi(architecture, driver->environment);
578 /* jfm:7/16/2000 the client always sends the cversion=0.
579 * The server should check which version the driver is by reading
580 * the PE header of driver->driverpath.
582 * For Windows 95/98 the version is 0 (so the value sent is correct)
583 * For Windows NT (the architecture doesn't matter)
585 * NT 3.5/3.51: cversion=1
589 if ((driver->cversion = get_correct_cversion( architecture,
590 driver->driverpath, user, &err)) == -1)
593 return NT_STATUS_NO_PROBLEMO;
596 /****************************************************************************
597 ****************************************************************************/
598 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
599 struct current_user *user)
601 fstring architecture;
607 /* clean up the driver name.
608 * we can get .\driver.dll
609 * or worse c:\windows\system\driver.dll !
611 /* using an intermediate string to not have overlaping memcpy()'s */
612 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
613 fstrcpy(new_name, p+1);
614 fstrcpy(driver->driverpath, new_name);
617 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
618 fstrcpy(new_name, p+1);
619 fstrcpy(driver->datafile, new_name);
622 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
623 fstrcpy(new_name, p+1);
624 fstrcpy(driver->configfile, new_name);
627 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
628 fstrcpy(new_name, p+1);
629 fstrcpy(driver->helpfile, new_name);
632 if (driver->dependentfiles) {
633 for (i=0; *driver->dependentfiles[i]; i++) {
634 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
635 fstrcpy(new_name, p+1);
636 fstrcpy(driver->dependentfiles[i], new_name);
641 get_short_archi(architecture, driver->environment);
643 /* jfm:7/16/2000 the client always sends the cversion=0.
644 * The server should check which version the driver is by reading
645 * the PE header of driver->driverpath.
647 * For Windows 95/98 the version is 0 (so the value sent is correct)
648 * For Windows NT (the architecture doesn't matter)
650 * NT 3.5/3.51: cversion=1
654 if ((driver->version = get_correct_cversion(architecture,
655 driver->driverpath, user, &err)) == -1)
658 return NT_STATUS_NO_PROBLEMO;
661 /****************************************************************************
662 ****************************************************************************/
663 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
664 uint32 level, struct current_user *user)
669 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
670 driver=driver_abstract.info_3;
671 return clean_up_driver_struct_level_3(driver, user);
675 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
676 driver=driver_abstract.info_6;
677 return clean_up_driver_struct_level_6(driver, user);
680 return ERROR_INVALID_PARAMETER;
684 /****************************************************************************
685 This function sucks and should be replaced. JRA.
686 ****************************************************************************/
688 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
690 dst->cversion = src->version;
692 fstrcpy( dst->name, src->name);
693 fstrcpy( dst->environment, src->environment);
694 fstrcpy( dst->driverpath, src->driverpath);
695 fstrcpy( dst->datafile, src->datafile);
696 fstrcpy( dst->configfile, src->configfile);
697 fstrcpy( dst->helpfile, src->helpfile);
698 fstrcpy( dst->monitorname, src->monitorname);
699 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
700 dst->dependentfiles = src->dependentfiles;
703 #if 0 /* Debugging function */
705 static char* ffmt(unsigned char *c){
707 static char ffmt_str[17];
709 for (i=0; i<16; i++) {
710 if ((c[i] < ' ') || (c[i] > '~'))
721 /****************************************************************************
722 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
723 There are two case to be covered here: PE (Portable Executable) and NE (New
724 Executable) files. Both files support the same INFO structure, but PE files
725 store the signature in unicode, and NE files store it as !unicode.
726 ****************************************************************************/
727 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
734 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
735 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
736 fname, PE_HEADER_SIZE));
740 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
741 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
742 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
744 goto no_version_info;
747 /* Is this really a DOS header? */
748 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
749 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
750 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
751 goto no_version_info;
754 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
755 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
756 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
758 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
759 goto no_version_info;
762 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
763 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
765 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
766 goto no_version_info;
769 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
770 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
772 int section_table_bytes;
774 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
775 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
776 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
777 /* At this point, we assume the file is in error. It still could be somthing
778 * else besides a PE file, but it unlikely at this point.
783 /* get the section table */
784 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
785 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
787 if ((buf=malloc(section_table_bytes)) == NULL) {
788 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
789 fname, section_table_bytes));
793 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
794 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
799 /* Iterate the section table looking for the resource section ".rsrc" */
800 for (i = 0; i < num_sections; i++) {
801 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
803 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
804 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
805 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
808 if ((buf=malloc(section_bytes)) == NULL) {
809 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
810 fname, section_bytes));
814 /* Seek to the start of the .rsrc section info */
815 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
816 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
821 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
822 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
827 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
828 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
829 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
830 /* Align to next long address */
831 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
833 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
834 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
835 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
837 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
838 fname, *major, *minor,
839 (*major>>16)&0xffff, *major&0xffff,
840 (*minor>>16)&0xffff, *minor&0xffff));
849 /* Version info not found, fall back to origin date/time */
850 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
854 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
855 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
856 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
857 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
858 /* At this point, we assume the file is in error. It still could be somthing
859 * else besides a NE file, but it unlikely at this point. */
863 /* Allocate a bit more space to speed up things */
865 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
866 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
867 fname, PE_HEADER_SIZE));
871 /* This is a HACK! I got tired of trying to sort through the messy
872 * 'NE' file format. If anyone wants to clean this up please have at
873 * it, but this works. 'NE' files will eventually fade away. JRR */
874 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
875 /* Cover case that should not occur in a well formed 'NE' .dll file */
876 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
878 for(i=0; i<byte_count; i++) {
879 /* Fast skip past data that can't possibly match */
880 if (buf[i] != 'V') continue;
882 /* Potential match data crosses buf boundry, move it to beginning
883 * of buf, and fill the buf with as much as it will hold. */
884 if (i>byte_count-VS_VERSION_INFO_SIZE) {
887 memcpy(buf, &buf[i], byte_count-i);
888 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
889 (byte_count-i))) < 0) {
891 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
896 byte_count = bc + (byte_count - i);
897 if (byte_count<VS_VERSION_INFO_SIZE) break;
902 /* Check that the full signature string and the magic number that
903 * follows exist (not a perfect solution, but the chances that this
904 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
905 * twice, as it is simpler to read the code. */
906 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
907 /* Compute skip alignment to next long address */
908 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
909 sizeof(VS_SIGNATURE)) & 3;
910 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
912 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
913 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
914 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
915 fname, *major, *minor,
916 (*major>>16)&0xffff, *major&0xffff,
917 (*minor>>16)&0xffff, *minor&0xffff));
924 /* Version info not found, fall back to origin date/time */
925 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
930 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
931 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
932 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
943 /****************************************************************************
944 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
945 share one or more files. During the MS installation process files are checked
946 to insure that only a newer version of a shared file is installed over an
947 older version. There are several possibilities for this comparison. If there
948 is no previous version, the new one is newer (obviously). If either file is
949 missing the version info structure, compare the creation date (on Unix use
950 the modification date). Otherwise chose the numerically larger version number.
951 ****************************************************************************/
952 static int file_version_is_newer(connection_struct *conn, fstring new_file,
955 BOOL use_version = True;
960 time_t new_create_time;
964 time_t old_create_time;
968 files_struct *fsp = NULL;
970 SMB_STRUCT_STAT stat_buf;
974 ZERO_STRUCT(stat_buf);
975 new_create_time = (time_t)0;
976 old_create_time = (time_t)0;
978 /* Get file version info (if available) for previous file (if it exists) */
979 pstrcpy(filepath, old_file);
981 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
983 fsp = open_file_shared(conn, filepath, &stat_buf,
984 SET_OPEN_MODE(DOS_OPEN_RDONLY),
985 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
986 0, 0, &access_mode, &action);
988 /* Old file not found, so by definition new file is in fact newer */
989 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
994 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
995 if (ret == -1) goto error_exit;
998 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1000 use_version = False;
1001 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1002 old_create_time = st.st_mtime;
1003 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1006 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1010 /* Get file version info (if available) for new file */
1011 pstrcpy(filepath, new_file);
1012 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1014 fsp = open_file_shared(conn, filepath, &stat_buf,
1015 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1016 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1017 0, 0, &access_mode, &action);
1019 /* New file not found, this shouldn't occur if the caller did its job */
1020 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1025 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1026 if (ret == -1) goto error_exit;
1029 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1031 use_version = False;
1032 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1033 new_create_time = st.st_mtime;
1034 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1037 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1041 /* Compare versions and choose the larger version number */
1042 if (new_major > old_major ||
1043 (new_major == old_major && new_minor > old_minor)) {
1045 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1049 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1054 /* Compare modification time/dates and choose the newest time/date */
1055 if (new_create_time > old_create_time) {
1056 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1060 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1069 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1074 /****************************************************************************
1075 ****************************************************************************/
1076 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1078 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1079 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1080 fstring architecture;
1086 connection_struct *conn;
1089 struct passwd *pass;
1096 memset(inbuf, '\0', sizeof(inbuf));
1097 memset(outbuf, '\0', sizeof(outbuf));
1100 driver=driver_abstract.info_3;
1101 else if (level==6) {
1102 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1103 driver = &converted_driver;
1105 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1109 get_short_archi(architecture, driver->environment);
1112 pass = getpwuid(user->uid);
1114 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1115 (unsigned int)user->uid ));
1121 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1122 fstrcpy(user_name, pass->pw_name );
1123 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1125 /* Null password is ok - we are already an authenticated user... */
1127 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1130 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1131 *perr = (uint32)ecode;
1136 * Save who we are - we are temporarily becoming the connection user.
1141 if (!become_user(conn, conn->vuid)) {
1142 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1148 * make the directories version and version\driver_name
1149 * under the architecture directory.
1151 DEBUG(5,("Creating first directory\n"));
1152 slprintf(new_dir, sizeof(new_dir), "%s/%d", architecture, driver->cversion);
1153 mkdir_internal(conn, inbuf, outbuf, new_dir);
1155 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1156 * listed for this driver which has already been moved, skip it (note:
1157 * drivers may list the same file name several times. Then check if the
1158 * file already exists in archi\cversion\, if so, check that the version
1159 * info (or time stamps if version info is unavailable) is newer (or the
1160 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1161 * Otherwise, delete the file.
1163 * If a file is not moved to archi\cversion\ because of an error, all the
1164 * rest of the 'unmoved' driver files are removed from archi\. If one or
1165 * more of the driver's files was already moved to archi\cversion\, it
1166 * potentially leaves the driver in a partially updated state. Version
1167 * trauma will most likely occur if an client attempts to use any printer
1168 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1169 * done is appropriate... later JRR
1172 DEBUG(5,("Moving files now !\n"));
1174 if (driver->driverpath && strlen(driver->driverpath)) {
1175 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->driverpath);
1176 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->driverpath);
1177 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1178 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1179 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1180 new_name, old_name));
1181 *perr = (uint32)SVAL(outbuf,smb_err);
1182 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1187 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1190 if (driver->datafile && strlen(driver->datafile)) {
1191 if (!strequal(driver->datafile, driver->driverpath)) {
1192 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->datafile);
1193 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->datafile);
1194 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1195 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1196 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1197 new_name, old_name));
1198 *perr = (uint32)SVAL(outbuf,smb_err);
1199 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1204 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1208 if (driver->configfile && strlen(driver->configfile)) {
1209 if (!strequal(driver->configfile, driver->driverpath) &&
1210 !strequal(driver->configfile, driver->datafile)) {
1211 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->configfile);
1212 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->configfile);
1213 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1214 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1215 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1216 new_name, old_name));
1217 *perr = (uint32)SVAL(outbuf,smb_err);
1218 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1223 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1227 if (driver->helpfile && strlen(driver->helpfile)) {
1228 if (!strequal(driver->helpfile, driver->driverpath) &&
1229 !strequal(driver->helpfile, driver->datafile) &&
1230 !strequal(driver->helpfile, driver->configfile)) {
1231 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->helpfile);
1232 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->helpfile);
1233 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1234 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1235 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1236 new_name, old_name));
1237 *perr = (uint32)SVAL(outbuf,smb_err);
1238 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1243 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1247 if (driver->dependentfiles) {
1248 for (i=0; *driver->dependentfiles[i]; i++) {
1249 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1250 !strequal(driver->dependentfiles[i], driver->datafile) &&
1251 !strequal(driver->dependentfiles[i], driver->configfile) &&
1252 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1254 for (j=0; j < i; j++) {
1255 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1260 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->dependentfiles[i]);
1261 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->dependentfiles[i]);
1262 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1263 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1264 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1265 new_name, old_name));
1266 *perr = (uint32)SVAL(outbuf,smb_err);
1267 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1272 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1278 close_cnum(conn, user->vuid);
1281 return ver == -1 ? False : True;
1284 /****************************************************************************
1285 ****************************************************************************/
1286 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1289 fstring architecture;
1295 TDB_DATA kbuf, dbuf;
1297 get_short_archi(architecture, driver->environment);
1299 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1300 * \\server is added in the rpc server layer.
1301 * It does make sense to NOT store the server's name in the printer TDB.
1304 slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
1306 /* .inf files do not always list a file for each of the four standard files.
1307 * Don't prepend a path to a null filename, or client claims:
1308 * "The server on which the printer resides does not have a suitable
1309 * <printer driver name> printer driver installed. Click OK if you
1310 * wish to install the driver on your local machine."
1312 if (strlen(driver->driverpath)) {
1313 fstrcpy(temp_name, driver->driverpath);
1314 slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
1317 if (strlen(driver->datafile)) {
1318 fstrcpy(temp_name, driver->datafile);
1319 slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
1322 if (strlen(driver->configfile)) {
1323 fstrcpy(temp_name, driver->configfile);
1324 slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
1327 if (strlen(driver->helpfile)) {
1328 fstrcpy(temp_name, driver->helpfile);
1329 slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
1332 if (driver->dependentfiles) {
1333 for (i=0; *driver->dependentfiles[i]; i++) {
1334 fstrcpy(temp_name, driver->dependentfiles[i]);
1335 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
1339 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1340 dos_to_unix(key, True); /* Convert key to unix-codepage */
1342 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1349 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1352 driver->environment,
1357 driver->monitorname,
1358 driver->defaultdatatype);
1360 if (driver->dependentfiles) {
1361 for (i=0; *driver->dependentfiles[i]; i++) {
1362 len += tdb_pack(buf+len, buflen-len, "f",
1363 driver->dependentfiles[i]);
1367 if (len != buflen) {
1368 buf = (char *)Realloc(buf, len);
1375 kbuf.dsize = strlen(key)+1;
1379 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1382 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1388 /****************************************************************************
1389 ****************************************************************************/
1390 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1392 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1395 info3.cversion = driver->version;
1396 fstrcpy(info3.name,driver->name);
1397 fstrcpy(info3.environment,driver->environment);
1398 fstrcpy(info3.driverpath,driver->driverpath);
1399 fstrcpy(info3.datafile,driver->datafile);
1400 fstrcpy(info3.configfile,driver->configfile);
1401 fstrcpy(info3.helpfile,driver->helpfile);
1402 fstrcpy(info3.monitorname,driver->monitorname);
1403 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1404 info3.dependentfiles = driver->dependentfiles;
1406 return add_a_printer_driver_3(&info3);
1410 /****************************************************************************
1411 ****************************************************************************/
1412 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1414 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1418 fstrcpy(info.name, in_prt);
1419 fstrcpy(info.defaultdatatype, "RAW");
1421 fstrcpy(info.driverpath, "");
1422 fstrcpy(info.datafile, "");
1423 fstrcpy(info.configfile, "");
1424 fstrcpy(info.helpfile, "");
1426 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1427 return ERROR_NOT_ENOUGH_MEMORY;
1429 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1430 fstrcpy(info.dependentfiles[0], "");
1432 *info_ptr = memdup(&info, sizeof(info));
1437 /****************************************************************************
1438 ****************************************************************************/
1439 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1441 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1442 TDB_DATA kbuf, dbuf;
1443 fstring architecture;
1448 ZERO_STRUCT(driver);
1450 get_short_archi(architecture, in_arch);
1452 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1454 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1457 kbuf.dsize = strlen(key)+1;
1459 dbuf = tdb_fetch(tdb, kbuf);
1461 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1463 if (!dbuf.dptr) return 5;
1465 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1474 driver.defaultdatatype);
1477 while (len < dbuf.dsize) {
1478 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
1479 sizeof(fstring)*(i+2));
1480 if (driver.dependentfiles == NULL)
1483 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1484 &driver.dependentfiles[i]);
1487 if (driver.dependentfiles != NULL)
1488 fstrcpy(driver.dependentfiles[i], "");
1490 safe_free(dbuf.dptr);
1492 if (len != dbuf.dsize) {
1493 if (driver.dependentfiles != NULL)
1494 safe_free(driver.dependentfiles);
1496 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1499 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1504 /****************************************************************************
1505 ****************************************************************************/
1506 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1508 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1514 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1515 DEBUG(10,("driver key: [%s]\n", key));
1518 kbuf.dsize = strlen(key)+1;
1519 if (!tdb_exists(tdb, kbuf)) return False;
1522 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1524 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1525 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1526 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1527 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1528 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1529 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1530 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1532 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1533 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1534 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1536 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1537 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1538 pstrcat(line, info3->configfile);
1540 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1541 pstrcat(line, info3->datafile);
1543 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1544 pstrcat(line, info3->helpfile);
1546 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1547 pstrcat(line, info3->monitorname);
1549 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1552 for (i=0; info3->dependentfiles &&
1553 *info3->dependentfiles[i]; i++) {
1554 if (i) pstrcat(line, ","); /* don't end in a "," */
1555 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1556 pstrcat(line, info3->dependentfiles[i]);
1564 /****************************************************************************
1565 debugging function, dump at level 6 the struct in the logs
1566 ****************************************************************************/
1567 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1570 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1573 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1579 if (driver.info_3 == NULL)
1582 info3=driver.info_3;
1584 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1585 DEBUGADD(106,("name:[%s]\n", info3->name));
1586 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1587 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1588 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1589 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1590 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1591 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1592 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1594 for (i=0; info3->dependentfiles &&
1595 *info3->dependentfiles[i]; i++) {
1596 DEBUGADD(106,("dependentfile:[%s]\n",
1597 info3->dependentfiles[i]));
1604 DEBUGADD(1,("Level not implemented\n"));
1612 /****************************************************************************
1613 ****************************************************************************/
1614 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1618 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1620 if (!nt_devmode) return len;
1622 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1623 nt_devmode->devicename,
1624 nt_devmode->formname,
1626 nt_devmode->specversion,
1627 nt_devmode->driverversion,
1629 nt_devmode->driverextra,
1630 nt_devmode->orientation,
1631 nt_devmode->papersize,
1632 nt_devmode->paperlength,
1633 nt_devmode->paperwidth,
1636 nt_devmode->defaultsource,
1637 nt_devmode->printquality,
1640 nt_devmode->yresolution,
1641 nt_devmode->ttoption,
1642 nt_devmode->collate,
1643 nt_devmode->logpixels,
1646 nt_devmode->bitsperpel,
1647 nt_devmode->pelswidth,
1648 nt_devmode->pelsheight,
1649 nt_devmode->displayflags,
1650 nt_devmode->displayfrequency,
1651 nt_devmode->icmmethod,
1652 nt_devmode->icmintent,
1653 nt_devmode->mediatype,
1654 nt_devmode->dithertype,
1655 nt_devmode->reserved1,
1656 nt_devmode->reserved2,
1657 nt_devmode->panningwidth,
1658 nt_devmode->panningheight,
1659 nt_devmode->private);
1662 if (nt_devmode->private) {
1663 len += tdb_pack(buf+len, buflen-len, "B",
1664 nt_devmode->driverextra,
1665 nt_devmode->private);
1668 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1673 /****************************************************************************
1674 ****************************************************************************/
1675 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1679 while (param != NULL) {
1680 len += tdb_pack(buf+len, buflen-len, "pfdB",
1689 len += tdb_pack(buf+len, buflen-len, "p", param);
1695 /****************************************************************************
1696 delete a printer - this just deletes the printer info file, any open
1697 handles are not affected
1698 ****************************************************************************/
1699 uint32 del_a_printer(char *sharename)
1704 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
1705 dos_to_unix(key, True); /* Convert key to unix-codepage */
1708 kbuf.dsize=strlen(key)+1;
1710 tdb_delete(tdb, kbuf);
1714 /****************************************************************************
1715 ****************************************************************************/
1716 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1720 int buflen, len, ret;
1721 TDB_DATA kbuf, dbuf;
1724 * in addprinter: no servername and the printer is the name
1725 * in setprinter: servername is \\server
1726 * and printer is \\server\\printer
1728 * Samba manages only local printers.
1729 * we currently don't support things like path=\\other_server\printer
1732 if (info->servername[0]!='\0') {
1733 trim_string(info->printername, info->servername, NULL);
1734 trim_string(info->printername, "\\", NULL);
1735 info->servername[0]='\0';
1739 * JFM: one day I'll forget.
1740 * below that's info->portname because that's the SAMBA sharename
1741 * and I made NT 'thinks' it's the portname
1742 * the info->sharename is the thing you can name when you add a printer
1743 * that's the short-name when you create shared printer for 95/98
1744 * So I've made a limitation in SAMBA: you can only have 1 printer model
1745 * behind a SAMBA share.
1753 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1756 info->default_priority,
1773 info->printprocessor,
1777 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1778 len += pack_specifics(info->specific, buf+len, buflen-len);
1780 if (buflen != len) {
1781 buf = (char *)Realloc(buf, len);
1787 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, info->sharename);
1788 dos_to_unix(key, True); /* Convert key to unix-codepage */
1791 kbuf.dsize = strlen(key)+1;
1795 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1798 DEBUG(8, ("error updating printer to tdb on disk\n"));
1802 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1803 info->sharename, info->drivername, info->portname, len));
1809 /****************************************************************************
1810 ****************************************************************************/
1811 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1813 NT_PRINTER_PARAM *current;
1815 DEBUG(108,("add_a_specific_param\n"));
1817 (*param)->next=NULL;
1819 if (info_2->specific == NULL)
1821 info_2->specific=*param;
1825 current=info_2->specific;
1826 while (current->next != NULL) {
1827 current=current->next;
1829 current->next=*param;
1835 /****************************************************************************
1836 ****************************************************************************/
1837 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1839 NT_PRINTER_PARAM *current;
1840 NT_PRINTER_PARAM *previous;
1842 current=info_2->specific;
1845 if (current==NULL) return (False);
1847 if ( !strcmp(current->value, param->value) &&
1848 (strlen(current->value)==strlen(param->value)) ) {
1849 DEBUG(109,("deleting first value\n"));
1850 info_2->specific=current->next;
1851 safe_free(current->data);
1853 DEBUG(109,("deleted first value\n"));
1857 current=previous->next;
1859 while ( current!=NULL ) {
1860 if (!strcmp(current->value, param->value) &&
1861 strlen(current->value)==strlen(param->value) ) {
1862 DEBUG(109,("deleting current value\n"));
1863 previous->next=current->next;
1864 safe_free(current->data);
1866 DEBUG(109,("deleted current value\n"));
1870 previous=previous->next;
1871 current=current->next;
1876 /****************************************************************************
1877 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
1878 ****************************************************************************/
1879 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
1881 NT_PRINTER_PARAM *param = *param_ptr;
1886 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
1889 safe_free(param->data);
1895 /****************************************************************************
1896 Malloc and return an NT devicemode.
1897 ****************************************************************************/
1899 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
1902 * should I init this ones ???
1903 nt_devmode->devicename
1907 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
1909 if (nt_devmode == NULL) {
1910 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
1914 ZERO_STRUCTP(nt_devmode);
1916 safe_strcpy(adevice, default_devicename, sizeof(adevice));
1917 fstrcpy(nt_devmode->devicename, adevice);
1919 fstrcpy(nt_devmode->formname, "Letter");
1921 nt_devmode->specversion = 0x0401;
1922 nt_devmode->driverversion = 0x0400;
1923 nt_devmode->size = 0x00DC;
1924 nt_devmode->driverextra = 0x0000;
1925 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
1926 DEFAULTSOURCE | COPIES | SCALE |
1927 PAPERSIZE | ORIENTATION;
1928 nt_devmode->orientation = 1;
1929 nt_devmode->papersize = PAPER_LETTER;
1930 nt_devmode->paperlength = 0;
1931 nt_devmode->paperwidth = 0;
1932 nt_devmode->scale = 0x64;
1933 nt_devmode->copies = 01;
1934 nt_devmode->defaultsource = BIN_FORMSOURCE;
1935 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
1936 nt_devmode->color = COLOR_MONOCHROME;
1937 nt_devmode->duplex = DUP_SIMPLEX;
1938 nt_devmode->yresolution = 0;
1939 nt_devmode->ttoption = TT_SUBDEV;
1940 nt_devmode->collate = COLLATE_FALSE;
1941 nt_devmode->icmmethod = 0;
1942 nt_devmode->icmintent = 0;
1943 nt_devmode->mediatype = 0;
1944 nt_devmode->dithertype = 0;
1946 /* non utilisés par un driver d'imprimante */
1947 nt_devmode->logpixels = 0;
1948 nt_devmode->bitsperpel = 0;
1949 nt_devmode->pelswidth = 0;
1950 nt_devmode->pelsheight = 0;
1951 nt_devmode->displayflags = 0;
1952 nt_devmode->displayfrequency = 0;
1953 nt_devmode->reserved1 = 0;
1954 nt_devmode->reserved2 = 0;
1955 nt_devmode->panningwidth = 0;
1956 nt_devmode->panningheight = 0;
1958 nt_devmode->private=NULL;
1963 /****************************************************************************
1964 Deepcopy an NT devicemode.
1965 ****************************************************************************/
1967 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
1969 NT_DEVICEMODE *new_nt_devicemode = NULL;
1971 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
1972 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1976 new_nt_devicemode->private = NULL;
1977 if (nt_devicemode->private != NULL) {
1978 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
1979 safe_free(new_nt_devicemode);
1980 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1985 return new_nt_devicemode;
1988 /****************************************************************************
1989 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
1990 ****************************************************************************/
1992 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
1994 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
1996 if(nt_devmode == NULL)
1999 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2001 if(nt_devmode->private)
2002 safe_free(nt_devmode->private);
2004 safe_free(nt_devmode);
2005 *devmode_ptr = NULL;
2008 /****************************************************************************
2009 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2010 ****************************************************************************/
2011 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2013 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2014 NT_PRINTER_PARAM *param_ptr;
2019 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2021 free_nt_devicemode(&info->devmode);
2022 free_sec_desc_buf(&info->secdesc_buf);
2024 for(param_ptr = info->specific; param_ptr; ) {
2025 NT_PRINTER_PARAM *tofree = param_ptr;
2027 param_ptr = param_ptr->next;
2028 free_nt_printer_param(&tofree);
2031 safe_free(*info_ptr);
2036 /****************************************************************************
2037 ****************************************************************************/
2038 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2042 NT_DEVICEMODE devmode;
2044 ZERO_STRUCT(devmode);
2046 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2048 if (!*nt_devmode) return len;
2050 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2054 &devmode.specversion,
2055 &devmode.driverversion,
2057 &devmode.driverextra,
2058 &devmode.orientation,
2060 &devmode.paperlength,
2061 &devmode.paperwidth,
2064 &devmode.defaultsource,
2065 &devmode.printquality,
2068 &devmode.yresolution,
2074 &devmode.bitsperpel,
2076 &devmode.pelsheight,
2077 &devmode.displayflags,
2078 &devmode.displayfrequency,
2082 &devmode.dithertype,
2085 &devmode.panningwidth,
2086 &devmode.panningheight,
2089 if (devmode.private) {
2090 /* the len in tdb_unpack is an int value and
2091 * devmoce.driverextra is only a short
2093 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2094 devmode.driverextra=(uint16)extra_len;
2096 /* check to catch an invalid TDB entry so we don't segfault */
2097 if (devmode.driverextra == 0) {
2098 devmode.private = NULL;
2102 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2104 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2105 if (devmode.private)
2106 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2111 /****************************************************************************
2112 ****************************************************************************/
2113 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2116 NT_PRINTER_PARAM param, *p;
2121 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2124 len += tdb_unpack(buf+len, buflen-len, "fdB",
2130 *list = memdup(¶m, sizeof(param));
2132 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2139 /****************************************************************************
2140 get a default printer info 2 struct
2141 ****************************************************************************/
2142 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2144 extern pstring global_myname;
2146 NT_PRINTER_INFO_LEVEL_2 info;
2150 snum = lp_servicenumber(sharename);
2152 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2153 slprintf(info.printername, sizeof(info.printername), "\\\\%s\\%s",
2154 global_myname, sharename);
2155 fstrcpy(info.sharename, sharename);
2156 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2157 fstrcpy(info.drivername, lp_printerdriver(snum));
2159 if (!*info.drivername)
2160 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2162 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2164 pstrcpy(info.comment, "");
2165 fstrcpy(info.printprocessor, "winprint");
2166 fstrcpy(info.datatype, "RAW");
2168 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2169 | PRINTER_ATTRIBUTE_LOCAL \
2170 | PRINTER_ATTRIBUTE_RAW_ONLY \
2171 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2173 info.starttime = 0; /* Minutes since 12:00am GMT */
2174 info.untiltime = 0; /* Minutes since 12:00am GMT */
2176 info.default_priority = 1;
2177 info.setuptime = (uint32)time(NULL);
2179 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2182 if (!nt_printing_getsec(sharename, &info.secdesc_buf))
2185 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2187 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2196 free_nt_devicemode(&info.devmode);
2197 if (info.secdesc_buf)
2198 free_sec_desc_buf(&info.secdesc_buf);
2202 /****************************************************************************
2203 ****************************************************************************/
2204 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2207 NT_PRINTER_INFO_LEVEL_2 info;
2209 TDB_DATA kbuf, dbuf;
2210 fstring printername;
2214 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
2215 dos_to_unix(key, True); /* Convert key to unix-codepage */
2218 kbuf.dsize = strlen(key)+1;
2220 dbuf = tdb_fetch(tdb, kbuf);
2222 return get_a_printer_2_default(info_ptr, sharename);
2224 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2227 &info.default_priority,
2244 info.printprocessor,
2248 /* Samba has to have shared raw drivers. */
2249 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2251 /* Restore the stripped strings. */
2252 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2253 slprintf(printername, sizeof(printername), "\\\\%s\\%s", global_myname,
2255 fstrcpy(info.printername, printername);
2257 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2258 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2260 nt_printing_getsec(sharename, &info.secdesc_buf);
2262 safe_free(dbuf.dptr);
2263 *info_ptr=memdup(&info, sizeof(info));
2265 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2266 sharename, info.printername, info.drivername));
2272 /****************************************************************************
2273 debugging function, dump at level 6 the struct in the logs
2274 ****************************************************************************/
2275 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2278 NT_PRINTER_INFO_LEVEL_2 *info2;
2280 DEBUG(106,("Dumping printer at level [%d]\n", level));
2286 if (printer.info_2 == NULL)
2290 info2=printer.info_2;
2292 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2293 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2294 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2295 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2296 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2297 DEBUGADD(106,("status:[%d]\n", info2->status));
2298 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2299 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2300 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2301 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2302 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2304 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2305 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2306 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2307 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2308 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2309 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2310 DEBUGADD(106,("location:[%s]\n", info2->location));
2311 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2312 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2313 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2314 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2320 DEBUGADD(1,("Level not implemented\n"));
2328 /****************************************************************************
2329 Get the parameters we can substitute in an NT print job.
2330 ****************************************************************************/
2332 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2334 NT_PRINTER_INFO_LEVEL *printer = NULL;
2336 **printername = **sharename = **portname = '\0';
2338 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2341 fstrcpy(*printername, printer->info_2->printername);
2342 fstrcpy(*sharename, printer->info_2->sharename);
2343 fstrcpy(*portname, printer->info_2->portname);
2345 free_a_printer(&printer, 2);
2349 * The function below are the high level ones.
2350 * only those ones must be called from the spoolss code.
2354 /****************************************************************************
2355 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2356 ****************************************************************************/
2358 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2362 dump_a_printer(printer, level);
2368 printer.info_2->c_setprinter++;
2369 result=update_a_printer_2(printer.info_2);
2380 /****************************************************************************
2381 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2382 We split this out from mod_a_printer as it updates the id's and timestamps.
2383 ****************************************************************************/
2385 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2389 dump_a_printer(printer, level);
2396 * Update the changestamp.
2397 * Note we must *not* do this in mod_a_printer().
2400 time_t time_unix = time(NULL);
2401 unix_to_nt_time(&time_nt, time_unix);
2402 printer.info_2->changeid=time_nt.low;
2404 printer.info_2->c_setprinter++;
2405 result=update_a_printer_2(printer.info_2);
2416 /****************************************************************************
2417 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2418 ****************************************************************************/
2420 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2423 NT_PRINTER_INFO_LEVEL *printer = NULL;
2427 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
2433 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
2434 DEBUG(0,("get_a_printer: malloc fail.\n"));
2437 ZERO_STRUCTP(printer);
2438 result=get_a_printer_2(&printer->info_2, sharename);
2440 dump_a_printer(*printer, level);
2441 *pp_printer = printer;
2452 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
2457 /****************************************************************************
2458 Deletes a NT_PRINTER_INFO_LEVEL struct.
2459 ****************************************************************************/
2461 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
2464 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
2466 DEBUG(104,("freeing a printer at level [%d]\n", level));
2468 if (printer == NULL)
2475 if (printer->info_2 != NULL)
2477 free_nt_printer_info_level_2(&printer->info_2);
2496 /****************************************************************************
2497 ****************************************************************************/
2498 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2501 DEBUG(104,("adding a printer at level [%d]\n", level));
2502 dump_a_printer_driver(driver, level);
2508 result=add_a_printer_driver_3(driver.info_3);
2514 result=add_a_printer_driver_6(driver.info_6);
2524 /****************************************************************************
2525 ****************************************************************************/
2526 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2527 fstring printername, fstring architecture, uint32 version)
2535 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2544 dump_a_printer_driver(*driver, level);
2548 /****************************************************************************
2549 ****************************************************************************/
2550 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2558 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2559 if (driver.info_3 != NULL)
2561 info3=driver.info_3;
2562 safe_free(info3->dependentfiles);
2563 ZERO_STRUCTP(info3);
2575 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2576 if (driver.info_6 != NULL)
2578 info6=driver.info_6;
2579 safe_free(info6->dependentfiles);
2580 safe_free(info6->previousnames);
2581 ZERO_STRUCTP(info6);
2598 /****************************************************************************
2599 ****************************************************************************/
2600 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2601 fstring value, uint8 **data, uint32 *type, uint32 *len)
2603 /* right now that's enough ! */
2604 NT_PRINTER_PARAM *param;
2607 param=printer.info_2->specific;
2609 while (param != NULL && i < param_index) {
2617 /* exited because it exist */
2619 StrnCpy(value, param->value, sizeof(fstring)-1);
2620 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2623 ZERO_STRUCTP(*data);
2624 memcpy(*data, param->data, param->data_len);
2625 *len=param->data_len;
2629 /****************************************************************************
2630 ****************************************************************************/
2631 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2632 fstring value, uint8 **data, uint32 *type, uint32 *len)
2634 /* right now that's enough ! */
2635 NT_PRINTER_PARAM *param;
2637 DEBUG(105, ("get_specific_param\n"));
2639 param=printer.info_2->specific;
2641 while (param != NULL)
2643 #if 1 /* JRA - I think this should be case insensitive.... */
2644 if ( strequal(value, param->value)
2646 if ( !strcmp(value, param->value)
2648 && strlen(value)==strlen(param->value))
2654 DEBUG(106, ("found one param\n"));
2657 /* exited because it exist */
2660 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2663 memcpy(*data, param->data, param->data_len);
2664 *len=param->data_len;
2666 DEBUG(106, ("exit of get_specific_param:true\n"));
2669 DEBUG(106, ("exit of get_specific_param:false\n"));
2673 /****************************************************************************
2674 Store a security desc for a printer.
2675 ****************************************************************************/
2677 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
2679 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2680 SEC_DESC_BUF *old_secdesc_ctr = NULL;
2682 TALLOC_CTX *mem_ctx = NULL;
2686 mem_ctx = talloc_init();
2687 if (mem_ctx == NULL)
2690 /* The old owner and group sids of the security descriptor are not
2691 present when new ACEs are added or removed by changing printer
2692 permissions through NT. If they are NULL in the new security
2693 descriptor then copy them over from the old one. */
2695 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
2696 DOM_SID *owner_sid, *group_sid;
2697 SEC_ACL *dacl, *sacl;
2698 SEC_DESC *psd = NULL;
2701 nt_printing_getsec(printername, &old_secdesc_ctr);
2703 /* Pick out correct owner and group sids */
2705 owner_sid = secdesc_ctr->sec->owner_sid ?
2706 secdesc_ctr->sec->owner_sid :
2707 old_secdesc_ctr->sec->owner_sid;
2709 group_sid = secdesc_ctr->sec->grp_sid ?
2710 secdesc_ctr->sec->grp_sid :
2711 old_secdesc_ctr->sec->grp_sid;
2713 dacl = secdesc_ctr->sec->dacl ?
2714 secdesc_ctr->sec->dacl :
2715 old_secdesc_ctr->sec->dacl;
2717 sacl = secdesc_ctr->sec->sacl ?
2718 secdesc_ctr->sec->sacl :
2719 old_secdesc_ctr->sec->sacl;
2721 /* Make a deep copy of the security descriptor */
2723 psd = make_sec_desc(secdesc_ctr->sec->revision,
2724 owner_sid, group_sid,
2729 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2731 /* Free up memory */
2733 free_sec_desc(&psd);
2734 free_sec_desc_buf(&old_secdesc_ctr);
2737 if (!new_secdesc_ctr) {
2738 new_secdesc_ctr = secdesc_ctr;
2741 /* Store the security descriptor in a tdb */
2743 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
2744 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
2746 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
2748 status = ERROR_INVALID_FUNCTION;
2752 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2754 if (tdb_prs_store(tdb, key, &ps)==0) {
2757 DEBUG(1,("Failed to store secdesc for %s\n", printername));
2758 status = ERROR_INVALID_FUNCTION;
2761 /* Free mallocated memory */
2764 free_sec_desc_buf(&old_secdesc_ctr);
2766 if (new_secdesc_ctr != secdesc_ctr) {
2767 free_sec_desc_buf(&new_secdesc_ctr);
2772 talloc_destroy(mem_ctx);
2776 /****************************************************************************
2777 Construct a default security descriptor buffer for a printer.
2778 ****************************************************************************/
2780 static SEC_DESC_BUF *construct_default_printer_sdb(void)
2784 SEC_ACL *psa = NULL;
2785 SEC_DESC_BUF *sdb = NULL;
2786 SEC_DESC *psd = NULL;
2789 enum SID_NAME_USE name_type;
2791 /* Create an ACE where Everyone is allowed to print */
2793 init_sec_access(&sa, PRINTER_ACE_PRINT);
2794 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2795 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2797 /* Make the security descriptor owned by the Administrators group
2798 on the PDC of the domain. */
2800 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
2801 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2804 /* Backup plan - make printer owned by admins or root. This should
2805 emulate a lanman printer as security settings can't be
2808 if (!lookup_name( "Printer Administrators", &owner_sid, &name_type) &&
2809 !lookup_name( "Administrators", &owner_sid, &name_type) &&
2810 !lookup_name( "Administrator", &owner_sid, &name_type) &&
2811 !lookup_name("root", &owner_sid, &name_type)) {
2812 sid_copy(&owner_sid, &global_sid_World);
2816 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
2817 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2818 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
2819 SEC_ACE_FLAG_INHERIT_ONLY);
2821 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
2822 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2823 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2825 /* The ACL revision number in rpc_secdesc.h differs from the one
2826 created by NT when setting ACE entries in printer
2827 descriptors. NT4 complains about the property being edited by a
2830 #define NT4_ACL_REVISION 0x2
2832 if ((psa = make_sec_acl(NT4_ACL_REVISION, 3, ace)) != NULL) {
2833 psd = make_sec_desc(SEC_DESC_REVISION,
2835 NULL, psa, &sd_size);
2840 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2844 sdb = make_sec_desc_buf(sd_size, psd);
2846 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2847 (unsigned int)sd_size));
2849 free_sec_desc(&psd);
2853 /****************************************************************************
2854 Get a security desc for a printer.
2855 ****************************************************************************/
2857 BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
2860 TALLOC_CTX *mem_ctx = NULL;
2864 mem_ctx = talloc_init();
2865 if (mem_ctx == NULL)
2868 if ((temp = strchr(printername + 2, '\\'))) {
2869 printername = temp + 1;
2872 /* Fetch security descriptor from tdb */
2874 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2876 if (tdb_prs_fetch(tdb, key, &ps, mem_ctx)!=0 ||
2877 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
2879 DEBUG(4,("using default secdesc for %s\n", printername));
2881 if (!(*secdesc_ctr = construct_default_printer_sdb())) {
2882 talloc_destroy(mem_ctx);
2886 talloc_destroy(mem_ctx);
2890 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2891 this security descriptor has been created when winbindd was
2892 down. Take ownership of security descriptor. */
2894 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
2896 enum SID_NAME_USE name_type;
2898 /* Change sd owner to workgroup administrator */
2900 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
2902 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2903 SEC_DESC *psd = NULL;
2908 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2910 psd = make_sec_desc((*secdesc_ctr)->sec->revision,
2912 (*secdesc_ctr)->sec->grp_sid,
2913 (*secdesc_ctr)->sec->sacl,
2914 (*secdesc_ctr)->sec->dacl,
2917 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2919 free_sec_desc(&psd);
2921 /* Swap with other one */
2923 free_sec_desc_buf(secdesc_ctr);
2924 *secdesc_ctr = new_secdesc_ctr;
2928 nt_printing_setsec(printername, *secdesc_ctr);
2932 if (DEBUGLEVEL >= 10) {
2933 SEC_ACL *acl = (*secdesc_ctr)->sec->dacl;
2936 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
2937 printername, acl->num_aces));
2939 for (i = 0; i < acl->num_aces; i++) {
2942 sid_to_string(sid_str, &acl->ace[i].sid);
2944 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
2945 acl->ace[i].type, acl->ace[i].flags,
2946 acl->ace[i].info.mask));
2951 talloc_destroy(mem_ctx);
2957 1: level not implemented
2958 2: file doesn't exist
2959 3: can't allocate memory
2960 4: can't free memory
2961 5: non existant struct
2965 A printer and a printer driver are 2 different things.
2966 NT manages them separatelly, Samba does the same.
2967 Why ? Simply because it's easier and it makes sense !
2969 Now explanation: You have 3 printers behind your samba server,
2970 2 of them are the same make and model (laser A and B). But laser B
2971 has an 3000 sheet feeder and laser A doesn't such an option.
2972 Your third printer is an old dot-matrix model for the accounting :-).
2974 If the /usr/local/samba/lib directory (default dir), you will have
2975 5 files to describe all of this.
2977 3 files for the printers (1 by printer):
2980 NTprinter_accounting
2981 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2982 NTdriver_printer model X
2983 NTdriver_printer model Y
2985 jfm: I should use this comment for the text file to explain
2986 same thing for the forms BTW.
2987 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2991 /* Convert generic access rights to printer object specific access rights.
2992 It turns out that NT4 security descriptors use generic access rights and
2993 NT5 the object specific ones. */
2995 void map_printer_permissions(SEC_DESC *sd)
2999 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
3000 se_map_generic(&sd->dacl->ace[i].info.mask,
3001 &printer_generic_mapping);
3005 /****************************************************************************
3006 Check a user has permissions to perform the given operation. We use some
3007 constants defined in include/rpc_spoolss.h that look relevant to check
3008 the various actions we perform when checking printer access.
3010 PRINTER_ACCESS_ADMINISTER:
3011 print_queue_pause, print_queue_resume, update_printer_sec,
3012 update_printer, spoolss_addprinterex_level_2,
3013 _spoolss_setprinterdata
3018 PRINTER_ACCESS_ADMINISTER (should really be JOB_ACCESS_ADMINISTER):
3019 print_job_delete, print_job_pause, print_job_resume,
3022 ****************************************************************************/
3023 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3025 SEC_DESC_BUF *secdesc = NULL;
3026 uint32 access_granted, status;
3029 extern struct current_user current_user;
3031 /* If user is NULL then use the current_user structure */
3033 if (!user) user = ¤t_user;
3035 /* Always allow root or printer admins to do anything */
3037 if (user->uid == 0 ||
3038 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3042 /* Get printer name */
3044 pname = PRINTERNAME(snum);
3046 if (!pname || !*pname)
3047 pname = SERVICE(snum);
3049 if (!pname || !*pname) {
3054 /* Get printer security descriptor */
3056 nt_printing_getsec(pname, &secdesc);
3058 map_printer_permissions(secdesc->sec);
3060 result = se_access_check(secdesc->sec, user, access_type,
3061 &access_granted, &status);
3065 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3067 /* Free mallocated memory */
3069 free_sec_desc_buf(&secdesc);
3077 /****************************************************************************
3078 Check the time parameters allow a print operation.
3079 *****************************************************************************/
3081 BOOL print_time_access_check(int snum)
3083 NT_PRINTER_INFO_LEVEL *printer = NULL;
3085 time_t now = time(NULL);
3089 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3092 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3096 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3098 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3101 free_a_printer(&printer, 2);