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 kbuf.dsize = strlen(key)+1;
151 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) break;
157 /****************************************************************************
158 add a form struct at the end of the list
159 ****************************************************************************/
160 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
167 * NT tries to add forms even when
168 * they are already in the base
169 * only update the values if already present
174 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
175 for (n=0; n<*count; n++) {
176 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
177 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
184 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
186 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
190 (*list)[n].flag=form->flags;
191 (*list)[n].width=form->size_x;
192 (*list)[n].length=form->size_y;
193 (*list)[n].left=form->left;
194 (*list)[n].top=form->top;
195 (*list)[n].right=form->right;
196 (*list)[n].bottom=form->bottom;
201 /****************************************************************************
202 delete a named form struct
203 ****************************************************************************/
204 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
215 * Don't delete the last form (no empty lists).
216 * CHECKME ! Is this correct ? JRA.
218 *ret = ERROR_INVALID_PARAMETER;
222 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
224 for (n=0; n<*count; n++) {
225 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
226 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
232 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
233 *ret = ERROR_INVALID_PARAMETER;
237 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[n].name);
238 kbuf.dsize = strlen(key)+1;
240 if (tdb_delete(tdb, kbuf) != 0) {
241 *ret = ERROR_NOT_ENOUGH_MEMORY;
248 /****************************************************************************
250 ****************************************************************************/
251 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
255 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
257 DEBUG(106, ("[%s]\n", form_name));
258 for (n=0; n<count; n++)
260 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
261 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
265 if (n==count) return;
267 (*list)[n].flag=form->flags;
268 (*list)[n].width=form->size_x;
269 (*list)[n].length=form->size_y;
270 (*list)[n].left=form->left;
271 (*list)[n].top=form->top;
272 (*list)[n].right=form->right;
273 (*list)[n].bottom=form->bottom;
276 /****************************************************************************
277 get the nt drivers list
279 traverse the database and look-up the matching names
280 ****************************************************************************/
281 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
286 TDB_DATA kbuf, newkey;
288 get_short_archi(short_archi, architecture);
289 slprintf(key, sizeof(key), "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
291 for (kbuf = tdb_firstkey(tdb);
293 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
294 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
296 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
299 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
306 /****************************************************************************
307 function to do the mapping between the long architecture name and
309 ****************************************************************************/
310 BOOL get_short_archi(char *short_archi, char *long_archi)
317 struct table archi_table[]=
319 {"Windows 4.0", "WIN40" },
320 {"Windows NT x86", "W32X86" },
321 {"Windows NT R4000", "W32MIPS" },
322 {"Windows NT Alpha_AXP", "W32ALPHA" },
323 {"Windows NT PowerPC", "W32PPC" },
329 DEBUG(107,("Getting architecture dependant directory\n"));
332 } while ( (archi_table[i].long_archi!=NULL ) &&
333 StrCaseCmp(long_archi, archi_table[i].long_archi) );
335 if (archi_table[i].long_archi==NULL) {
336 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
340 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
342 DEBUGADD(108,("index: [%d]\n", i));
343 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
344 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
349 /****************************************************************************
350 Determine the correct cVersion associated with an architecture and driver
351 ****************************************************************************/
352 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
353 struct current_user *user, uint32 *perr)
359 char buf[PE_HEADER_SIZE];
364 files_struct *fsp = NULL;
368 connection_struct *conn;
372 /* If architecture is Windows 95/98, the version is always 0. */
373 if (strcmp(architecture, "WIN40") == 0) {
374 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
379 pass = getpwuid(user->uid);
381 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
382 (unsigned int)user->uid ));
384 *perr = ERROR_ACCESS_DENIED;
389 /* connect to the print$ share under the same account as the user connected
391 fstrcpy(user_name, pass->pw_name );
392 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
394 /* Null password is ok - we are already an authenticated user... */
396 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
399 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
400 *perr = (uint32)ecode;
404 /* Save who we are - we are temporarily becoming the connection user. */
407 if (!become_user(conn, conn->vuid)) {
408 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
409 *perr = ERROR_ACCESS_DENIED;
414 /* Open the driver file (Portable Executable format) and determine the
415 * deriver the cversion. */
416 slprintf(driverpath, sizeof(driverpath), "%s/%s", architecture, driverpath_in);
418 unix_convert(driverpath,conn,NULL,&bad_path,&st);
420 fsp = open_file_shared(conn, driverpath, &st,
421 SET_OPEN_MODE(DOS_OPEN_RDONLY),
422 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
423 0, 0, &access_mode, &action);
425 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
427 *perr = ERROR_ACCESS_DENIED;
431 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
432 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
433 driverpath, byte_count));
434 *perr = NT_STATUS_FILE_INVALID;
438 /* Is this really a DOS header? */
439 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
440 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
441 driverpath, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
442 *perr = NT_STATUS_FILE_INVALID;
446 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
447 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
448 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
450 *perr = NT_STATUS_FILE_INVALID;
454 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
455 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
456 driverpath, byte_count));
457 *perr = NT_STATUS_FILE_INVALID;
461 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
462 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
463 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) == PE_HEADER_MACHINE_I386) {
465 switch (SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)) {
466 case 4: cversion = 2; break; /* Win NT 4 */
467 case 5: cversion = 3; break; /* Win 2000 */
469 DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
470 driverpath, SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)));
471 *perr = NT_STATUS_FILE_INVALID;
475 DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
476 driverpath, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
477 *perr = NT_STATUS_FILE_INVALID;
481 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
482 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) == NE_HEADER_TARGOS_WIN ) {
484 switch (CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)) {
485 case 3: cversion = 0; break; /* Win 3.x / Win 9x / Win ME */
486 /* case ?: cversion = 1; break;*/ /* Win NT 3.51 ... needs research JRR */
488 DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
489 driverpath, CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)));
490 *perr = NT_STATUS_FILE_INVALID;
494 DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
495 driverpath, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
496 *perr = NT_STATUS_FILE_INVALID;
501 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
502 driverpath, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
503 *perr = NT_STATUS_FILE_INVALID;
507 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
508 driverpath, cversion));
510 fsp->conn->vfs_ops.close(fsp, fsp->fd);
512 close_cnum(conn, user->vuid);
520 fsp->conn->vfs_ops.close(fsp, fsp->fd);
524 close_cnum(conn, user->vuid);
529 /****************************************************************************
530 ****************************************************************************/
531 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
532 struct current_user *user)
534 fstring architecture;
540 /* clean up the driver name.
541 * we can get .\driver.dll
542 * or worse c:\windows\system\driver.dll !
544 /* using an intermediate string to not have overlaping memcpy()'s */
545 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
546 fstrcpy(new_name, p+1);
547 fstrcpy(driver->driverpath, new_name);
550 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
551 fstrcpy(new_name, p+1);
552 fstrcpy(driver->datafile, new_name);
555 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
556 fstrcpy(new_name, p+1);
557 fstrcpy(driver->configfile, new_name);
560 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
561 fstrcpy(new_name, p+1);
562 fstrcpy(driver->helpfile, new_name);
565 if (driver->dependentfiles) {
566 for (i=0; *driver->dependentfiles[i]; i++) {
567 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
568 fstrcpy(new_name, p+1);
569 fstrcpy(driver->dependentfiles[i], new_name);
574 get_short_archi(architecture, driver->environment);
576 /* jfm:7/16/2000 the client always sends the cversion=0.
577 * The server should check which version the driver is by reading
578 * the PE header of driver->driverpath.
580 * For Windows 95/98 the version is 0 (so the value sent is correct)
581 * For Windows NT (the architecture doesn't matter)
583 * NT 3.5/3.51: cversion=1
587 if ((driver->cversion = get_correct_cversion( architecture,
588 driver->driverpath, user, &err)) == -1)
591 return NT_STATUS_NO_PROBLEMO;
594 /****************************************************************************
595 ****************************************************************************/
596 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
597 struct current_user *user)
599 fstring architecture;
605 /* clean up the driver name.
606 * we can get .\driver.dll
607 * or worse c:\windows\system\driver.dll !
609 /* using an intermediate string to not have overlaping memcpy()'s */
610 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
611 fstrcpy(new_name, p+1);
612 fstrcpy(driver->driverpath, new_name);
615 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
616 fstrcpy(new_name, p+1);
617 fstrcpy(driver->datafile, new_name);
620 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
621 fstrcpy(new_name, p+1);
622 fstrcpy(driver->configfile, new_name);
625 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
626 fstrcpy(new_name, p+1);
627 fstrcpy(driver->helpfile, new_name);
630 if (driver->dependentfiles) {
631 for (i=0; *driver->dependentfiles[i]; i++) {
632 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
633 fstrcpy(new_name, p+1);
634 fstrcpy(driver->dependentfiles[i], new_name);
639 get_short_archi(architecture, driver->environment);
641 /* jfm:7/16/2000 the client always sends the cversion=0.
642 * The server should check which version the driver is by reading
643 * the PE header of driver->driverpath.
645 * For Windows 95/98 the version is 0 (so the value sent is correct)
646 * For Windows NT (the architecture doesn't matter)
648 * NT 3.5/3.51: cversion=1
652 if ((driver->version = get_correct_cversion(architecture,
653 driver->driverpath, user, &err)) == -1)
656 return NT_STATUS_NO_PROBLEMO;
659 /****************************************************************************
660 ****************************************************************************/
661 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
662 uint32 level, struct current_user *user)
667 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
668 driver=driver_abstract.info_3;
669 return clean_up_driver_struct_level_3(driver, user);
673 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
674 driver=driver_abstract.info_6;
675 return clean_up_driver_struct_level_6(driver, user);
678 return ERROR_INVALID_PARAMETER;
682 /****************************************************************************
683 This function sucks and should be replaced. JRA.
684 ****************************************************************************/
686 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
688 dst->cversion = src->version;
690 fstrcpy( dst->name, src->name);
691 fstrcpy( dst->environment, src->environment);
692 fstrcpy( dst->driverpath, src->driverpath);
693 fstrcpy( dst->datafile, src->datafile);
694 fstrcpy( dst->configfile, src->configfile);
695 fstrcpy( dst->helpfile, src->helpfile);
696 fstrcpy( dst->monitorname, src->monitorname);
697 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
698 dst->dependentfiles = src->dependentfiles;
701 #if 0 /* Debugging function */
703 static char* ffmt(unsigned char *c){
705 static char ffmt_str[17];
707 for (i=0; i<16; i++) {
708 if ((c[i] < ' ') || (c[i] > '~'))
719 /****************************************************************************
720 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
721 There are two case to be covered here: PE (Portable Executable) and NE (New
722 Executable) files. Both files support the same INFO structure, but PE files
723 store the signature in unicode, and NE files store it as !unicode.
724 ****************************************************************************/
725 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
732 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
733 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
734 fname, PE_HEADER_SIZE));
738 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
739 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
740 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
742 goto no_version_info;
745 /* Is this really a DOS header? */
746 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
747 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
748 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
749 goto no_version_info;
752 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
753 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
754 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
756 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
757 goto no_version_info;
760 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
761 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
763 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
764 goto no_version_info;
767 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
768 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
770 int section_table_bytes;
772 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
773 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
774 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
775 /* At this point, we assume the file is in error. It still could be somthing
776 * else besides a PE file, but it unlikely at this point.
781 /* get the section table */
782 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
783 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
785 if ((buf=malloc(section_table_bytes)) == NULL) {
786 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
787 fname, section_table_bytes));
791 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
792 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
797 /* Iterate the section table looking for the resource section ".rsrc" */
798 for (i = 0; i < num_sections; i++) {
799 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
801 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
802 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
803 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
806 if ((buf=malloc(section_bytes)) == NULL) {
807 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
808 fname, section_bytes));
812 /* Seek to the start of the .rsrc section info */
813 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
814 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
819 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
820 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
825 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
826 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
827 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
828 /* Align to next long address */
829 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
831 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
832 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
833 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
835 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
836 fname, *major, *minor,
837 (*major>>16)&0xffff, *major&0xffff,
838 (*minor>>16)&0xffff, *minor&0xffff));
847 /* Version info not found, fall back to origin date/time */
848 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
852 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
853 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
854 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
855 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
856 /* At this point, we assume the file is in error. It still could be somthing
857 * else besides a NE file, but it unlikely at this point. */
861 /* Allocate a bit more space to speed up things */
863 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
864 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
865 fname, PE_HEADER_SIZE));
869 /* This is a HACK! I got tired of trying to sort through the messy
870 * 'NE' file format. If anyone wants to clean this up please have at
871 * it, but this works. 'NE' files will eventually fade away. JRR */
872 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
873 /* Cover case that should not occur in a well formed 'NE' .dll file */
874 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
876 for(i=0; i<byte_count; i++) {
877 /* Fast skip past data that can't possibly match */
878 if (buf[i] != 'V') continue;
880 /* Potential match data crosses buf boundry, move it to beginning
881 * of buf, and fill the buf with as much as it will hold. */
882 if (i>byte_count-VS_VERSION_INFO_SIZE) {
885 memcpy(buf, &buf[i], byte_count-i);
886 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
887 (byte_count-i))) < 0) {
889 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
894 byte_count = bc + (byte_count - i);
895 if (byte_count<VS_VERSION_INFO_SIZE) break;
900 /* Check that the full signature string and the magic number that
901 * follows exist (not a perfect solution, but the chances that this
902 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
903 * twice, as it is simpler to read the code. */
904 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
905 /* Compute skip alignment to next long address */
906 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
907 sizeof(VS_SIGNATURE)) & 3;
908 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
910 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
911 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
912 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
913 fname, *major, *minor,
914 (*major>>16)&0xffff, *major&0xffff,
915 (*minor>>16)&0xffff, *minor&0xffff));
922 /* Version info not found, fall back to origin date/time */
923 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
928 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
929 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
930 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
941 /****************************************************************************
942 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
943 share one or more files. During the MS installation process files are checked
944 to insure that only a newer version of a shared file is installed over an
945 older version. There are several possibilities for this comparison. If there
946 is no previous version, the new one is newer (obviously). If either file is
947 missing the version info structure, compare the creation date (on Unix use
948 the modification date). Otherwise chose the numerically larger version number.
949 ****************************************************************************/
950 static int file_version_is_newer(connection_struct *conn, fstring new_file,
953 BOOL use_version = True;
958 time_t new_create_time;
962 time_t old_create_time;
966 files_struct *fsp = NULL;
968 SMB_STRUCT_STAT stat_buf;
972 ZERO_STRUCT(stat_buf);
973 new_create_time = (time_t)0;
974 old_create_time = (time_t)0;
976 /* Get file version info (if available) for previous file (if it exists) */
977 pstrcpy(filepath, old_file);
979 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
981 fsp = open_file_shared(conn, filepath, &stat_buf,
982 SET_OPEN_MODE(DOS_OPEN_RDONLY),
983 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
984 0, 0, &access_mode, &action);
986 /* Old file not found, so by definition new file is in fact newer */
987 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
992 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
993 if (ret == -1) goto error_exit;
996 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
999 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1000 old_create_time = st.st_mtime;
1001 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1004 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1008 /* Get file version info (if available) for new file */
1009 pstrcpy(filepath, new_file);
1010 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1012 fsp = open_file_shared(conn, filepath, &stat_buf,
1013 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1014 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1015 0, 0, &access_mode, &action);
1017 /* New file not found, this shouldn't occur if the caller did its job */
1018 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1023 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1024 if (ret == -1) goto error_exit;
1027 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1029 use_version = False;
1030 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1031 new_create_time = st.st_mtime;
1032 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1035 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1039 /* Compare versions and choose the larger version number */
1040 if (new_major > old_major ||
1041 (new_major == old_major && new_minor > old_minor)) {
1043 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1047 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1052 /* Compare modification time/dates and choose the newest time/date */
1053 if (new_create_time > old_create_time) {
1054 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1058 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1067 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1072 /****************************************************************************
1073 ****************************************************************************/
1074 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1076 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1077 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1078 fstring architecture;
1084 connection_struct *conn;
1087 struct passwd *pass;
1094 memset(inbuf, '\0', sizeof(inbuf));
1095 memset(outbuf, '\0', sizeof(outbuf));
1098 driver=driver_abstract.info_3;
1099 else if (level==6) {
1100 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1101 driver = &converted_driver;
1103 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1107 get_short_archi(architecture, driver->environment);
1110 pass = getpwuid(user->uid);
1112 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1113 (unsigned int)user->uid ));
1119 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1120 fstrcpy(user_name, pass->pw_name );
1121 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1123 /* Null password is ok - we are already an authenticated user... */
1125 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1128 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1129 *perr = (uint32)ecode;
1134 * Save who we are - we are temporarily becoming the connection user.
1139 if (!become_user(conn, conn->vuid)) {
1140 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1146 * make the directories version and version\driver_name
1147 * under the architecture directory.
1149 DEBUG(5,("Creating first directory\n"));
1150 slprintf(new_dir, sizeof(new_dir), "%s/%d", architecture, driver->cversion);
1151 mkdir_internal(conn, inbuf, outbuf, new_dir);
1153 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1154 * listed for this driver which has already been moved, skip it (note:
1155 * drivers may list the same file name several times. Then check if the
1156 * file already exists in archi\cversion\, if so, check that the version
1157 * info (or time stamps if version info is unavailable) is newer (or the
1158 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1159 * Otherwise, delete the file.
1161 * If a file is not moved to archi\cversion\ because of an error, all the
1162 * rest of the 'unmoved' driver files are removed from archi\. If one or
1163 * more of the driver's files was already moved to archi\cversion\, it
1164 * potentially leaves the driver in a partially updated state. Version
1165 * trauma will most likely occur if an client attempts to use any printer
1166 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1167 * done is appropriate... later JRR
1170 DEBUG(5,("Moving files now !\n"));
1172 if (driver->driverpath && strlen(driver->driverpath)) {
1173 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->driverpath);
1174 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->driverpath);
1175 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1176 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1177 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1178 new_name, old_name));
1179 *perr = (uint32)SVAL(outbuf,smb_err);
1180 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1185 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1188 if (driver->datafile && strlen(driver->datafile)) {
1189 if (!strequal(driver->datafile, driver->driverpath)) {
1190 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->datafile);
1191 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->datafile);
1192 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1193 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1194 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1195 new_name, old_name));
1196 *perr = (uint32)SVAL(outbuf,smb_err);
1197 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1202 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1206 if (driver->configfile && strlen(driver->configfile)) {
1207 if (!strequal(driver->configfile, driver->driverpath) &&
1208 !strequal(driver->configfile, driver->datafile)) {
1209 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->configfile);
1210 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->configfile);
1211 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1212 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1213 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1214 new_name, old_name));
1215 *perr = (uint32)SVAL(outbuf,smb_err);
1216 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1221 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1225 if (driver->helpfile && strlen(driver->helpfile)) {
1226 if (!strequal(driver->helpfile, driver->driverpath) &&
1227 !strequal(driver->helpfile, driver->datafile) &&
1228 !strequal(driver->helpfile, driver->configfile)) {
1229 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->helpfile);
1230 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->helpfile);
1231 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1232 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1233 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1234 new_name, old_name));
1235 *perr = (uint32)SVAL(outbuf,smb_err);
1236 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1241 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1245 if (driver->dependentfiles) {
1246 for (i=0; *driver->dependentfiles[i]; i++) {
1247 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1248 !strequal(driver->dependentfiles[i], driver->datafile) &&
1249 !strequal(driver->dependentfiles[i], driver->configfile) &&
1250 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1252 for (j=0; j < i; j++) {
1253 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1258 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->dependentfiles[i]);
1259 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->dependentfiles[i]);
1260 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1261 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1262 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1263 new_name, old_name));
1264 *perr = (uint32)SVAL(outbuf,smb_err);
1265 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1270 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1276 close_cnum(conn, user->vuid);
1279 return ver == -1 ? False : True;
1282 /****************************************************************************
1283 ****************************************************************************/
1284 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1287 fstring architecture;
1293 TDB_DATA kbuf, dbuf;
1295 get_short_archi(architecture, driver->environment);
1297 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1298 * \\server is added in the rpc server layer.
1299 * It does make sense to NOT store the server's name in the printer TDB.
1302 slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
1305 fstrcpy(temp_name, driver->driverpath);
1306 slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
1308 fstrcpy(temp_name, driver->datafile);
1309 slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
1311 fstrcpy(temp_name, driver->configfile);
1312 slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
1314 fstrcpy(temp_name, driver->helpfile);
1315 slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
1317 if (driver->dependentfiles) {
1318 for (i=0; *driver->dependentfiles[i]; i++) {
1319 fstrcpy(temp_name, driver->dependentfiles[i]);
1320 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
1324 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1326 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1333 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1336 driver->environment,
1341 driver->monitorname,
1342 driver->defaultdatatype);
1344 if (driver->dependentfiles) {
1345 for (i=0; *driver->dependentfiles[i]; i++) {
1346 len += tdb_pack(buf+len, buflen-len, "f",
1347 driver->dependentfiles[i]);
1351 if (len != buflen) {
1352 buf = (char *)Realloc(buf, len);
1359 kbuf.dsize = strlen(key)+1;
1363 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1366 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1372 /****************************************************************************
1373 ****************************************************************************/
1374 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1376 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1379 info3.cversion = driver->version;
1380 fstrcpy(info3.name,driver->name);
1381 fstrcpy(info3.environment,driver->environment);
1382 fstrcpy(info3.driverpath,driver->driverpath);
1383 fstrcpy(info3.datafile,driver->datafile);
1384 fstrcpy(info3.configfile,driver->configfile);
1385 fstrcpy(info3.helpfile,driver->helpfile);
1386 fstrcpy(info3.monitorname,driver->monitorname);
1387 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1388 info3.dependentfiles = driver->dependentfiles;
1390 return add_a_printer_driver_3(&info3);
1394 /****************************************************************************
1395 ****************************************************************************/
1396 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1398 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1402 fstrcpy(info.name, in_prt);
1403 fstrcpy(info.defaultdatatype, "RAW");
1405 fstrcpy(info.driverpath, "");
1406 fstrcpy(info.datafile, "");
1407 fstrcpy(info.configfile, "");
1408 fstrcpy(info.helpfile, "");
1410 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1411 return ERROR_NOT_ENOUGH_MEMORY;
1413 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1414 fstrcpy(info.dependentfiles[0], "");
1416 *info_ptr = memdup(&info, sizeof(info));
1421 /****************************************************************************
1422 ****************************************************************************/
1423 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1425 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1426 TDB_DATA kbuf, dbuf;
1427 fstring architecture;
1432 ZERO_STRUCT(driver);
1434 get_short_archi(architecture, in_arch);
1436 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1438 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1441 kbuf.dsize = strlen(key)+1;
1443 dbuf = tdb_fetch(tdb, kbuf);
1445 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1447 if (!dbuf.dptr) return 5;
1449 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1458 driver.defaultdatatype);
1461 while (len < dbuf.dsize) {
1462 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
1463 sizeof(fstring)*(i+2));
1464 if (driver.dependentfiles == NULL)
1467 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1468 &driver.dependentfiles[i]);
1471 if (driver.dependentfiles != NULL)
1472 fstrcpy(driver.dependentfiles[i], "");
1474 safe_free(dbuf.dptr);
1476 if (len != dbuf.dsize) {
1477 if (driver.dependentfiles != NULL)
1478 safe_free(driver.dependentfiles);
1480 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1483 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1488 /****************************************************************************
1489 ****************************************************************************/
1490 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1492 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1498 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1499 DEBUG(10,("driver key: [%s]\n", key));
1502 kbuf.dsize = strlen(key)+1;
1503 if (!tdb_exists(tdb, kbuf)) return False;
1506 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1508 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1509 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1510 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1511 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1512 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1513 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1514 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1516 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1517 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1518 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1520 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1521 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1522 pstrcat(line, info3->configfile);
1524 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1525 pstrcat(line, info3->datafile);
1527 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1528 pstrcat(line, info3->helpfile);
1530 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1531 pstrcat(line, info3->monitorname);
1533 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1536 for (i=0; info3->dependentfiles &&
1537 *info3->dependentfiles[i]; i++) {
1538 if (i) pstrcat(line, ","); /* don't end in a "," */
1539 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1540 pstrcat(line, info3->dependentfiles[i]);
1548 /****************************************************************************
1549 debugging function, dump at level 6 the struct in the logs
1550 ****************************************************************************/
1551 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1554 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1557 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1563 if (driver.info_3 == NULL)
1566 info3=driver.info_3;
1568 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1569 DEBUGADD(106,("name:[%s]\n", info3->name));
1570 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1571 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1572 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1573 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1574 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1575 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1576 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1578 for (i=0; info3->dependentfiles &&
1579 *info3->dependentfiles[i]; i++) {
1580 DEBUGADD(106,("dependentfile:[%s]\n",
1581 info3->dependentfiles[i]));
1588 DEBUGADD(1,("Level not implemented\n"));
1596 /****************************************************************************
1597 ****************************************************************************/
1598 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1602 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1604 if (!nt_devmode) return len;
1606 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1607 nt_devmode->devicename,
1608 nt_devmode->formname,
1610 nt_devmode->specversion,
1611 nt_devmode->driverversion,
1613 nt_devmode->driverextra,
1614 nt_devmode->orientation,
1615 nt_devmode->papersize,
1616 nt_devmode->paperlength,
1617 nt_devmode->paperwidth,
1620 nt_devmode->defaultsource,
1621 nt_devmode->printquality,
1624 nt_devmode->yresolution,
1625 nt_devmode->ttoption,
1626 nt_devmode->collate,
1627 nt_devmode->logpixels,
1630 nt_devmode->bitsperpel,
1631 nt_devmode->pelswidth,
1632 nt_devmode->pelsheight,
1633 nt_devmode->displayflags,
1634 nt_devmode->displayfrequency,
1635 nt_devmode->icmmethod,
1636 nt_devmode->icmintent,
1637 nt_devmode->mediatype,
1638 nt_devmode->dithertype,
1639 nt_devmode->reserved1,
1640 nt_devmode->reserved2,
1641 nt_devmode->panningwidth,
1642 nt_devmode->panningheight,
1643 nt_devmode->private);
1646 if (nt_devmode->private) {
1647 len += tdb_pack(buf+len, buflen-len, "B",
1648 nt_devmode->driverextra,
1649 nt_devmode->private);
1652 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1657 /****************************************************************************
1658 ****************************************************************************/
1659 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1663 while (param != NULL) {
1664 len += tdb_pack(buf+len, buflen-len, "pfdB",
1673 len += tdb_pack(buf+len, buflen-len, "p", param);
1679 /****************************************************************************
1680 delete a printer - this just deletes the printer info file, any open
1681 handles are not affected
1682 ****************************************************************************/
1683 uint32 del_a_printer(char *sharename)
1688 slprintf(key, sizeof(key), "%s%s",
1689 PRINTERS_PREFIX, sharename);
1692 kbuf.dsize=strlen(key)+1;
1694 tdb_delete(tdb, kbuf);
1698 /****************************************************************************
1699 ****************************************************************************/
1700 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1704 int buflen, len, ret;
1705 TDB_DATA kbuf, dbuf;
1708 * in addprinter: no servername and the printer is the name
1709 * in setprinter: servername is \\server
1710 * and printer is \\server\\printer
1712 * Samba manages only local printers.
1713 * we currently don't support things like path=\\other_server\printer
1716 if (info->servername[0]!='\0') {
1717 trim_string(info->printername, info->servername, NULL);
1718 trim_string(info->printername, "\\", NULL);
1719 info->servername[0]='\0';
1723 * JFM: one day I'll forget.
1724 * below that's info->portname because that's the SAMBA sharename
1725 * and I made NT 'thinks' it's the portname
1726 * the info->sharename is the thing you can name when you add a printer
1727 * that's the short-name when you create shared printer for 95/98
1728 * So I've made a limitation in SAMBA: you can only have 1 printer model
1729 * behind a SAMBA share.
1737 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1740 info->default_priority,
1757 info->printprocessor,
1761 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1762 len += pack_specifics(info->specific, buf+len, buflen-len);
1764 if (buflen != len) {
1765 buf = (char *)Realloc(buf, len);
1771 slprintf(key, sizeof(key), "%s%s",
1772 PRINTERS_PREFIX, info->sharename);
1775 kbuf.dsize = strlen(key)+1;
1779 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1782 DEBUG(8, ("error updating printer to tdb on disk\n"));
1786 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1787 info->sharename, info->drivername, info->portname, len));
1793 /****************************************************************************
1794 ****************************************************************************/
1795 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1797 NT_PRINTER_PARAM *current;
1799 DEBUG(108,("add_a_specific_param\n"));
1801 (*param)->next=NULL;
1803 if (info_2->specific == NULL)
1805 info_2->specific=*param;
1809 current=info_2->specific;
1810 while (current->next != NULL) {
1811 current=current->next;
1813 current->next=*param;
1819 /****************************************************************************
1820 ****************************************************************************/
1821 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1823 NT_PRINTER_PARAM *current;
1824 NT_PRINTER_PARAM *previous;
1826 current=info_2->specific;
1829 if (current==NULL) return (False);
1831 if ( !strcmp(current->value, param->value) &&
1832 (strlen(current->value)==strlen(param->value)) ) {
1833 DEBUG(109,("deleting first value\n"));
1834 info_2->specific=current->next;
1835 safe_free(current->data);
1837 DEBUG(109,("deleted first value\n"));
1841 current=previous->next;
1843 while ( current!=NULL ) {
1844 if (!strcmp(current->value, param->value) &&
1845 strlen(current->value)==strlen(param->value) ) {
1846 DEBUG(109,("deleting current value\n"));
1847 previous->next=current->next;
1848 safe_free(current->data);
1850 DEBUG(109,("deleted current value\n"));
1854 previous=previous->next;
1855 current=current->next;
1860 /****************************************************************************
1861 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
1862 ****************************************************************************/
1863 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
1865 NT_PRINTER_PARAM *param = *param_ptr;
1870 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
1873 safe_free(param->data);
1879 /****************************************************************************
1880 Malloc and return an NT devicemode.
1881 ****************************************************************************/
1883 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
1886 * should I init this ones ???
1887 nt_devmode->devicename
1891 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
1893 if (nt_devmode == NULL) {
1894 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
1898 ZERO_STRUCTP(nt_devmode);
1900 safe_strcpy(adevice, default_devicename, sizeof(adevice));
1901 fstrcpy(nt_devmode->devicename, adevice);
1903 fstrcpy(nt_devmode->formname, "Letter");
1905 nt_devmode->specversion = 0x0401;
1906 nt_devmode->driverversion = 0x0400;
1907 nt_devmode->size = 0x00DC;
1908 nt_devmode->driverextra = 0x0000;
1909 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
1910 DEFAULTSOURCE | COPIES | SCALE |
1911 PAPERSIZE | ORIENTATION;
1912 nt_devmode->orientation = 1;
1913 nt_devmode->papersize = PAPER_LETTER;
1914 nt_devmode->paperlength = 0;
1915 nt_devmode->paperwidth = 0;
1916 nt_devmode->scale = 0x64;
1917 nt_devmode->copies = 01;
1918 nt_devmode->defaultsource = BIN_FORMSOURCE;
1919 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
1920 nt_devmode->color = COLOR_MONOCHROME;
1921 nt_devmode->duplex = DUP_SIMPLEX;
1922 nt_devmode->yresolution = 0;
1923 nt_devmode->ttoption = TT_SUBDEV;
1924 nt_devmode->collate = COLLATE_FALSE;
1925 nt_devmode->icmmethod = 0;
1926 nt_devmode->icmintent = 0;
1927 nt_devmode->mediatype = 0;
1928 nt_devmode->dithertype = 0;
1930 /* non utilisés par un driver d'imprimante */
1931 nt_devmode->logpixels = 0;
1932 nt_devmode->bitsperpel = 0;
1933 nt_devmode->pelswidth = 0;
1934 nt_devmode->pelsheight = 0;
1935 nt_devmode->displayflags = 0;
1936 nt_devmode->displayfrequency = 0;
1937 nt_devmode->reserved1 = 0;
1938 nt_devmode->reserved2 = 0;
1939 nt_devmode->panningwidth = 0;
1940 nt_devmode->panningheight = 0;
1942 nt_devmode->private=NULL;
1947 /****************************************************************************
1948 Deepcopy an NT devicemode.
1949 ****************************************************************************/
1951 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
1953 NT_DEVICEMODE *new_nt_devicemode = NULL;
1955 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
1956 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1960 new_nt_devicemode->private = NULL;
1961 if (nt_devicemode->private != NULL) {
1962 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
1963 safe_free(new_nt_devicemode);
1964 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1969 return new_nt_devicemode;
1972 /****************************************************************************
1973 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
1974 ****************************************************************************/
1976 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
1978 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
1980 if(nt_devmode == NULL)
1983 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
1985 if(nt_devmode->private)
1986 safe_free(nt_devmode->private);
1988 safe_free(nt_devmode);
1989 *devmode_ptr = NULL;
1992 /****************************************************************************
1993 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
1994 ****************************************************************************/
1995 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
1997 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
1998 NT_PRINTER_PARAM *param_ptr;
2003 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2005 free_nt_devicemode(&info->devmode);
2006 free_sec_desc_buf(&info->secdesc_buf);
2008 for(param_ptr = info->specific; param_ptr; ) {
2009 NT_PRINTER_PARAM *tofree = param_ptr;
2011 param_ptr = param_ptr->next;
2012 free_nt_printer_param(&tofree);
2015 safe_free(*info_ptr);
2020 /****************************************************************************
2021 ****************************************************************************/
2022 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2026 NT_DEVICEMODE devmode;
2028 ZERO_STRUCT(devmode);
2030 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2032 if (!*nt_devmode) return len;
2034 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2038 &devmode.specversion,
2039 &devmode.driverversion,
2041 &devmode.driverextra,
2042 &devmode.orientation,
2044 &devmode.paperlength,
2045 &devmode.paperwidth,
2048 &devmode.defaultsource,
2049 &devmode.printquality,
2052 &devmode.yresolution,
2058 &devmode.bitsperpel,
2060 &devmode.pelsheight,
2061 &devmode.displayflags,
2062 &devmode.displayfrequency,
2066 &devmode.dithertype,
2069 &devmode.panningwidth,
2070 &devmode.panningheight,
2073 if (devmode.private) {
2074 /* the len in tdb_unpack is an int value and
2075 * devmoce.driverextra is only a short
2077 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2078 devmode.driverextra=(uint16)extra_len;
2080 /* check to catch an invalid TDB entry so we don't segfault */
2081 if (devmode.driverextra == 0) {
2082 devmode.private = NULL;
2086 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2088 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2089 if (devmode.private)
2090 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2095 /****************************************************************************
2096 ****************************************************************************/
2097 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2100 NT_PRINTER_PARAM param, *p;
2105 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2108 len += tdb_unpack(buf+len, buflen-len, "fdB",
2114 *list = memdup(¶m, sizeof(param));
2116 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2123 /****************************************************************************
2124 get a default printer info 2 struct
2125 ****************************************************************************/
2126 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2128 extern pstring global_myname;
2130 NT_PRINTER_INFO_LEVEL_2 info;
2134 snum = lp_servicenumber(sharename);
2136 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2137 slprintf(info.printername, sizeof(info.printername), "\\\\%s\\%s",
2138 global_myname, sharename);
2139 fstrcpy(info.sharename, sharename);
2140 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2141 fstrcpy(info.drivername, lp_printerdriver(snum));
2143 if (!*info.drivername)
2144 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2146 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2148 pstrcpy(info.comment, "");
2149 fstrcpy(info.printprocessor, "winprint");
2150 fstrcpy(info.datatype, "RAW");
2152 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2153 | PRINTER_ATTRIBUTE_LOCAL \
2154 | PRINTER_ATTRIBUTE_RAW_ONLY \
2155 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2157 info.starttime = 0; /* Minutes since 12:00am GMT */
2158 info.untiltime = 0; /* Minutes since 12:00am GMT */
2160 info.default_priority = 1;
2161 info.setuptime = (uint32)time(NULL);
2163 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2166 if (!nt_printing_getsec(sharename, &info.secdesc_buf))
2169 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2171 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2180 free_nt_devicemode(&info.devmode);
2181 if (info.secdesc_buf)
2182 free_sec_desc_buf(&info.secdesc_buf);
2186 /****************************************************************************
2187 ****************************************************************************/
2188 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2191 NT_PRINTER_INFO_LEVEL_2 info;
2193 TDB_DATA kbuf, dbuf;
2194 fstring printername;
2198 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
2201 kbuf.dsize = strlen(key)+1;
2203 dbuf = tdb_fetch(tdb, kbuf);
2205 return get_a_printer_2_default(info_ptr, sharename);
2207 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2210 &info.default_priority,
2227 info.printprocessor,
2231 /* Samba has to have shared raw drivers. */
2232 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2234 /* Restore the stripped strings. */
2235 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2236 slprintf(printername, sizeof(printername), "\\\\%s\\%s", global_myname,
2238 fstrcpy(info.printername, printername);
2240 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2241 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2243 nt_printing_getsec(sharename, &info.secdesc_buf);
2245 safe_free(dbuf.dptr);
2246 *info_ptr=memdup(&info, sizeof(info));
2248 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2249 sharename, info.printername, info.drivername));
2255 /****************************************************************************
2256 debugging function, dump at level 6 the struct in the logs
2257 ****************************************************************************/
2258 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2261 NT_PRINTER_INFO_LEVEL_2 *info2;
2263 DEBUG(106,("Dumping printer at level [%d]\n", level));
2269 if (printer.info_2 == NULL)
2273 info2=printer.info_2;
2275 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2276 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2277 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2278 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2279 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2280 DEBUGADD(106,("status:[%d]\n", info2->status));
2281 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2282 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2283 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2284 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2285 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2287 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2288 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2289 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2290 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2291 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2292 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2293 DEBUGADD(106,("location:[%s]\n", info2->location));
2294 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2295 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2296 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2297 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2303 DEBUGADD(1,("Level not implemented\n"));
2311 /****************************************************************************
2312 Get the parameters we can substitute in an NT print job.
2313 ****************************************************************************/
2315 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2317 NT_PRINTER_INFO_LEVEL *printer = NULL;
2319 **printername = **sharename = **portname = '\0';
2321 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2324 fstrcpy(*printername, printer->info_2->printername);
2325 fstrcpy(*sharename, printer->info_2->sharename);
2326 fstrcpy(*portname, printer->info_2->portname);
2328 free_a_printer(&printer, 2);
2332 * The function below are the high level ones.
2333 * only those ones must be called from the spoolss code.
2337 /****************************************************************************
2338 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2339 ****************************************************************************/
2341 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2345 dump_a_printer(printer, level);
2351 printer.info_2->c_setprinter++;
2352 result=update_a_printer_2(printer.info_2);
2363 /****************************************************************************
2364 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2365 We split this out from mod_a_printer as it updates the id's and timestamps.
2366 ****************************************************************************/
2368 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2372 dump_a_printer(printer, level);
2379 * Update the changestamp.
2380 * Note we must *not* do this in mod_a_printer().
2383 time_t time_unix = time(NULL);
2384 unix_to_nt_time(&time_nt, time_unix);
2385 printer.info_2->changeid=time_nt.low;
2387 printer.info_2->c_setprinter++;
2388 result=update_a_printer_2(printer.info_2);
2399 /****************************************************************************
2400 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2401 ****************************************************************************/
2403 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2406 NT_PRINTER_INFO_LEVEL *printer = NULL;
2410 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
2416 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
2417 DEBUG(0,("get_a_printer: malloc fail.\n"));
2420 ZERO_STRUCTP(printer);
2421 result=get_a_printer_2(&printer->info_2, sharename);
2423 dump_a_printer(*printer, level);
2424 *pp_printer = printer;
2435 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
2440 /****************************************************************************
2441 Deletes a NT_PRINTER_INFO_LEVEL struct.
2442 ****************************************************************************/
2444 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
2447 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
2449 DEBUG(104,("freeing a printer at level [%d]\n", level));
2451 if (printer == NULL)
2458 if (printer->info_2 != NULL)
2460 free_nt_printer_info_level_2(&printer->info_2);
2479 /****************************************************************************
2480 ****************************************************************************/
2481 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2484 DEBUG(104,("adding a printer at level [%d]\n", level));
2485 dump_a_printer_driver(driver, level);
2491 result=add_a_printer_driver_3(driver.info_3);
2497 result=add_a_printer_driver_6(driver.info_6);
2507 /****************************************************************************
2508 ****************************************************************************/
2509 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2510 fstring printername, fstring architecture, uint32 version)
2518 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2527 dump_a_printer_driver(*driver, level);
2531 /****************************************************************************
2532 ****************************************************************************/
2533 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2541 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2542 if (driver.info_3 != NULL)
2544 info3=driver.info_3;
2545 safe_free(info3->dependentfiles);
2546 ZERO_STRUCTP(info3);
2558 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2559 if (driver.info_6 != NULL)
2561 info6=driver.info_6;
2562 safe_free(info6->dependentfiles);
2563 safe_free(info6->previousnames);
2564 ZERO_STRUCTP(info6);
2581 /****************************************************************************
2582 ****************************************************************************/
2583 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2584 fstring value, uint8 **data, uint32 *type, uint32 *len)
2586 /* right now that's enough ! */
2587 NT_PRINTER_PARAM *param;
2590 param=printer.info_2->specific;
2592 while (param != NULL && i < param_index) {
2600 /* exited because it exist */
2602 StrnCpy(value, param->value, sizeof(fstring)-1);
2603 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2606 ZERO_STRUCTP(*data);
2607 memcpy(*data, param->data, param->data_len);
2608 *len=param->data_len;
2612 /****************************************************************************
2613 ****************************************************************************/
2614 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2615 fstring value, uint8 **data, uint32 *type, uint32 *len)
2617 /* right now that's enough ! */
2618 NT_PRINTER_PARAM *param;
2620 DEBUG(105, ("get_specific_param\n"));
2622 param=printer.info_2->specific;
2624 while (param != NULL)
2626 #if 1 /* JRA - I think this should be case insensitive.... */
2627 if ( strequal(value, param->value)
2629 if ( !strcmp(value, param->value)
2631 && strlen(value)==strlen(param->value))
2637 DEBUG(106, ("found one param\n"));
2640 /* exited because it exist */
2643 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2646 memcpy(*data, param->data, param->data_len);
2647 *len=param->data_len;
2649 DEBUG(106, ("exit of get_specific_param:true\n"));
2652 DEBUG(106, ("exit of get_specific_param:false\n"));
2656 /****************************************************************************
2657 Store a security desc for a printer.
2658 ****************************************************************************/
2660 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
2662 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2663 SEC_DESC_BUF *old_secdesc_ctr = NULL;
2665 TALLOC_CTX *mem_ctx = NULL;
2669 mem_ctx = talloc_init();
2670 if (mem_ctx == NULL)
2673 /* The old owner and group sids of the security descriptor are not
2674 present when new ACEs are added or removed by changing printer
2675 permissions through NT. If they are NULL in the new security
2676 descriptor then copy them over from the old one. */
2678 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
2679 DOM_SID *owner_sid, *group_sid;
2680 SEC_ACL *dacl, *sacl;
2681 SEC_DESC *psd = NULL;
2684 nt_printing_getsec(printername, &old_secdesc_ctr);
2686 /* Pick out correct owner and group sids */
2688 owner_sid = secdesc_ctr->sec->owner_sid ?
2689 secdesc_ctr->sec->owner_sid :
2690 old_secdesc_ctr->sec->owner_sid;
2692 group_sid = secdesc_ctr->sec->grp_sid ?
2693 secdesc_ctr->sec->grp_sid :
2694 old_secdesc_ctr->sec->grp_sid;
2696 dacl = secdesc_ctr->sec->dacl ?
2697 secdesc_ctr->sec->dacl :
2698 old_secdesc_ctr->sec->dacl;
2700 sacl = secdesc_ctr->sec->sacl ?
2701 secdesc_ctr->sec->sacl :
2702 old_secdesc_ctr->sec->sacl;
2704 /* Make a deep copy of the security descriptor */
2706 psd = make_sec_desc(secdesc_ctr->sec->revision,
2707 owner_sid, group_sid,
2712 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2714 /* Free up memory */
2716 free_sec_desc(&psd);
2717 free_sec_desc_buf(&old_secdesc_ctr);
2720 if (!new_secdesc_ctr) {
2721 new_secdesc_ctr = secdesc_ctr;
2724 /* Store the security descriptor in a tdb */
2726 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
2727 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
2729 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
2731 status = ERROR_INVALID_FUNCTION;
2735 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2737 if (tdb_prs_store(tdb, key, &ps)==0) {
2740 DEBUG(1,("Failed to store secdesc for %s\n", printername));
2741 status = ERROR_INVALID_FUNCTION;
2744 /* Free mallocated memory */
2747 free_sec_desc_buf(&old_secdesc_ctr);
2749 if (new_secdesc_ctr != secdesc_ctr) {
2750 free_sec_desc_buf(&new_secdesc_ctr);
2755 talloc_destroy(mem_ctx);
2759 /****************************************************************************
2760 Construct a default security descriptor buffer for a printer.
2761 ****************************************************************************/
2763 static SEC_DESC_BUF *construct_default_printer_sdb(void)
2767 SEC_ACL *psa = NULL;
2768 SEC_DESC_BUF *sdb = NULL;
2769 SEC_DESC *psd = NULL;
2772 enum SID_NAME_USE name_type;
2774 /* Create an ACE where Everyone is allowed to print */
2776 init_sec_access(&sa, PRINTER_ACE_PRINT);
2777 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2778 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2780 /* Make the security descriptor owned by the Administrators group
2781 on the PDC of the domain. */
2783 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
2784 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2787 /* Backup plan - make printer owned by admins or root. This should
2788 emulate a lanman printer as security settings can't be
2791 if (!lookup_name( "Printer Administrators", &owner_sid, &name_type) &&
2792 !lookup_name( "Administrators", &owner_sid, &name_type) &&
2793 !lookup_name( "Administrator", &owner_sid, &name_type) &&
2794 !lookup_name("root", &owner_sid, &name_type)) {
2795 sid_copy(&owner_sid, &global_sid_World);
2799 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
2800 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2801 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
2802 SEC_ACE_FLAG_INHERIT_ONLY);
2804 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
2805 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2806 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2808 /* The ACL revision number in rpc_secdesc.h differs from the one
2809 created by NT when setting ACE entries in printer
2810 descriptors. NT4 complains about the property being edited by a
2813 #define NT4_ACL_REVISION 0x2
2815 if ((psa = make_sec_acl(NT4_ACL_REVISION, 3, ace)) != NULL) {
2816 psd = make_sec_desc(SEC_DESC_REVISION,
2818 NULL, psa, &sd_size);
2823 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2827 sdb = make_sec_desc_buf(sd_size, psd);
2829 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2830 (unsigned int)sd_size));
2832 free_sec_desc(&psd);
2836 /****************************************************************************
2837 Get a security desc for a printer.
2838 ****************************************************************************/
2840 BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
2843 TALLOC_CTX *mem_ctx = NULL;
2847 mem_ctx = talloc_init();
2848 if (mem_ctx == NULL)
2851 if ((temp = strchr(printername + 2, '\\'))) {
2852 printername = temp + 1;
2855 /* Fetch security descriptor from tdb */
2857 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2859 if (tdb_prs_fetch(tdb, key, &ps, mem_ctx)!=0 ||
2860 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
2862 DEBUG(4,("using default secdesc for %s\n", printername));
2864 if (!(*secdesc_ctr = construct_default_printer_sdb())) {
2865 talloc_destroy(mem_ctx);
2869 talloc_destroy(mem_ctx);
2873 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2874 this security descriptor has been created when winbindd was
2875 down. Take ownership of security descriptor. */
2877 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
2879 enum SID_NAME_USE name_type;
2881 /* Change sd owner to workgroup administrator */
2883 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
2885 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2886 SEC_DESC *psd = NULL;
2891 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2893 psd = make_sec_desc((*secdesc_ctr)->sec->revision,
2895 (*secdesc_ctr)->sec->grp_sid,
2896 (*secdesc_ctr)->sec->sacl,
2897 (*secdesc_ctr)->sec->dacl,
2900 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2902 free_sec_desc(&psd);
2904 /* Swap with other one */
2906 free_sec_desc_buf(secdesc_ctr);
2907 *secdesc_ctr = new_secdesc_ctr;
2911 nt_printing_setsec(printername, *secdesc_ctr);
2915 if (DEBUGLEVEL >= 10) {
2916 SEC_ACL *acl = (*secdesc_ctr)->sec->dacl;
2919 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
2920 printername, acl->num_aces));
2922 for (i = 0; i < acl->num_aces; i++) {
2925 sid_to_string(sid_str, &acl->ace[i].sid);
2927 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
2928 acl->ace[i].type, acl->ace[i].flags,
2929 acl->ace[i].info.mask));
2934 talloc_destroy(mem_ctx);
2940 1: level not implemented
2941 2: file doesn't exist
2942 3: can't allocate memory
2943 4: can't free memory
2944 5: non existant struct
2948 A printer and a printer driver are 2 different things.
2949 NT manages them separatelly, Samba does the same.
2950 Why ? Simply because it's easier and it makes sense !
2952 Now explanation: You have 3 printers behind your samba server,
2953 2 of them are the same make and model (laser A and B). But laser B
2954 has an 3000 sheet feeder and laser A doesn't such an option.
2955 Your third printer is an old dot-matrix model for the accounting :-).
2957 If the /usr/local/samba/lib directory (default dir), you will have
2958 5 files to describe all of this.
2960 3 files for the printers (1 by printer):
2963 NTprinter_accounting
2964 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2965 NTdriver_printer model X
2966 NTdriver_printer model Y
2968 jfm: I should use this comment for the text file to explain
2969 same thing for the forms BTW.
2970 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2974 /* Convert generic access rights to printer object specific access rights.
2975 It turns out that NT4 security descriptors use generic access rights and
2976 NT5 the object specific ones. */
2978 void map_printer_permissions(SEC_DESC *sd)
2982 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2983 se_map_generic(&sd->dacl->ace[i].info.mask,
2984 &printer_generic_mapping);
2988 /****************************************************************************
2989 Check a user has permissions to perform the given operation. We use some
2990 constants defined in include/rpc_spoolss.h that look relevant to check
2991 the various actions we perform when checking printer access.
2993 PRINTER_ACCESS_ADMINISTER:
2994 print_queue_pause, print_queue_resume, update_printer_sec,
2995 update_printer, spoolss_addprinterex_level_2,
2996 _spoolss_setprinterdata
3001 PRINTER_ACCESS_ADMINISTER (should really be JOB_ACCESS_ADMINISTER):
3002 print_job_delete, print_job_pause, print_job_resume,
3005 ****************************************************************************/
3006 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3008 SEC_DESC_BUF *secdesc = NULL;
3009 uint32 access_granted, status;
3012 extern struct current_user current_user;
3014 /* If user is NULL then use the current_user structure */
3016 if (!user) user = ¤t_user;
3018 /* Always allow root or printer admins to do anything */
3020 if (user->uid == 0 ||
3021 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3025 /* Get printer name */
3027 pname = PRINTERNAME(snum);
3029 if (!pname || !*pname)
3030 pname = SERVICE(snum);
3032 if (!pname || !*pname) {
3037 /* Get printer security descriptor */
3039 nt_printing_getsec(pname, &secdesc);
3041 map_printer_permissions(secdesc->sec);
3043 result = se_access_check(secdesc->sec, user, access_type,
3044 &access_granted, &status);
3048 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3050 /* Free mallocated memory */
3052 free_sec_desc_buf(&secdesc);
3060 /****************************************************************************
3061 Check the time parameters allow a print operation.
3062 *****************************************************************************/
3064 BOOL print_time_access_check(int snum)
3066 NT_PRINTER_INFO_LEVEL *printer = NULL;
3068 time_t now = time(NULL);
3072 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3075 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3079 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3081 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3084 free_a_printer(&printer, 2);