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 /* We need one default form to support our default printer. Msoft adds the
39 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
40 array index). Letter is always first, so (for the current code) additions
41 always put things in the correct order. */
42 static nt_forms_struct default_forms[] = {
43 {"Letter", 0x2, 0x34b5b, 0x44367, 0x0, 0x0, 0x34b5b, 0x44367},
47 /****************************************************************************
48 open the NT printing tdb
49 ****************************************************************************/
50 BOOL nt_printing_init(void)
52 static pid_t local_pid;
53 char *vstring = "INFO/version";
55 if (tdb && local_pid == sys_getpid()) return True;
56 tdb = tdb_open(lock_path("ntdrivers.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
58 DEBUG(0,("Failed to open nt drivers database\n"));
62 local_pid = sys_getpid();
64 /* handle a Samba upgrade */
65 tdb_lock_bystring(tdb, vstring);
66 if (tdb_fetch_int(tdb, vstring) != DATABASE_VERSION) {
67 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
68 tdb_store_int(tdb, vstring, DATABASE_VERSION);
70 tdb_unlock_bystring(tdb, vstring);
76 /****************************************************************************
77 get a form struct list
78 ****************************************************************************/
79 int get_ntforms(nt_forms_struct **list)
81 TDB_DATA kbuf, newkey, dbuf;
87 for (kbuf = tdb_firstkey(tdb);
89 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
90 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
92 dbuf = tdb_fetch(tdb, kbuf);
93 if (!dbuf.dptr) continue;
95 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
96 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
97 &i, &form.flag, &form.width, &form.length, &form.left,
98 &form.top, &form.right, &form.bottom);
100 if (ret != dbuf.dsize) continue;
102 /* allocate space and populate the list in correct order */
104 *list = Realloc(*list, sizeof(nt_forms_struct)*(i+1));
110 /* we should never return a null forms list or NT gets unhappy */
112 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
113 n = sizeof(default_forms) / sizeof(default_forms[0]);
120 /****************************************************************************
121 write a form struct list
122 ****************************************************************************/
123 int write_ntforms(nt_forms_struct **list, int number)
130 for (i=0;i<number;i++) {
131 /* save index, so list is rebuilt in correct order */
132 len = tdb_pack(buf, sizeof(buf), "dddddddd",
133 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
134 (*list)[i].left, (*list)[i].top, (*list)[i].right,
136 if (len > sizeof(buf)) break;
137 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[i].name);
138 kbuf.dsize = strlen(key)+1;
142 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) break;
148 /****************************************************************************
149 add a form struct at the end of the list
150 ****************************************************************************/
151 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
158 * NT tries to add forms even when
159 * they are already in the base
160 * only update the values if already present
165 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
166 for (n=0; n<*count; n++) {
167 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
168 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
175 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
177 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
181 (*list)[n].flag=form->flags;
182 (*list)[n].width=form->size_x;
183 (*list)[n].length=form->size_y;
184 (*list)[n].left=form->left;
185 (*list)[n].top=form->top;
186 (*list)[n].right=form->right;
187 (*list)[n].bottom=form->bottom;
192 /****************************************************************************
193 delete a named form struct
194 ****************************************************************************/
195 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
206 * Don't delete the last form (no empty lists).
207 * CHECKME ! Is this correct ? JRA.
209 *ret = ERROR_INVALID_PARAMETER;
213 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
215 for (n=0; n<*count; n++) {
216 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
217 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
223 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
224 *ret = ERROR_INVALID_PARAMETER;
228 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[n].name);
229 kbuf.dsize = strlen(key)+1;
231 if (tdb_delete(tdb, kbuf) != 0) {
232 *ret = ERROR_NOT_ENOUGH_MEMORY;
239 /****************************************************************************
241 ****************************************************************************/
242 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
246 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
248 DEBUG(106, ("[%s]\n", form_name));
249 for (n=0; n<count; n++)
251 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
252 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
256 if (n==count) return;
258 (*list)[n].flag=form->flags;
259 (*list)[n].width=form->size_x;
260 (*list)[n].length=form->size_y;
261 (*list)[n].left=form->left;
262 (*list)[n].top=form->top;
263 (*list)[n].right=form->right;
264 (*list)[n].bottom=form->bottom;
267 /****************************************************************************
268 get the nt drivers list
270 traverse the database and look-up the matching names
271 ****************************************************************************/
272 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
277 TDB_DATA kbuf, newkey;
279 get_short_archi(short_archi, architecture);
280 slprintf(key, sizeof(key), "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
282 for (kbuf = tdb_firstkey(tdb);
284 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
285 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
287 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
290 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
297 /****************************************************************************
298 function to do the mapping between the long architecture name and
300 ****************************************************************************/
301 BOOL get_short_archi(char *short_archi, char *long_archi)
308 struct table archi_table[]=
310 {"Windows 4.0", "WIN40" },
311 {"Windows NT x86", "W32X86" },
312 {"Windows NT R4000", "W32MIPS" },
313 {"Windows NT Alpha_AXP", "W32ALPHA" },
314 {"Windows NT PowerPC", "W32PPC" },
320 DEBUG(107,("Getting architecture dependant directory\n"));
323 } while ( (archi_table[i].long_archi!=NULL ) &&
324 StrCaseCmp(long_archi, archi_table[i].long_archi) );
326 if (archi_table[i].long_archi==NULL) {
327 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
331 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
333 DEBUGADD(108,("index: [%d]\n", i));
334 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
335 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
340 /****************************************************************************
341 Determine the correct cVersion associated with an architecture and driver
342 ****************************************************************************/
343 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
344 struct current_user *user, uint32 *perr)
350 char buf[PE_HEADER_SIZE];
355 files_struct *fsp = NULL;
359 connection_struct *conn;
363 /* If architecture is Windows 95/98, the version is always 0. */
364 if (strcmp(architecture, "WIN40") == 0) {
365 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
370 pass = getpwuid(user->uid);
372 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
373 (unsigned int)user->uid ));
375 *perr = ERROR_ACCESS_DENIED;
380 /* connect to the print$ share under the same account as the user connected
382 fstrcpy(user_name, pass->pw_name );
383 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
385 /* Null password is ok - we are already an authenticated user... */
387 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
390 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
391 *perr = (uint32)ecode;
395 /* Save who we are - we are temporarily becoming the connection user. */
398 if (!become_user(conn, conn->vuid)) {
399 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
400 *perr = ERROR_ACCESS_DENIED;
405 /* Open the driver file (Portable Executable format) and determine the
406 * deriver the cversion. */
407 slprintf(driverpath, sizeof(driverpath), "%s/%s", architecture, driverpath_in);
409 unix_convert(driverpath,conn,NULL,&bad_path,&st);
411 fsp = open_file_shared(conn, driverpath, &st,
412 SET_OPEN_MODE(DOS_OPEN_RDONLY),
413 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
414 0, 0, &access_mode, &action);
416 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
418 *perr = ERROR_ACCESS_DENIED;
422 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
423 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
424 driverpath, byte_count));
425 *perr = NT_STATUS_FILE_INVALID;
429 /* Is this really a DOS header? */
430 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
431 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
432 driverpath, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
433 *perr = NT_STATUS_FILE_INVALID;
437 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
438 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
439 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
441 *perr = NT_STATUS_FILE_INVALID;
445 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
446 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
447 driverpath, byte_count));
448 *perr = NT_STATUS_FILE_INVALID;
452 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
453 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
454 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) == PE_HEADER_MACHINE_I386) {
456 switch (SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)) {
457 case 4: cversion = 2; break; /* Win NT 4 */
458 case 5: cversion = 3; break; /* Win 2000 */
460 DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
461 driverpath, SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)));
462 *perr = NT_STATUS_FILE_INVALID;
466 DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
467 driverpath, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
468 *perr = NT_STATUS_FILE_INVALID;
472 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
473 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) == NE_HEADER_TARGOS_WIN ) {
475 switch (CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)) {
476 case 3: cversion = 0; break; /* Win 3.x / Win 9x / Win ME */
477 /* case ?: cversion = 1; break;*/ /* Win NT 3.51 ... needs research JRR */
479 DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
480 driverpath, CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)));
481 *perr = NT_STATUS_FILE_INVALID;
485 DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
486 driverpath, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
487 *perr = NT_STATUS_FILE_INVALID;
492 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
493 driverpath, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
494 *perr = NT_STATUS_FILE_INVALID;
498 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
499 driverpath, cversion));
501 fsp->conn->vfs_ops.close(fsp, fsp->fd);
503 close_cnum(conn, user->vuid);
511 fsp->conn->vfs_ops.close(fsp, fsp->fd);
515 close_cnum(conn, user->vuid);
520 /****************************************************************************
521 ****************************************************************************/
522 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
523 struct current_user *user)
525 fstring architecture;
531 /* clean up the driver name.
532 * we can get .\driver.dll
533 * or worse c:\windows\system\driver.dll !
535 /* using an intermediate string to not have overlaping memcpy()'s */
536 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
537 fstrcpy(new_name, p+1);
538 fstrcpy(driver->driverpath, new_name);
541 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
542 fstrcpy(new_name, p+1);
543 fstrcpy(driver->datafile, new_name);
546 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
547 fstrcpy(new_name, p+1);
548 fstrcpy(driver->configfile, new_name);
551 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
552 fstrcpy(new_name, p+1);
553 fstrcpy(driver->helpfile, new_name);
556 if (driver->dependentfiles) {
557 for (i=0; *driver->dependentfiles[i]; i++) {
558 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
559 fstrcpy(new_name, p+1);
560 fstrcpy(driver->dependentfiles[i], new_name);
565 get_short_archi(architecture, driver->environment);
567 /* jfm:7/16/2000 the client always sends the cversion=0.
568 * The server should check which version the driver is by reading
569 * the PE header of driver->driverpath.
571 * For Windows 95/98 the version is 0 (so the value sent is correct)
572 * For Windows NT (the architecture doesn't matter)
574 * NT 3.5/3.51: cversion=1
578 if ((driver->cversion = get_correct_cversion( architecture,
579 driver->driverpath, user, &err)) == -1)
582 return NT_STATUS_NO_PROBLEMO;
585 /****************************************************************************
586 ****************************************************************************/
587 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
588 struct current_user *user)
590 fstring architecture;
596 /* clean up the driver name.
597 * we can get .\driver.dll
598 * or worse c:\windows\system\driver.dll !
600 /* using an intermediate string to not have overlaping memcpy()'s */
601 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
602 fstrcpy(new_name, p+1);
603 fstrcpy(driver->driverpath, new_name);
606 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
607 fstrcpy(new_name, p+1);
608 fstrcpy(driver->datafile, new_name);
611 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
612 fstrcpy(new_name, p+1);
613 fstrcpy(driver->configfile, new_name);
616 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
617 fstrcpy(new_name, p+1);
618 fstrcpy(driver->helpfile, new_name);
621 if (driver->dependentfiles) {
622 for (i=0; *driver->dependentfiles[i]; i++) {
623 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
624 fstrcpy(new_name, p+1);
625 fstrcpy(driver->dependentfiles[i], new_name);
630 get_short_archi(architecture, driver->environment);
632 /* jfm:7/16/2000 the client always sends the cversion=0.
633 * The server should check which version the driver is by reading
634 * the PE header of driver->driverpath.
636 * For Windows 95/98 the version is 0 (so the value sent is correct)
637 * For Windows NT (the architecture doesn't matter)
639 * NT 3.5/3.51: cversion=1
643 if ((driver->version = get_correct_cversion(architecture,
644 driver->driverpath, user, &err)) == -1)
647 return NT_STATUS_NO_PROBLEMO;
650 /****************************************************************************
651 ****************************************************************************/
652 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
653 uint32 level, struct current_user *user)
658 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
659 driver=driver_abstract.info_3;
660 return clean_up_driver_struct_level_3(driver, user);
665 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
666 driver=driver_abstract.info_6;
667 return clean_up_driver_struct_level_6(driver, user);
671 return ERROR_INVALID_PARAMETER;
675 /****************************************************************************
676 This function sucks and should be replaced. JRA.
677 ****************************************************************************/
679 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
681 dst->cversion = src->version;
683 fstrcpy( dst->name, src->name);
684 fstrcpy( dst->environment, src->environment);
685 fstrcpy( dst->driverpath, src->driverpath);
686 fstrcpy( dst->datafile, src->datafile);
687 fstrcpy( dst->configfile, src->configfile);
688 fstrcpy( dst->helpfile, src->helpfile);
689 fstrcpy( dst->monitorname, src->monitorname);
690 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
691 dst->dependentfiles = src->dependentfiles;
694 #if 0 /* Debugging function */
696 static char* ffmt(unsigned char *c){
698 static char ffmt_str[17];
700 for (i=0; i<16; i++) {
701 if ((c[i] < ' ') || (c[i] > '~'))
712 /****************************************************************************
713 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
714 There are two case to be covered here: PE (Portable Executable) and NE (New
715 Executable) files. Both files support the same INFO structure, but PE files
716 store the signature in unicode, and NE files store it as !unicode.
717 ****************************************************************************/
718 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
725 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
726 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
727 fname, PE_HEADER_SIZE));
731 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
732 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
733 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
735 goto no_version_info;
738 /* Is this really a DOS header? */
739 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
740 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
741 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
742 goto no_version_info;
745 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
746 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
747 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
749 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
750 goto no_version_info;
753 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
754 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %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 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
761 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
763 int section_table_bytes;
765 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
766 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
767 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
768 /* At this point, we assume the file is in error. It still could be somthing
769 * else besides a PE file, but it unlikely at this point.
774 /* get the section table */
775 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
776 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
778 if ((buf=malloc(section_table_bytes)) == NULL) {
779 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
780 fname, section_table_bytes));
784 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
785 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
790 /* Iterate the section table looking for the resource section ".rsrc" */
791 for (i = 0; i < num_sections; i++) {
792 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
794 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
795 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
796 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
799 if ((buf=malloc(section_bytes)) == NULL) {
800 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
801 fname, section_bytes));
805 /* Seek to the start of the .rsrc section info */
806 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
807 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
812 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
813 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
818 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
819 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
820 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
821 /* Align to next long address */
822 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
824 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
825 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
826 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
828 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
829 fname, *major, *minor,
830 (*major>>16)&0xffff, *major&0xffff,
831 (*minor>>16)&0xffff, *minor&0xffff));
840 /* Version info not found, fall back to origin date/time */
841 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
845 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
846 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
847 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
848 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
849 /* At this point, we assume the file is in error. It still could be somthing
850 * else besides a NE file, but it unlikely at this point. */
854 /* Allocate a bit more space to speed up things */
856 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
857 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
858 fname, PE_HEADER_SIZE));
862 /* This is a HACK! I got tired of trying to sort through the messy
863 * 'NE' file format. If anyone wants to clean this up please have at
864 * it, but this works. 'NE' files will eventually fade away. JRR */
865 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
866 /* Cover case that should not occur in a well formed 'NE' .dll file */
867 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
869 for(i=0; i<byte_count; i++) {
870 /* Fast skip past data that can't possibly match */
871 if (buf[i] != 'V') continue;
873 /* Potential match data crosses buf boundry, move it to beginning
874 * of buf, and fill the buf with as much as it will hold. */
875 if (i>byte_count-VS_VERSION_INFO_SIZE) {
878 memcpy(buf, &buf[i], byte_count-i);
879 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
880 (byte_count-i))) < 0) {
882 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
887 byte_count = bc + (byte_count - i);
888 if (byte_count<VS_VERSION_INFO_SIZE) break;
893 /* Check that the full signature string and the magic number that
894 * follows exist (not a perfect solution, but the chances that this
895 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
896 * twice, as it is simpler to read the code. */
897 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
898 /* Compute skip alignment to next long address */
899 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
900 sizeof(VS_SIGNATURE)) & 3;
901 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
903 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
904 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
905 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
906 fname, *major, *minor,
907 (*major>>16)&0xffff, *major&0xffff,
908 (*minor>>16)&0xffff, *minor&0xffff));
915 /* Version info not found, fall back to origin date/time */
916 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
921 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
922 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
923 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
934 /****************************************************************************
935 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
936 share one or more files. During the MS installation process files are checked
937 to insure that only a newer version of a shared file is installed over an
938 older version. There are several possibilities for this comparison. If there
939 is no previous version, the new one is newer (obviously). If either file is
940 missing the version info structure, compare the creation date (on Unix use
941 the modification date). Otherwise chose the numerically larger version number.
942 ****************************************************************************/
943 static int file_version_is_newer(connection_struct *conn, fstring new_file,
946 BOOL use_version = True;
951 time_t new_create_time;
955 time_t old_create_time;
959 files_struct *fsp = NULL;
961 SMB_STRUCT_STAT stat_buf;
965 ZERO_STRUCT(stat_buf);
966 new_create_time = (time_t)0;
967 old_create_time = (time_t)0;
969 /* Get file version info (if available) for previous file (if it exists) */
970 pstrcpy(filepath, old_file);
972 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
974 fsp = open_file_shared(conn, filepath, &stat_buf,
975 SET_OPEN_MODE(DOS_OPEN_RDONLY),
976 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
977 0, 0, &access_mode, &action);
979 /* Old file not found, so by definition new file is in fact newer */
980 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
985 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
986 if (ret == -1) goto error_exit;
989 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
992 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
993 old_create_time = st.st_mtime;
994 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
997 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1001 /* Get file version info (if available) for new file */
1002 pstrcpy(filepath, new_file);
1003 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1005 fsp = open_file_shared(conn, filepath, &stat_buf,
1006 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1007 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1008 0, 0, &access_mode, &action);
1010 /* New file not found, this shouldn't occur if the caller did its job */
1011 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1016 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1017 if (ret == -1) goto error_exit;
1020 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1022 use_version = False;
1023 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1024 new_create_time = st.st_mtime;
1025 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1028 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1032 /* Compare versions and choose the larger version number */
1033 if (new_major > old_major ||
1034 (new_major == old_major && new_minor > old_minor)) {
1036 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1040 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1045 /* Compare modification time/dates and choose the newest time/date */
1046 if (new_create_time > old_create_time) {
1047 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1051 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1060 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1065 /****************************************************************************
1066 ****************************************************************************/
1067 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1069 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1070 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1071 fstring architecture;
1077 connection_struct *conn;
1080 struct passwd *pass;
1087 memset(inbuf, '\0', sizeof(inbuf));
1088 memset(outbuf, '\0', sizeof(outbuf));
1091 driver=driver_abstract.info_3;
1092 else if (level==6) {
1093 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1094 driver = &converted_driver;
1096 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1100 get_short_archi(architecture, driver->environment);
1103 pass = getpwuid(user->uid);
1105 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1106 (unsigned int)user->uid ));
1112 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1113 fstrcpy(user_name, pass->pw_name );
1114 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1116 /* Null password is ok - we are already an authenticated user... */
1118 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1121 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1122 *perr = (uint32)ecode;
1127 * Save who we are - we are temporarily becoming the connection user.
1132 if (!become_user(conn, conn->vuid)) {
1133 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1139 * make the directories version and version\driver_name
1140 * under the architecture directory.
1142 DEBUG(5,("Creating first directory\n"));
1143 slprintf(new_dir, sizeof(new_dir), "%s/%d", architecture, driver->cversion);
1144 mkdir_internal(conn, inbuf, outbuf, new_dir);
1146 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1147 * listed for this driver which has already been moved, skip it (note:
1148 * drivers may list the same file name several times. Then check if the
1149 * file already exists in archi\cversion\, if so, check that the version
1150 * info (or time stamps if version info is unavailable) is newer (or the
1151 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1152 * Otherwise, delete the file.
1154 * If a file is not moved to archi\cversion\ because of an error, all the
1155 * rest of the 'unmoved' driver files are removed from archi\. If one or
1156 * more of the driver's files was already moved to archi\cversion\, it
1157 * potentially leaves the driver in a partially updated state. Version
1158 * trauma will most likely occur if an client attempts to use any printer
1159 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1160 * done is appropriate... later JRR
1163 DEBUG(5,("Moving files now !\n"));
1165 if (driver->driverpath && strlen(driver->driverpath)) {
1166 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->driverpath);
1167 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->driverpath);
1168 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1169 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1170 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1171 new_name, old_name));
1172 *perr = (uint32)SVAL(outbuf,smb_err);
1173 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1178 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1181 if (driver->datafile && strlen(driver->datafile)) {
1182 if (!strequal(driver->datafile, driver->driverpath)) {
1183 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->datafile);
1184 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->datafile);
1185 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1186 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1187 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1188 new_name, old_name));
1189 *perr = (uint32)SVAL(outbuf,smb_err);
1190 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1195 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1199 if (driver->configfile && strlen(driver->configfile)) {
1200 if (!strequal(driver->configfile, driver->driverpath) &&
1201 !strequal(driver->configfile, driver->datafile)) {
1202 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->configfile);
1203 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->configfile);
1204 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1205 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1206 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1207 new_name, old_name));
1208 *perr = (uint32)SVAL(outbuf,smb_err);
1209 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1214 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1218 if (driver->helpfile && strlen(driver->helpfile)) {
1219 if (!strequal(driver->helpfile, driver->driverpath) &&
1220 !strequal(driver->helpfile, driver->datafile) &&
1221 !strequal(driver->helpfile, driver->configfile)) {
1222 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->helpfile);
1223 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->helpfile);
1224 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1225 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1226 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1227 new_name, old_name));
1228 *perr = (uint32)SVAL(outbuf,smb_err);
1229 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1234 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1238 if (driver->dependentfiles) {
1239 for (i=0; *driver->dependentfiles[i]; i++) {
1240 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1241 !strequal(driver->dependentfiles[i], driver->datafile) &&
1242 !strequal(driver->dependentfiles[i], driver->configfile) &&
1243 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1245 for (j=0; j < i; j++) {
1246 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1251 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->dependentfiles[i]);
1252 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->dependentfiles[i]);
1253 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1254 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1255 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1256 new_name, old_name));
1257 *perr = (uint32)SVAL(outbuf,smb_err);
1258 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1263 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1269 close_cnum(conn, user->vuid);
1272 return ver == -1 ? False : True;
1275 /****************************************************************************
1276 ****************************************************************************/
1277 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1280 fstring architecture;
1286 TDB_DATA kbuf, dbuf;
1288 get_short_archi(architecture, driver->environment);
1290 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1291 * \\server is added in the rpc server layer.
1292 * It does make sense to NOT store the server's name in the printer TDB.
1295 slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
1298 fstrcpy(temp_name, driver->driverpath);
1299 slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
1301 fstrcpy(temp_name, driver->datafile);
1302 slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
1304 fstrcpy(temp_name, driver->configfile);
1305 slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
1307 fstrcpy(temp_name, driver->helpfile);
1308 slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
1310 if (driver->dependentfiles) {
1311 for (i=0; *driver->dependentfiles[i]; i++) {
1312 fstrcpy(temp_name, driver->dependentfiles[i]);
1313 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
1317 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1319 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1326 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1329 driver->environment,
1334 driver->monitorname,
1335 driver->defaultdatatype);
1337 if (driver->dependentfiles) {
1338 for (i=0; *driver->dependentfiles[i]; i++) {
1339 len += tdb_pack(buf+len, buflen-len, "f",
1340 driver->dependentfiles[i]);
1344 if (len != buflen) {
1345 buf = (char *)Realloc(buf, len);
1352 kbuf.dsize = strlen(key)+1;
1356 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1359 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1365 /****************************************************************************
1366 ****************************************************************************/
1367 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1369 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1372 info3.cversion = driver->version;
1373 fstrcpy(info3.name,driver->name);
1374 fstrcpy(info3.environment,driver->environment);
1375 fstrcpy(info3.driverpath,driver->driverpath);
1376 fstrcpy(info3.datafile,driver->datafile);
1377 fstrcpy(info3.configfile,driver->configfile);
1378 fstrcpy(info3.helpfile,driver->helpfile);
1379 fstrcpy(info3.monitorname,driver->monitorname);
1380 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1381 info3.dependentfiles = driver->dependentfiles;
1383 return add_a_printer_driver_3(&info3);
1387 /****************************************************************************
1388 ****************************************************************************/
1389 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1391 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1395 fstrcpy(info.name, in_prt);
1396 fstrcpy(info.defaultdatatype, "RAW");
1398 fstrcpy(info.driverpath, "");
1399 fstrcpy(info.datafile, "");
1400 fstrcpy(info.configfile, "");
1401 fstrcpy(info.helpfile, "");
1403 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1404 return ERROR_NOT_ENOUGH_MEMORY;
1406 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1407 fstrcpy(info.dependentfiles[0], "");
1409 *info_ptr = memdup(&info, sizeof(info));
1414 /****************************************************************************
1415 ****************************************************************************/
1416 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1418 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1419 TDB_DATA kbuf, dbuf;
1420 fstring architecture;
1425 ZERO_STRUCT(driver);
1427 get_short_archi(architecture, in_arch);
1429 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1431 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1434 kbuf.dsize = strlen(key)+1;
1436 dbuf = tdb_fetch(tdb, kbuf);
1438 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1440 if (!dbuf.dptr) return 5;
1442 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1451 driver.defaultdatatype);
1454 while (len < dbuf.dsize) {
1455 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
1456 sizeof(fstring)*(i+2));
1457 if (driver.dependentfiles == NULL)
1460 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1461 &driver.dependentfiles[i]);
1464 if (driver.dependentfiles != NULL)
1465 fstrcpy(driver.dependentfiles[i], "");
1467 safe_free(dbuf.dptr);
1469 if (len != dbuf.dsize) {
1470 if (driver.dependentfiles != NULL)
1471 safe_free(driver.dependentfiles);
1473 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1476 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1481 /****************************************************************************
1482 ****************************************************************************/
1483 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1485 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1491 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1492 DEBUG(10,("driver key: [%s]\n", key));
1495 kbuf.dsize = strlen(key)+1;
1496 if (!tdb_exists(tdb, kbuf)) return False;
1499 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1501 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1502 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1503 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1504 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1505 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1506 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1507 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1509 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1510 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1511 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1513 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1514 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1515 pstrcat(line, info3->configfile);
1517 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1518 pstrcat(line, info3->datafile);
1520 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1521 pstrcat(line, info3->helpfile);
1523 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1524 pstrcat(line, info3->monitorname);
1526 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1529 for (i=0; info3->dependentfiles &&
1530 *info3->dependentfiles[i]; i++) {
1531 if (i) pstrcat(line, ","); /* don't end in a "," */
1532 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1533 pstrcat(line, info3->dependentfiles[i]);
1541 /****************************************************************************
1542 debugging function, dump at level 6 the struct in the logs
1543 ****************************************************************************/
1544 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1547 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1550 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1556 if (driver.info_3 == NULL)
1559 info3=driver.info_3;
1561 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1562 DEBUGADD(106,("name:[%s]\n", info3->name));
1563 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1564 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1565 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1566 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1567 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1568 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1569 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1571 for (i=0; info3->dependentfiles &&
1572 *info3->dependentfiles[i]; i++) {
1573 DEBUGADD(106,("dependentfile:[%s]\n",
1574 info3->dependentfiles[i]));
1581 DEBUGADD(1,("Level not implemented\n"));
1589 /****************************************************************************
1590 ****************************************************************************/
1591 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1595 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1597 if (!nt_devmode) return len;
1599 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1600 nt_devmode->devicename,
1601 nt_devmode->formname,
1603 nt_devmode->specversion,
1604 nt_devmode->driverversion,
1606 nt_devmode->driverextra,
1607 nt_devmode->orientation,
1608 nt_devmode->papersize,
1609 nt_devmode->paperlength,
1610 nt_devmode->paperwidth,
1613 nt_devmode->defaultsource,
1614 nt_devmode->printquality,
1617 nt_devmode->yresolution,
1618 nt_devmode->ttoption,
1619 nt_devmode->collate,
1620 nt_devmode->logpixels,
1623 nt_devmode->bitsperpel,
1624 nt_devmode->pelswidth,
1625 nt_devmode->pelsheight,
1626 nt_devmode->displayflags,
1627 nt_devmode->displayfrequency,
1628 nt_devmode->icmmethod,
1629 nt_devmode->icmintent,
1630 nt_devmode->mediatype,
1631 nt_devmode->dithertype,
1632 nt_devmode->reserved1,
1633 nt_devmode->reserved2,
1634 nt_devmode->panningwidth,
1635 nt_devmode->panningheight,
1636 nt_devmode->private);
1639 if (nt_devmode->private) {
1640 len += tdb_pack(buf+len, buflen-len, "B",
1641 nt_devmode->driverextra,
1642 nt_devmode->private);
1645 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1650 /****************************************************************************
1651 ****************************************************************************/
1652 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1656 while (param != NULL) {
1657 len += tdb_pack(buf+len, buflen-len, "pfdB",
1666 len += tdb_pack(buf+len, buflen-len, "p", param);
1672 /****************************************************************************
1673 delete a printer - this just deletes the printer info file, any open
1674 handles are not affected
1675 ****************************************************************************/
1676 uint32 del_a_printer(char *sharename)
1681 slprintf(key, sizeof(key), "%s%s",
1682 PRINTERS_PREFIX, sharename);
1685 kbuf.dsize=strlen(key)+1;
1687 tdb_delete(tdb, kbuf);
1691 /****************************************************************************
1692 ****************************************************************************/
1693 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1697 int buflen, len, ret;
1698 TDB_DATA kbuf, dbuf;
1701 * in addprinter: no servername and the printer is the name
1702 * in setprinter: servername is \\server
1703 * and printer is \\server\\printer
1705 * Samba manages only local printers.
1706 * we currently don't support things like path=\\other_server\printer
1709 if (info->servername[0]!='\0') {
1710 trim_string(info->printername, info->servername, NULL);
1711 trim_string(info->printername, "\\", NULL);
1712 info->servername[0]='\0';
1716 * JFM: one day I'll forget.
1717 * below that's info->portname because that's the SAMBA sharename
1718 * and I made NT 'thinks' it's the portname
1719 * the info->sharename is the thing you can name when you add a printer
1720 * that's the short-name when you create shared printer for 95/98
1721 * So I've made a limitation in SAMBA: you can only have 1 printer model
1722 * behind a SAMBA share.
1730 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1733 info->default_priority,
1750 info->printprocessor,
1754 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1755 len += pack_specifics(info->specific, buf+len, buflen-len);
1757 if (buflen != len) {
1758 buf = (char *)Realloc(buf, len);
1764 slprintf(key, sizeof(key), "%s%s",
1765 PRINTERS_PREFIX, info->sharename);
1768 kbuf.dsize = strlen(key)+1;
1772 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1775 DEBUG(8, ("error updating printer to tdb on disk\n"));
1779 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1780 info->sharename, info->drivername, info->portname, len));
1786 /****************************************************************************
1787 ****************************************************************************/
1788 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1790 NT_PRINTER_PARAM *current;
1792 DEBUG(108,("add_a_specific_param\n"));
1794 (*param)->next=NULL;
1796 if (info_2->specific == NULL)
1798 info_2->specific=*param;
1802 current=info_2->specific;
1803 while (current->next != NULL) {
1804 current=current->next;
1806 current->next=*param;
1812 /****************************************************************************
1813 ****************************************************************************/
1814 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1816 NT_PRINTER_PARAM *current;
1817 NT_PRINTER_PARAM *previous;
1819 current=info_2->specific;
1822 if (current==NULL) return (False);
1824 if ( !strcmp(current->value, param->value) &&
1825 (strlen(current->value)==strlen(param->value)) ) {
1826 DEBUG(109,("deleting first value\n"));
1827 info_2->specific=current->next;
1828 safe_free(current->data);
1830 DEBUG(109,("deleted first value\n"));
1834 current=previous->next;
1836 while ( current!=NULL ) {
1837 if (!strcmp(current->value, param->value) &&
1838 strlen(current->value)==strlen(param->value) ) {
1839 DEBUG(109,("deleting current value\n"));
1840 previous->next=current->next;
1841 safe_free(current->data);
1843 DEBUG(109,("deleted current value\n"));
1847 previous=previous->next;
1848 current=current->next;
1853 /****************************************************************************
1854 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
1855 ****************************************************************************/
1856 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
1858 NT_PRINTER_PARAM *param = *param_ptr;
1863 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
1866 safe_free(param->data);
1872 /****************************************************************************
1873 Malloc and return an NT devicemode.
1874 ****************************************************************************/
1876 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
1879 * should I init this ones ???
1880 nt_devmode->devicename
1884 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
1886 if (nt_devmode == NULL) {
1887 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
1891 ZERO_STRUCTP(nt_devmode);
1893 safe_strcpy(adevice, default_devicename, sizeof(adevice));
1894 fstrcpy(nt_devmode->devicename, adevice);
1896 fstrcpy(nt_devmode->formname, "Letter");
1898 nt_devmode->specversion = 0x0401;
1899 nt_devmode->driverversion = 0x0400;
1900 nt_devmode->size = 0x00DC;
1901 nt_devmode->driverextra = 0x0000;
1902 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
1903 DEFAULTSOURCE | COPIES | SCALE |
1904 PAPERSIZE | ORIENTATION;
1905 nt_devmode->orientation = 1;
1906 nt_devmode->papersize = PAPER_LETTER;
1907 nt_devmode->paperlength = 0;
1908 nt_devmode->paperwidth = 0;
1909 nt_devmode->scale = 0x64;
1910 nt_devmode->copies = 01;
1911 nt_devmode->defaultsource = BIN_FORMSOURCE;
1912 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
1913 nt_devmode->color = COLOR_MONOCHROME;
1914 nt_devmode->duplex = DUP_SIMPLEX;
1915 nt_devmode->yresolution = 0;
1916 nt_devmode->ttoption = TT_SUBDEV;
1917 nt_devmode->collate = COLLATE_FALSE;
1918 nt_devmode->icmmethod = 0;
1919 nt_devmode->icmintent = 0;
1920 nt_devmode->mediatype = 0;
1921 nt_devmode->dithertype = 0;
1923 /* non utilisés par un driver d'imprimante */
1924 nt_devmode->logpixels = 0;
1925 nt_devmode->bitsperpel = 0;
1926 nt_devmode->pelswidth = 0;
1927 nt_devmode->pelsheight = 0;
1928 nt_devmode->displayflags = 0;
1929 nt_devmode->displayfrequency = 0;
1930 nt_devmode->reserved1 = 0;
1931 nt_devmode->reserved2 = 0;
1932 nt_devmode->panningwidth = 0;
1933 nt_devmode->panningheight = 0;
1935 nt_devmode->private=NULL;
1940 /****************************************************************************
1941 Deepcopy an NT devicemode.
1942 ****************************************************************************/
1944 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
1946 NT_DEVICEMODE *new_nt_devicemode = NULL;
1948 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
1949 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1953 new_nt_devicemode->private = NULL;
1954 if (nt_devicemode->private != NULL) {
1955 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
1956 safe_free(new_nt_devicemode);
1957 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1962 return new_nt_devicemode;
1965 /****************************************************************************
1966 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
1967 ****************************************************************************/
1969 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
1971 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
1973 if(nt_devmode == NULL)
1976 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
1978 if(nt_devmode->private)
1979 safe_free(nt_devmode->private);
1981 safe_free(nt_devmode);
1982 *devmode_ptr = NULL;
1985 /****************************************************************************
1986 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
1987 ****************************************************************************/
1988 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
1990 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
1991 NT_PRINTER_PARAM *param_ptr;
1996 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
1998 free_nt_devicemode(&info->devmode);
1999 free_sec_desc_buf(&info->secdesc_buf);
2001 for(param_ptr = info->specific; param_ptr; ) {
2002 NT_PRINTER_PARAM *tofree = param_ptr;
2004 param_ptr = param_ptr->next;
2005 free_nt_printer_param(&tofree);
2008 safe_free(*info_ptr);
2013 /****************************************************************************
2014 ****************************************************************************/
2015 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2019 NT_DEVICEMODE devmode;
2021 ZERO_STRUCT(devmode);
2023 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2025 if (!*nt_devmode) return len;
2027 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2031 &devmode.specversion,
2032 &devmode.driverversion,
2034 &devmode.driverextra,
2035 &devmode.orientation,
2037 &devmode.paperlength,
2038 &devmode.paperwidth,
2041 &devmode.defaultsource,
2042 &devmode.printquality,
2045 &devmode.yresolution,
2051 &devmode.bitsperpel,
2053 &devmode.pelsheight,
2054 &devmode.displayflags,
2055 &devmode.displayfrequency,
2059 &devmode.dithertype,
2062 &devmode.panningwidth,
2063 &devmode.panningheight,
2066 if (devmode.private) {
2067 /* the len in tdb_unpack is an int value and
2068 * devmoce.driverextra is only a short
2070 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2071 devmode.driverextra=(uint16)extra_len;
2074 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2076 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2077 if (devmode.private)
2078 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2083 /****************************************************************************
2084 ****************************************************************************/
2085 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2088 NT_PRINTER_PARAM param, *p;
2093 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2096 len += tdb_unpack(buf+len, buflen-len, "fdB",
2102 *list = memdup(¶m, sizeof(param));
2104 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2111 /****************************************************************************
2112 get a default printer info 2 struct
2113 ****************************************************************************/
2114 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2116 extern pstring global_myname;
2118 NT_PRINTER_INFO_LEVEL_2 info;
2122 snum = lp_servicenumber(sharename);
2124 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2125 slprintf(info.printername, sizeof(info.printername), "\\\\%s\\%s",
2126 global_myname, sharename);
2127 fstrcpy(info.sharename, sharename);
2128 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2129 fstrcpy(info.drivername, lp_printerdriver(snum));
2131 if (!*info.drivername)
2132 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2134 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2136 pstrcpy(info.comment, "");
2137 fstrcpy(info.printprocessor, "winprint");
2138 fstrcpy(info.datatype, "RAW");
2140 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2141 | PRINTER_ATTRIBUTE_LOCAL \
2142 | PRINTER_ATTRIBUTE_RAW_ONLY \
2143 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2145 info.starttime = 0; /* Minutes since 12:00am GMT */
2146 info.untiltime = 0; /* Minutes since 12:00am GMT */
2148 info.default_priority = 1;
2149 info.setuptime = (uint32)time(NULL);
2151 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2154 if (!nt_printing_getsec(sharename, &info.secdesc_buf))
2157 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2159 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2168 free_nt_devicemode(&info.devmode);
2169 if (info.secdesc_buf)
2170 free_sec_desc_buf(&info.secdesc_buf);
2174 /****************************************************************************
2175 ****************************************************************************/
2176 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2179 NT_PRINTER_INFO_LEVEL_2 info;
2181 TDB_DATA kbuf, dbuf;
2182 fstring printername;
2186 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
2189 kbuf.dsize = strlen(key)+1;
2191 dbuf = tdb_fetch(tdb, kbuf);
2193 return get_a_printer_2_default(info_ptr, sharename);
2195 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2198 &info.default_priority,
2215 info.printprocessor,
2219 /* Samba has to have shared raw drivers. */
2220 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2222 /* Restore the stripped strings. */
2223 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2224 slprintf(printername, sizeof(printername), "\\\\%s\\%s", global_myname,
2226 fstrcpy(info.printername, printername);
2228 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2229 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2231 nt_printing_getsec(sharename, &info.secdesc_buf);
2233 safe_free(dbuf.dptr);
2234 *info_ptr=memdup(&info, sizeof(info));
2236 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2237 sharename, info.printername, info.drivername));
2243 /****************************************************************************
2244 debugging function, dump at level 6 the struct in the logs
2245 ****************************************************************************/
2246 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2249 NT_PRINTER_INFO_LEVEL_2 *info2;
2251 DEBUG(106,("Dumping printer at level [%d]\n", level));
2257 if (printer.info_2 == NULL)
2261 info2=printer.info_2;
2263 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2264 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2265 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2266 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2267 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2268 DEBUGADD(106,("status:[%d]\n", info2->status));
2269 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2270 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2271 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2272 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2273 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2275 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2276 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2277 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2278 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2279 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2280 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2281 DEBUGADD(106,("location:[%s]\n", info2->location));
2282 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2283 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2284 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2285 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2291 DEBUGADD(1,("Level not implemented\n"));
2299 /****************************************************************************
2300 Get the parameters we can substitute in an NT print job.
2301 ****************************************************************************/
2303 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2305 NT_PRINTER_INFO_LEVEL *printer = NULL;
2307 **printername = **sharename = **portname = '\0';
2309 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2312 fstrcpy(*printername, printer->info_2->printername);
2313 fstrcpy(*sharename, printer->info_2->sharename);
2314 fstrcpy(*portname, printer->info_2->portname);
2316 free_a_printer(&printer, 2);
2320 * The function below are the high level ones.
2321 * only those ones must be called from the spoolss code.
2325 /****************************************************************************
2326 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2327 ****************************************************************************/
2329 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2333 dump_a_printer(printer, level);
2339 printer.info_2->c_setprinter++;
2340 success=update_a_printer_2(printer.info_2);
2351 /****************************************************************************
2352 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2353 We split this out from mod_a_printer as it updates the id's and timestamps.
2354 ****************************************************************************/
2356 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2360 dump_a_printer(printer, level);
2367 * Update the changestamp.
2368 * Note we must *not* do this in mod_a_printer().
2371 time_t time_unix = time(NULL);
2372 unix_to_nt_time(&time_nt, time_unix);
2373 printer.info_2->changeid=time_nt.low;
2375 printer.info_2->c_setprinter++;
2376 success=update_a_printer_2(printer.info_2);
2387 /****************************************************************************
2388 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2389 ****************************************************************************/
2391 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2394 NT_PRINTER_INFO_LEVEL *printer = NULL;
2398 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
2404 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
2405 DEBUG(0,("get_a_printer: malloc fail.\n"));
2408 ZERO_STRUCTP(printer);
2409 success=get_a_printer_2(&printer->info_2, sharename);
2411 dump_a_printer(*printer, level);
2412 *pp_printer = printer;
2423 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)success));
2428 /****************************************************************************
2429 Deletes a NT_PRINTER_INFO_LEVEL struct.
2430 ****************************************************************************/
2432 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
2435 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
2437 DEBUG(104,("freeing a printer at level [%d]\n", level));
2439 if (printer == NULL)
2446 if (printer->info_2 != NULL)
2448 free_nt_printer_info_level_2(&printer->info_2);
2467 /****************************************************************************
2468 ****************************************************************************/
2469 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2472 DEBUG(104,("adding a printer at level [%d]\n", level));
2473 dump_a_printer_driver(driver, level);
2479 success=add_a_printer_driver_3(driver.info_3);
2485 success=add_a_printer_driver_6(driver.info_6);
2495 /****************************************************************************
2496 ****************************************************************************/
2497 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2498 fstring printername, fstring architecture, uint32 version)
2506 success=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2515 dump_a_printer_driver(*driver, level);
2519 /****************************************************************************
2520 ****************************************************************************/
2521 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2529 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2530 if (driver.info_3 != NULL)
2532 info3=driver.info_3;
2533 safe_free(info3->dependentfiles);
2534 ZERO_STRUCTP(info3);
2546 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2547 if (driver.info_6 != NULL)
2549 info6=driver.info_6;
2550 safe_free(info6->dependentfiles);
2551 safe_free(info6->previousnames);
2552 ZERO_STRUCTP(info6);
2569 /****************************************************************************
2570 ****************************************************************************/
2571 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2572 fstring value, uint8 **data, uint32 *type, uint32 *len)
2574 /* right now that's enough ! */
2575 NT_PRINTER_PARAM *param;
2578 param=printer.info_2->specific;
2580 while (param != NULL && i < param_index) {
2588 /* exited because it exist */
2590 StrnCpy(value, param->value, sizeof(fstring)-1);
2591 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2594 ZERO_STRUCTP(*data);
2595 memcpy(*data, param->data, param->data_len);
2596 *len=param->data_len;
2600 /****************************************************************************
2601 ****************************************************************************/
2602 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2603 fstring value, uint8 **data, uint32 *type, uint32 *len)
2605 /* right now that's enough ! */
2606 NT_PRINTER_PARAM *param;
2608 DEBUG(105, ("get_specific_param\n"));
2610 param=printer.info_2->specific;
2612 while (param != NULL)
2614 #if 1 /* JRA - I think this should be case insensitive.... */
2615 if ( strequal(value, param->value)
2617 if ( !strcmp(value, param->value)
2619 && strlen(value)==strlen(param->value))
2625 DEBUG(106, ("found one param\n"));
2628 /* exited because it exist */
2631 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2634 memcpy(*data, param->data, param->data_len);
2635 *len=param->data_len;
2637 DEBUG(106, ("exit of get_specific_param:true\n"));
2640 DEBUG(106, ("exit of get_specific_param:false\n"));
2644 /****************************************************************************
2645 Store a security desc for a printer.
2646 ****************************************************************************/
2648 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
2650 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2651 SEC_DESC_BUF *old_secdesc_ctr = NULL;
2653 TALLOC_CTX *mem_ctx = NULL;
2657 mem_ctx = talloc_init();
2658 if (mem_ctx == NULL)
2661 /* The old owner and group sids of the security descriptor are not
2662 present when new ACEs are added or removed by changing printer
2663 permissions through NT. If they are NULL in the new security
2664 descriptor then copy them over from the old one. */
2666 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
2667 DOM_SID *owner_sid, *group_sid;
2668 SEC_ACL *dacl, *sacl;
2669 SEC_DESC *psd = NULL;
2672 nt_printing_getsec(printername, &old_secdesc_ctr);
2674 /* Pick out correct owner and group sids */
2676 owner_sid = secdesc_ctr->sec->owner_sid ?
2677 secdesc_ctr->sec->owner_sid :
2678 old_secdesc_ctr->sec->owner_sid;
2680 group_sid = secdesc_ctr->sec->grp_sid ?
2681 secdesc_ctr->sec->grp_sid :
2682 old_secdesc_ctr->sec->grp_sid;
2684 dacl = secdesc_ctr->sec->dacl ?
2685 secdesc_ctr->sec->dacl :
2686 old_secdesc_ctr->sec->dacl;
2688 sacl = secdesc_ctr->sec->sacl ?
2689 secdesc_ctr->sec->sacl :
2690 old_secdesc_ctr->sec->sacl;
2692 /* Make a deep copy of the security descriptor */
2694 psd = make_sec_desc(secdesc_ctr->sec->revision,
2695 owner_sid, group_sid,
2700 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2702 /* Free up memory */
2704 free_sec_desc(&psd);
2705 free_sec_desc_buf(&old_secdesc_ctr);
2708 if (!new_secdesc_ctr) {
2709 new_secdesc_ctr = secdesc_ctr;
2712 /* Store the security descriptor in a tdb */
2714 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
2715 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
2717 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
2719 status = ERROR_INVALID_FUNCTION;
2723 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2725 if (tdb_prs_store(tdb, key, &ps)==0) {
2728 DEBUG(1,("Failed to store secdesc for %s\n", printername));
2729 status = ERROR_INVALID_FUNCTION;
2732 /* Free mallocated memory */
2735 free_sec_desc_buf(&old_secdesc_ctr);
2737 if (new_secdesc_ctr != secdesc_ctr) {
2738 free_sec_desc_buf(&new_secdesc_ctr);
2743 talloc_destroy(mem_ctx);
2747 /****************************************************************************
2748 Construct a default security descriptor buffer for a printer.
2749 ****************************************************************************/
2751 static SEC_DESC_BUF *construct_default_printer_sdb(void)
2755 SEC_ACL *psa = NULL;
2756 SEC_DESC_BUF *sdb = NULL;
2757 SEC_DESC *psd = NULL;
2760 enum SID_NAME_USE name_type;
2762 /* Create an ACE where Everyone is allowed to print */
2764 init_sec_access(&sa, PRINTER_ACE_PRINT);
2765 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2766 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2769 /* Make the security descriptor owned by the Administrators group
2770 on the PDC of the domain. */
2772 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
2773 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2776 /* Backup plan - make printer owned by admins or root. This should
2777 emulate a lanman printer as security settings can't be
2780 if (!lookup_name( "Printer Administrators", &owner_sid, &name_type) &&
2781 !lookup_name( "Administrators", &owner_sid, &name_type) &&
2782 !lookup_name( "Administrator", &owner_sid, &name_type) &&
2783 !lookup_name("root", &owner_sid, &name_type)) {
2784 sid_copy(&owner_sid, &global_sid_World);
2788 init_sec_access(&sa, PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT);
2789 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2790 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2792 /* The ACL revision number in rpc_secdesc.h differs from the one
2793 created by NT when setting ACE entries in printer
2794 descriptors. NT4 complains about the property being edited by a
2797 #define NT4_ACL_REVISION 0x2
2799 if ((psa = make_sec_acl(NT4_ACL_REVISION, 2, ace)) != NULL) {
2800 psd = make_sec_desc(SEC_DESC_REVISION,
2802 NULL, psa, &sd_size);
2807 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2811 sdb = make_sec_desc_buf(sd_size, psd);
2813 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2814 (unsigned int)sd_size));
2816 free_sec_desc(&psd);
2820 /****************************************************************************
2821 Get a security desc for a printer.
2822 ****************************************************************************/
2824 BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
2827 TALLOC_CTX *mem_ctx = NULL;
2830 mem_ctx = talloc_init();
2831 if (mem_ctx == NULL)
2834 /* Fetch security descriptor from tdb */
2836 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2838 if (tdb_prs_fetch(tdb, key, &ps, mem_ctx)!=0 ||
2839 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
2841 DEBUG(4,("using default secdesc for %s\n", printername));
2843 if (!(*secdesc_ctr = construct_default_printer_sdb())) {
2844 talloc_destroy(mem_ctx);
2848 talloc_destroy(mem_ctx);
2852 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2853 this security descriptor has been created when winbindd was
2854 down. Take ownership of security descriptor. */
2856 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
2858 enum SID_NAME_USE name_type;
2860 /* Change sd owner to workgroup administrator */
2862 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
2864 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2865 SEC_DESC *psd = NULL;
2870 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2872 psd = make_sec_desc((*secdesc_ctr)->sec->revision,
2874 (*secdesc_ctr)->sec->grp_sid,
2875 (*secdesc_ctr)->sec->sacl,
2876 (*secdesc_ctr)->sec->dacl,
2879 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2881 free_sec_desc(&psd);
2883 /* Swap with other one */
2885 free_sec_desc_buf(secdesc_ctr);
2886 *secdesc_ctr = new_secdesc_ctr;
2890 nt_printing_setsec(printername, *secdesc_ctr);
2895 talloc_destroy(mem_ctx);
2901 1: level not implemented
2902 2: file doesn't exist
2903 3: can't allocate memory
2904 4: can't free memory
2905 5: non existant struct
2909 A printer and a printer driver are 2 different things.
2910 NT manages them separatelly, Samba does the same.
2911 Why ? Simply because it's easier and it makes sense !
2913 Now explanation: You have 3 printers behind your samba server,
2914 2 of them are the same make and model (laser A and B). But laser B
2915 has an 3000 sheet feeder and laser A doesn't such an option.
2916 Your third printer is an old dot-matrix model for the accounting :-).
2918 If the /usr/local/samba/lib directory (default dir), you will have
2919 5 files to describe all of this.
2921 3 files for the printers (1 by printer):
2924 NTprinter_accounting
2925 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2926 NTdriver_printer model X
2927 NTdriver_printer model Y
2929 jfm: I should use this comment for the text file to explain
2930 same thing for the forms BTW.
2931 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2935 /****************************************************************************
2936 Check a user has permissions to perform the given operation. We use some
2937 constants defined in include/rpc_spoolss.h that look relevant to check
2938 the various actions we perform when checking printer access.
2940 PRINTER_ACCESS_ADMINISTER:
2941 print_queue_pause, print_queue_resume, update_printer_sec,
2942 update_printer, spoolss_addprinterex_level_2,
2943 _spoolss_setprinterdata
2948 JOB_ACCESS_ADMINISTER:
2949 print_job_delete, print_job_pause, print_job_resume,
2952 ****************************************************************************/
2953 BOOL print_access_check(struct current_user *user, int snum, int access_type)
2955 SEC_DESC_BUF *secdesc = NULL;
2956 uint32 access_granted, status, required_access = 0;
2960 extern struct current_user current_user;
2962 /* If user is NULL then use the current_user structure */
2964 if (!user) user = ¤t_user;
2966 /* Always allow root or printer admins to do anything */
2968 if (user->uid == 0 ||
2969 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
2973 /* Get printer name */
2975 pname = PRINTERNAME(snum);
2977 if (!pname || !*pname)
2978 pname = SERVICE(snum);
2980 if (!pname || !*pname) {
2985 /* Get printer security descriptor */
2987 nt_printing_getsec(pname, &secdesc);
2989 /* Check against NT4 ACE mask values. From observation these
2992 Access Type ACE Mask Constant
2993 -------------------------------------
2994 Full Control 0x10000000 PRINTER_ACE_FULL_CONTROL
2995 Print 0xe0000000 PRINTER_ACE_PRINT
2996 Manage Documents 0x00020000 PRINTER_ACE_MANAGE_DOCUMENTS
2999 switch (access_type) {
3000 case PRINTER_ACCESS_USE:
3001 required_access = PRINTER_ACE_PRINT;
3003 case PRINTER_ACCESS_ADMINISTER:
3004 required_access = PRINTER_ACE_MANAGE_DOCUMENTS |
3007 case JOB_ACCESS_ADMINISTER:
3008 required_access = PRINTER_ACE_MANAGE_DOCUMENTS;
3011 DEBUG(0, ("invalid value passed to print_access_check()\n"));
3016 /* The ACE for Full Control in a printer security descriptor
3017 doesn't seem to map properly to the access checking model. For
3018 it to work properly it should be the logical OR of all the other
3019 values, i.e PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT.
3020 This would cause the access check to simply fall out when we
3021 check against any subset of these bits. To get things to work,
3022 change every ACE mask of PRINTER_ACE_FULL_CONTROL to
3023 PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT before
3024 performing the access check. I'm sure there is a better way to
3027 if (secdesc && secdesc->sec && secdesc->sec->dacl &&
3028 secdesc->sec->dacl->ace) {
3029 for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
3030 if (secdesc->sec->dacl->ace[i].info.mask ==
3031 PRINTER_ACE_FULL_CONTROL) {
3032 secdesc->sec->dacl->ace[i].info.mask =
3033 PRINTER_ACE_MANAGE_DOCUMENTS |
3039 if ((result = se_access_check(secdesc->sec, user, required_access,
3040 &access_granted, &status))) {
3044 /* Check against NT5 ACE mask values. From observation these
3047 Access Type ACE Mask Constant
3048 -------------------------------------
3049 Full Control 0x000f000c PRINTER_ACE_NT5_FULL_CONTROL
3050 Print 0x00020008 PRINTER_ACE_NT5_PRINT
3051 Manage Documents 0x00020000 PRINTER_ACE_NT5_MANAGE_DOCUMENTS
3053 NT5 likes to rewrite the security descriptor and change the ACE
3054 masks from NT4 format to NT5 format making them unreadable by
3057 switch (access_type) {
3058 case PRINTER_ACCESS_USE:
3059 required_access = PRINTER_ACE_NT5_PRINT;
3061 case PRINTER_ACCESS_ADMINISTER:
3062 required_access = PRINTER_ACE_NT5_FULL_CONTROL;
3064 case JOB_ACCESS_ADMINISTER:
3065 required_access = PRINTER_ACE_NT5_MANAGE_DOCUMENTS;
3069 result = se_access_check(secdesc->sec, user, required_access,
3070 &access_granted, &status);
3075 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3077 /* Free mallocated memory */
3079 free_sec_desc_buf(&secdesc);
3087 /****************************************************************************
3088 Check the time parameters allow a print operation.
3089 *****************************************************************************/
3091 BOOL print_time_access_check(int snum)
3093 NT_PRINTER_INFO_LEVEL *printer = NULL;
3095 time_t now = time(NULL);
3099 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3102 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3106 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3108 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3111 free_a_printer(&printer, 2);