3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-2000,
7 * Copyright (C) Jean François Micouleau 1998-2000.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern int DEBUGLEVEL;
27 extern pstring global_myname;
28 extern DOM_SID global_sid_World;
30 static TDB_CONTEXT *tdb; /* used for driver files */
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define PRINTERS_PREFIX "PRINTERS/"
36 #define DATABASE_VERSION 1
38 /* Map generic permissions to printer object specific permissions */
40 struct generic_mapping printer_generic_mapping = {
47 /* We need one default form to support our default printer. Msoft adds the
48 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
49 array index). Letter is always first, so (for the current code) additions
50 always put things in the correct order. */
51 static nt_forms_struct default_forms[] = {
52 {"Letter", 0x2, 0x34b5b, 0x44367, 0x0, 0x0, 0x34b5b, 0x44367},
56 /****************************************************************************
57 open the NT printing tdb
58 ****************************************************************************/
59 BOOL nt_printing_init(void)
61 static pid_t local_pid;
62 char *vstring = "INFO/version";
64 if (tdb && local_pid == sys_getpid()) return True;
65 tdb = tdb_open(lock_path("ntdrivers.tdb"), 0, 0, O_RDWR|O_CREAT, 0600);
67 DEBUG(0,("Failed to open nt drivers database\n"));
71 local_pid = sys_getpid();
73 /* handle a Samba upgrade */
74 tdb_lock_bystring(tdb, vstring);
75 if (tdb_fetch_int(tdb, vstring) != DATABASE_VERSION) {
76 tdb_traverse(tdb, (tdb_traverse_func)tdb_delete, NULL);
77 tdb_store_int(tdb, vstring, DATABASE_VERSION);
79 tdb_unlock_bystring(tdb, vstring);
85 /****************************************************************************
86 get a form struct list
87 ****************************************************************************/
88 int get_ntforms(nt_forms_struct **list)
90 TDB_DATA kbuf, newkey, dbuf;
96 for (kbuf = tdb_firstkey(tdb);
98 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
99 if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0) continue;
101 dbuf = tdb_fetch(tdb, kbuf);
102 if (!dbuf.dptr) continue;
104 fstrcpy(form.name, kbuf.dptr+strlen(FORMS_PREFIX));
105 ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
106 &i, &form.flag, &form.width, &form.length, &form.left,
107 &form.top, &form.right, &form.bottom);
108 safe_free(dbuf.dptr);
109 if (ret != dbuf.dsize) continue;
111 /* allocate space and populate the list in correct order */
113 *list = Realloc(*list, sizeof(nt_forms_struct)*(i+1));
119 /* we should never return a null forms list or NT gets unhappy */
121 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
122 n = sizeof(default_forms) / sizeof(default_forms[0]);
129 /****************************************************************************
130 write a form struct list
131 ****************************************************************************/
132 int write_ntforms(nt_forms_struct **list, int number)
139 for (i=0;i<number;i++) {
140 /* save index, so list is rebuilt in correct order */
141 len = tdb_pack(buf, sizeof(buf), "dddddddd",
142 i, (*list)[i].flag, (*list)[i].width, (*list)[i].length,
143 (*list)[i].left, (*list)[i].top, (*list)[i].right,
145 if (len > sizeof(buf)) break;
146 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[i].name);
147 dos_to_unix(key, True); /* Convert key to unix-codepage */
148 kbuf.dsize = strlen(key)+1;
152 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) break;
158 /****************************************************************************
159 add a form struct at the end of the list
160 ****************************************************************************/
161 BOOL add_a_form(nt_forms_struct **list, const FORM *form, int *count)
168 * NT tries to add forms even when
169 * they are already in the base
170 * only update the values if already present
175 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
176 for (n=0; n<*count; n++) {
177 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
178 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
185 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
187 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
191 (*list)[n].flag=form->flags;
192 (*list)[n].width=form->size_x;
193 (*list)[n].length=form->size_y;
194 (*list)[n].left=form->left;
195 (*list)[n].top=form->top;
196 (*list)[n].right=form->right;
197 (*list)[n].bottom=form->bottom;
202 /****************************************************************************
203 delete a named form struct
204 ****************************************************************************/
205 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
216 * Don't delete the last form (no empty lists).
217 * CHECKME ! Is this correct ? JRA.
219 *ret = ERROR_INVALID_PARAMETER;
223 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
225 for (n=0; n<*count; n++) {
226 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
227 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
233 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
234 *ret = ERROR_INVALID_PARAMETER;
238 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[n].name);
239 dos_to_unix(key, True); /* Convert key to unix-codepage */
240 kbuf.dsize = strlen(key)+1;
242 if (tdb_delete(tdb, kbuf) != 0) {
243 *ret = ERROR_NOT_ENOUGH_MEMORY;
250 /****************************************************************************
252 ****************************************************************************/
253 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
257 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
259 DEBUG(106, ("[%s]\n", form_name));
260 for (n=0; n<count; n++)
262 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
263 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
267 if (n==count) return;
269 (*list)[n].flag=form->flags;
270 (*list)[n].width=form->size_x;
271 (*list)[n].length=form->size_y;
272 (*list)[n].left=form->left;
273 (*list)[n].top=form->top;
274 (*list)[n].right=form->right;
275 (*list)[n].bottom=form->bottom;
278 /****************************************************************************
279 get the nt drivers list
281 traverse the database and look-up the matching names
282 ****************************************************************************/
283 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
288 TDB_DATA kbuf, newkey;
290 get_short_archi(short_archi, architecture);
291 slprintf(key, sizeof(key), "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
293 for (kbuf = tdb_firstkey(tdb);
295 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
296 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
298 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
301 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
308 /****************************************************************************
309 function to do the mapping between the long architecture name and
311 ****************************************************************************/
312 BOOL get_short_archi(char *short_archi, char *long_archi)
319 struct table archi_table[]=
321 {"Windows 4.0", "WIN40" },
322 {"Windows NT x86", "W32X86" },
323 {"Windows NT R4000", "W32MIPS" },
324 {"Windows NT Alpha_AXP", "W32ALPHA" },
325 {"Windows NT PowerPC", "W32PPC" },
331 DEBUG(107,("Getting architecture dependant directory\n"));
334 } while ( (archi_table[i].long_archi!=NULL ) &&
335 StrCaseCmp(long_archi, archi_table[i].long_archi) );
337 if (archi_table[i].long_archi==NULL) {
338 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
342 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
344 DEBUGADD(108,("index: [%d]\n", i));
345 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
346 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
351 /****************************************************************************
352 Determine the correct cVersion associated with an architecture and driver
353 ****************************************************************************/
354 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
355 struct current_user *user, uint32 *perr)
361 char buf[PE_HEADER_SIZE];
366 files_struct *fsp = NULL;
370 connection_struct *conn;
374 /* If architecture is Windows 95/98, the version is always 0. */
375 if (strcmp(architecture, "WIN40") == 0) {
376 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
381 pass = getpwuid(user->uid);
383 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
384 (unsigned int)user->uid ));
386 *perr = ERROR_ACCESS_DENIED;
391 /* connect to the print$ share under the same account as the user connected
393 fstrcpy(user_name, pass->pw_name );
394 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
396 /* Null password is ok - we are already an authenticated user... */
398 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
401 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
402 *perr = (uint32)ecode;
406 /* Save who we are - we are temporarily becoming the connection user. */
409 if (!become_user(conn, conn->vuid)) {
410 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
411 *perr = ERROR_ACCESS_DENIED;
416 /* Open the driver file (Portable Executable format) and determine the
417 * deriver the cversion. */
418 slprintf(driverpath, sizeof(driverpath), "%s/%s", architecture, driverpath_in);
420 unix_convert(driverpath,conn,NULL,&bad_path,&st);
422 fsp = open_file_shared(conn, driverpath, &st,
423 SET_OPEN_MODE(DOS_OPEN_RDONLY),
424 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
425 0, 0, &access_mode, &action);
427 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
429 *perr = ERROR_ACCESS_DENIED;
433 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
434 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
435 driverpath, byte_count));
436 *perr = NT_STATUS_FILE_INVALID;
440 /* Is this really a DOS header? */
441 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
442 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
443 driverpath, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
444 *perr = NT_STATUS_FILE_INVALID;
448 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
449 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
450 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
452 *perr = NT_STATUS_FILE_INVALID;
456 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
457 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
458 driverpath, byte_count));
459 *perr = NT_STATUS_FILE_INVALID;
463 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
464 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
465 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) == PE_HEADER_MACHINE_I386) {
467 switch (SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)) {
468 case 4: cversion = 2; break; /* Win NT 4 */
469 case 5: cversion = 3; break; /* Win 2000 */
471 DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
472 driverpath, SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)));
473 *perr = NT_STATUS_FILE_INVALID;
477 DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
478 driverpath, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
479 *perr = NT_STATUS_FILE_INVALID;
483 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
484 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) == NE_HEADER_TARGOS_WIN ) {
486 switch (CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)) {
487 case 3: cversion = 0; break; /* Win 3.x / Win 9x / Win ME */
488 /* case ?: cversion = 1; break;*/ /* Win NT 3.51 ... needs research JRR */
490 DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
491 driverpath, CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)));
492 *perr = NT_STATUS_FILE_INVALID;
496 DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
497 driverpath, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
498 *perr = NT_STATUS_FILE_INVALID;
503 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
504 driverpath, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
505 *perr = NT_STATUS_FILE_INVALID;
509 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
510 driverpath, cversion));
512 fsp->conn->vfs_ops.close(fsp, fsp->fd);
514 close_cnum(conn, user->vuid);
522 fsp->conn->vfs_ops.close(fsp, fsp->fd);
526 close_cnum(conn, user->vuid);
531 /****************************************************************************
532 ****************************************************************************/
533 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
534 struct current_user *user)
536 fstring architecture;
542 /* clean up the driver name.
543 * we can get .\driver.dll
544 * or worse c:\windows\system\driver.dll !
546 /* using an intermediate string to not have overlaping memcpy()'s */
547 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
548 fstrcpy(new_name, p+1);
549 fstrcpy(driver->driverpath, new_name);
552 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
553 fstrcpy(new_name, p+1);
554 fstrcpy(driver->datafile, new_name);
557 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
558 fstrcpy(new_name, p+1);
559 fstrcpy(driver->configfile, new_name);
562 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
563 fstrcpy(new_name, p+1);
564 fstrcpy(driver->helpfile, new_name);
567 if (driver->dependentfiles) {
568 for (i=0; *driver->dependentfiles[i]; i++) {
569 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
570 fstrcpy(new_name, p+1);
571 fstrcpy(driver->dependentfiles[i], new_name);
576 get_short_archi(architecture, driver->environment);
578 /* jfm:7/16/2000 the client always sends the cversion=0.
579 * The server should check which version the driver is by reading
580 * the PE header of driver->driverpath.
582 * For Windows 95/98 the version is 0 (so the value sent is correct)
583 * For Windows NT (the architecture doesn't matter)
585 * NT 3.5/3.51: cversion=1
589 if ((driver->cversion = get_correct_cversion( architecture,
590 driver->driverpath, user, &err)) == -1)
593 return NT_STATUS_NO_PROBLEMO;
596 /****************************************************************************
597 ****************************************************************************/
598 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
599 struct current_user *user)
601 fstring architecture;
607 /* clean up the driver name.
608 * we can get .\driver.dll
609 * or worse c:\windows\system\driver.dll !
611 /* using an intermediate string to not have overlaping memcpy()'s */
612 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
613 fstrcpy(new_name, p+1);
614 fstrcpy(driver->driverpath, new_name);
617 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
618 fstrcpy(new_name, p+1);
619 fstrcpy(driver->datafile, new_name);
622 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
623 fstrcpy(new_name, p+1);
624 fstrcpy(driver->configfile, new_name);
627 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
628 fstrcpy(new_name, p+1);
629 fstrcpy(driver->helpfile, new_name);
632 if (driver->dependentfiles) {
633 for (i=0; *driver->dependentfiles[i]; i++) {
634 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
635 fstrcpy(new_name, p+1);
636 fstrcpy(driver->dependentfiles[i], new_name);
641 get_short_archi(architecture, driver->environment);
643 /* jfm:7/16/2000 the client always sends the cversion=0.
644 * The server should check which version the driver is by reading
645 * the PE header of driver->driverpath.
647 * For Windows 95/98 the version is 0 (so the value sent is correct)
648 * For Windows NT (the architecture doesn't matter)
650 * NT 3.5/3.51: cversion=1
654 if ((driver->version = get_correct_cversion(architecture,
655 driver->driverpath, user, &err)) == -1)
658 return NT_STATUS_NO_PROBLEMO;
661 /****************************************************************************
662 ****************************************************************************/
663 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
664 uint32 level, struct current_user *user)
669 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
670 driver=driver_abstract.info_3;
671 return clean_up_driver_struct_level_3(driver, user);
675 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
676 driver=driver_abstract.info_6;
677 return clean_up_driver_struct_level_6(driver, user);
680 return ERROR_INVALID_PARAMETER;
684 /****************************************************************************
685 This function sucks and should be replaced. JRA.
686 ****************************************************************************/
688 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
690 dst->cversion = src->version;
692 fstrcpy( dst->name, src->name);
693 fstrcpy( dst->environment, src->environment);
694 fstrcpy( dst->driverpath, src->driverpath);
695 fstrcpy( dst->datafile, src->datafile);
696 fstrcpy( dst->configfile, src->configfile);
697 fstrcpy( dst->helpfile, src->helpfile);
698 fstrcpy( dst->monitorname, src->monitorname);
699 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
700 dst->dependentfiles = src->dependentfiles;
703 #if 0 /* Debugging function */
705 static char* ffmt(unsigned char *c){
707 static char ffmt_str[17];
709 for (i=0; i<16; i++) {
710 if ((c[i] < ' ') || (c[i] > '~'))
721 /****************************************************************************
722 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
723 There are two case to be covered here: PE (Portable Executable) and NE (New
724 Executable) files. Both files support the same INFO structure, but PE files
725 store the signature in unicode, and NE files store it as !unicode.
726 ****************************************************************************/
727 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
734 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
735 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
736 fname, PE_HEADER_SIZE));
740 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
741 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
742 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
744 goto no_version_info;
747 /* Is this really a DOS header? */
748 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
749 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
750 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
751 goto no_version_info;
754 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
755 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
756 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
758 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
759 goto no_version_info;
762 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
763 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
765 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
766 goto no_version_info;
769 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
770 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
772 int section_table_bytes;
774 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
775 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
776 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
777 /* At this point, we assume the file is in error. It still could be somthing
778 * else besides a PE file, but it unlikely at this point.
783 /* get the section table */
784 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
785 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
787 if ((buf=malloc(section_table_bytes)) == NULL) {
788 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
789 fname, section_table_bytes));
793 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
794 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
799 /* Iterate the section table looking for the resource section ".rsrc" */
800 for (i = 0; i < num_sections; i++) {
801 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
803 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
804 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
805 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
808 if ((buf=malloc(section_bytes)) == NULL) {
809 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
810 fname, section_bytes));
814 /* Seek to the start of the .rsrc section info */
815 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
816 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
821 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
822 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
827 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
828 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
829 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
830 /* Align to next long address */
831 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
833 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
834 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
835 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
837 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
838 fname, *major, *minor,
839 (*major>>16)&0xffff, *major&0xffff,
840 (*minor>>16)&0xffff, *minor&0xffff));
849 /* Version info not found, fall back to origin date/time */
850 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
854 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
855 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
856 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
857 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
858 /* At this point, we assume the file is in error. It still could be somthing
859 * else besides a NE file, but it unlikely at this point. */
863 /* Allocate a bit more space to speed up things */
865 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
866 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
867 fname, PE_HEADER_SIZE));
871 /* This is a HACK! I got tired of trying to sort through the messy
872 * 'NE' file format. If anyone wants to clean this up please have at
873 * it, but this works. 'NE' files will eventually fade away. JRR */
874 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
875 /* Cover case that should not occur in a well formed 'NE' .dll file */
876 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
878 for(i=0; i<byte_count; i++) {
879 /* Fast skip past data that can't possibly match */
880 if (buf[i] != 'V') continue;
882 /* Potential match data crosses buf boundry, move it to beginning
883 * of buf, and fill the buf with as much as it will hold. */
884 if (i>byte_count-VS_VERSION_INFO_SIZE) {
887 memcpy(buf, &buf[i], byte_count-i);
888 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
889 (byte_count-i))) < 0) {
891 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
896 byte_count = bc + (byte_count - i);
897 if (byte_count<VS_VERSION_INFO_SIZE) break;
902 /* Check that the full signature string and the magic number that
903 * follows exist (not a perfect solution, but the chances that this
904 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
905 * twice, as it is simpler to read the code. */
906 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
907 /* Compute skip alignment to next long address */
908 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
909 sizeof(VS_SIGNATURE)) & 3;
910 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
912 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
913 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
914 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
915 fname, *major, *minor,
916 (*major>>16)&0xffff, *major&0xffff,
917 (*minor>>16)&0xffff, *minor&0xffff));
924 /* Version info not found, fall back to origin date/time */
925 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
930 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
931 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
932 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
943 /****************************************************************************
944 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
945 share one or more files. During the MS installation process files are checked
946 to insure that only a newer version of a shared file is installed over an
947 older version. There are several possibilities for this comparison. If there
948 is no previous version, the new one is newer (obviously). If either file is
949 missing the version info structure, compare the creation date (on Unix use
950 the modification date). Otherwise chose the numerically larger version number.
951 ****************************************************************************/
952 static int file_version_is_newer(connection_struct *conn, fstring new_file,
955 BOOL use_version = True;
960 time_t new_create_time;
964 time_t old_create_time;
968 files_struct *fsp = NULL;
970 SMB_STRUCT_STAT stat_buf;
974 ZERO_STRUCT(stat_buf);
975 new_create_time = (time_t)0;
976 old_create_time = (time_t)0;
978 /* Get file version info (if available) for previous file (if it exists) */
979 pstrcpy(filepath, old_file);
981 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
983 fsp = open_file_shared(conn, filepath, &stat_buf,
984 SET_OPEN_MODE(DOS_OPEN_RDONLY),
985 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
986 0, 0, &access_mode, &action);
988 /* Old file not found, so by definition new file is in fact newer */
989 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
994 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
995 if (ret == -1) goto error_exit;
998 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1000 use_version = False;
1001 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1002 old_create_time = st.st_mtime;
1003 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
1006 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1010 /* Get file version info (if available) for new file */
1011 pstrcpy(filepath, new_file);
1012 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1014 fsp = open_file_shared(conn, filepath, &stat_buf,
1015 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1016 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1017 0, 0, &access_mode, &action);
1019 /* New file not found, this shouldn't occur if the caller did its job */
1020 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1025 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1026 if (ret == -1) goto error_exit;
1029 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1031 use_version = False;
1032 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1033 new_create_time = st.st_mtime;
1034 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1037 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1041 /* Compare versions and choose the larger version number */
1042 if (new_major > old_major ||
1043 (new_major == old_major && new_minor > old_minor)) {
1045 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1049 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1054 /* Compare modification time/dates and choose the newest time/date */
1055 if (new_create_time > old_create_time) {
1056 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1060 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1069 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1074 /****************************************************************************
1075 ****************************************************************************/
1076 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1078 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1079 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1080 fstring architecture;
1086 connection_struct *conn;
1089 struct passwd *pass;
1096 memset(inbuf, '\0', sizeof(inbuf));
1097 memset(outbuf, '\0', sizeof(outbuf));
1100 driver=driver_abstract.info_3;
1101 else if (level==6) {
1102 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1103 driver = &converted_driver;
1105 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1109 get_short_archi(architecture, driver->environment);
1112 pass = getpwuid(user->uid);
1114 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1115 (unsigned int)user->uid ));
1121 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1122 fstrcpy(user_name, pass->pw_name );
1123 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1125 /* Null password is ok - we are already an authenticated user... */
1127 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1130 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1131 *perr = (uint32)ecode;
1136 * Save who we are - we are temporarily becoming the connection user.
1141 if (!become_user(conn, conn->vuid)) {
1142 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1148 * make the directories version and version\driver_name
1149 * under the architecture directory.
1151 DEBUG(5,("Creating first directory\n"));
1152 slprintf(new_dir, sizeof(new_dir), "%s/%d", architecture, driver->cversion);
1153 mkdir_internal(conn, inbuf, outbuf, new_dir);
1155 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1156 * listed for this driver which has already been moved, skip it (note:
1157 * drivers may list the same file name several times. Then check if the
1158 * file already exists in archi\cversion\, if so, check that the version
1159 * info (or time stamps if version info is unavailable) is newer (or the
1160 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1161 * Otherwise, delete the file.
1163 * If a file is not moved to archi\cversion\ because of an error, all the
1164 * rest of the 'unmoved' driver files are removed from archi\. If one or
1165 * more of the driver's files was already moved to archi\cversion\, it
1166 * potentially leaves the driver in a partially updated state. Version
1167 * trauma will most likely occur if an client attempts to use any printer
1168 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1169 * done is appropriate... later JRR
1172 DEBUG(5,("Moving files now !\n"));
1174 if (driver->driverpath && strlen(driver->driverpath)) {
1175 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->driverpath);
1176 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->driverpath);
1177 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1178 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1179 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1180 new_name, old_name));
1181 *perr = (uint32)SVAL(outbuf,smb_err);
1182 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1187 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1190 if (driver->datafile && strlen(driver->datafile)) {
1191 if (!strequal(driver->datafile, driver->driverpath)) {
1192 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->datafile);
1193 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->datafile);
1194 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1195 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1196 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1197 new_name, old_name));
1198 *perr = (uint32)SVAL(outbuf,smb_err);
1199 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1204 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1208 if (driver->configfile && strlen(driver->configfile)) {
1209 if (!strequal(driver->configfile, driver->driverpath) &&
1210 !strequal(driver->configfile, driver->datafile)) {
1211 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->configfile);
1212 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->configfile);
1213 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1214 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1215 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1216 new_name, old_name));
1217 *perr = (uint32)SVAL(outbuf,smb_err);
1218 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1223 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1227 if (driver->helpfile && strlen(driver->helpfile)) {
1228 if (!strequal(driver->helpfile, driver->driverpath) &&
1229 !strequal(driver->helpfile, driver->datafile) &&
1230 !strequal(driver->helpfile, driver->configfile)) {
1231 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->helpfile);
1232 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->helpfile);
1233 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1234 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1235 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1236 new_name, old_name));
1237 *perr = (uint32)SVAL(outbuf,smb_err);
1238 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1243 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1247 if (driver->dependentfiles) {
1248 for (i=0; *driver->dependentfiles[i]; i++) {
1249 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1250 !strequal(driver->dependentfiles[i], driver->datafile) &&
1251 !strequal(driver->dependentfiles[i], driver->configfile) &&
1252 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1254 for (j=0; j < i; j++) {
1255 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1260 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->dependentfiles[i]);
1261 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->dependentfiles[i]);
1262 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1263 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1264 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1265 new_name, old_name));
1266 *perr = (uint32)SVAL(outbuf,smb_err);
1267 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1272 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1278 close_cnum(conn, user->vuid);
1281 return ver == -1 ? False : True;
1284 /****************************************************************************
1285 ****************************************************************************/
1286 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1289 fstring architecture;
1295 TDB_DATA kbuf, dbuf;
1297 get_short_archi(architecture, driver->environment);
1299 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1300 * \\server is added in the rpc server layer.
1301 * It does make sense to NOT store the server's name in the printer TDB.
1304 slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
1306 /* .inf files do not always list a file for each of the four standard files.
1307 * Don't prepend a path to a null filename, or client claims:
1308 * "The server on which the printer resides does not have a suitable
1309 * <printer driver name> printer driver installed. Click OK if you
1310 * wish to install the driver on your local machine."
1312 if (strlen(driver->driverpath)) {
1313 fstrcpy(temp_name, driver->driverpath);
1314 slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
1317 if (strlen(driver->datafile)) {
1318 fstrcpy(temp_name, driver->datafile);
1319 slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
1322 if (strlen(driver->configfile)) {
1323 fstrcpy(temp_name, driver->configfile);
1324 slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
1327 if (strlen(driver->helpfile)) {
1328 fstrcpy(temp_name, driver->helpfile);
1329 slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
1332 if (driver->dependentfiles) {
1333 for (i=0; *driver->dependentfiles[i]; i++) {
1334 fstrcpy(temp_name, driver->dependentfiles[i]);
1335 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
1339 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1340 dos_to_unix(key, True); /* Convert key to unix-codepage */
1342 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1349 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1352 driver->environment,
1357 driver->monitorname,
1358 driver->defaultdatatype);
1360 if (driver->dependentfiles) {
1361 for (i=0; *driver->dependentfiles[i]; i++) {
1362 len += tdb_pack(buf+len, buflen-len, "f",
1363 driver->dependentfiles[i]);
1367 if (len != buflen) {
1368 buf = (char *)Realloc(buf, len);
1375 kbuf.dsize = strlen(key)+1;
1379 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1382 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1388 /****************************************************************************
1389 ****************************************************************************/
1390 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1392 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1395 info3.cversion = driver->version;
1396 fstrcpy(info3.name,driver->name);
1397 fstrcpy(info3.environment,driver->environment);
1398 fstrcpy(info3.driverpath,driver->driverpath);
1399 fstrcpy(info3.datafile,driver->datafile);
1400 fstrcpy(info3.configfile,driver->configfile);
1401 fstrcpy(info3.helpfile,driver->helpfile);
1402 fstrcpy(info3.monitorname,driver->monitorname);
1403 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1404 info3.dependentfiles = driver->dependentfiles;
1406 return add_a_printer_driver_3(&info3);
1410 /****************************************************************************
1411 ****************************************************************************/
1412 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1414 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1418 fstrcpy(info.name, in_prt);
1419 fstrcpy(info.defaultdatatype, "RAW");
1421 fstrcpy(info.driverpath, "");
1422 fstrcpy(info.datafile, "");
1423 fstrcpy(info.configfile, "");
1424 fstrcpy(info.helpfile, "");
1426 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1427 return ERROR_NOT_ENOUGH_MEMORY;
1429 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1430 fstrcpy(info.dependentfiles[0], "");
1432 *info_ptr = memdup(&info, sizeof(info));
1437 /****************************************************************************
1438 ****************************************************************************/
1439 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1441 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1442 TDB_DATA kbuf, dbuf;
1443 fstring architecture;
1448 ZERO_STRUCT(driver);
1450 get_short_archi(architecture, in_arch);
1452 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1454 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1457 kbuf.dsize = strlen(key)+1;
1459 dbuf = tdb_fetch(tdb, kbuf);
1461 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1463 if (!dbuf.dptr) return 5;
1465 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1474 driver.defaultdatatype);
1477 while (len < dbuf.dsize) {
1478 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
1479 sizeof(fstring)*(i+2));
1480 if (driver.dependentfiles == NULL)
1483 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1484 &driver.dependentfiles[i]);
1487 if (driver.dependentfiles != NULL)
1488 fstrcpy(driver.dependentfiles[i], "");
1490 safe_free(dbuf.dptr);
1492 if (len != dbuf.dsize) {
1493 if (driver.dependentfiles != NULL)
1494 safe_free(driver.dependentfiles);
1496 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1499 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1504 /****************************************************************************
1505 ****************************************************************************/
1506 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1508 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1514 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1515 DEBUG(10,("driver key: [%s]\n", key));
1518 kbuf.dsize = strlen(key)+1;
1519 if (!tdb_exists(tdb, kbuf)) return False;
1522 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1524 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1525 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1526 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1527 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1528 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1529 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1530 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1532 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1533 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1534 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1536 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1537 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1538 pstrcat(line, info3->configfile);
1540 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1541 pstrcat(line, info3->datafile);
1543 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1544 pstrcat(line, info3->helpfile);
1546 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1547 pstrcat(line, info3->monitorname);
1549 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1552 for (i=0; info3->dependentfiles &&
1553 *info3->dependentfiles[i]; i++) {
1554 if (i) pstrcat(line, ","); /* don't end in a "," */
1555 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1556 pstrcat(line, info3->dependentfiles[i]);
1564 /****************************************************************************
1565 debugging function, dump at level 6 the struct in the logs
1566 ****************************************************************************/
1567 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1570 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1573 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1579 if (driver.info_3 == NULL)
1582 info3=driver.info_3;
1584 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1585 DEBUGADD(106,("name:[%s]\n", info3->name));
1586 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1587 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1588 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1589 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1590 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1591 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1592 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1594 for (i=0; info3->dependentfiles &&
1595 *info3->dependentfiles[i]; i++) {
1596 DEBUGADD(106,("dependentfile:[%s]\n",
1597 info3->dependentfiles[i]));
1604 DEBUGADD(1,("Level not implemented\n"));
1612 /****************************************************************************
1613 ****************************************************************************/
1614 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1618 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1620 if (!nt_devmode) return len;
1622 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1623 nt_devmode->devicename,
1624 nt_devmode->formname,
1626 nt_devmode->specversion,
1627 nt_devmode->driverversion,
1629 nt_devmode->driverextra,
1630 nt_devmode->orientation,
1631 nt_devmode->papersize,
1632 nt_devmode->paperlength,
1633 nt_devmode->paperwidth,
1636 nt_devmode->defaultsource,
1637 nt_devmode->printquality,
1640 nt_devmode->yresolution,
1641 nt_devmode->ttoption,
1642 nt_devmode->collate,
1643 nt_devmode->logpixels,
1646 nt_devmode->bitsperpel,
1647 nt_devmode->pelswidth,
1648 nt_devmode->pelsheight,
1649 nt_devmode->displayflags,
1650 nt_devmode->displayfrequency,
1651 nt_devmode->icmmethod,
1652 nt_devmode->icmintent,
1653 nt_devmode->mediatype,
1654 nt_devmode->dithertype,
1655 nt_devmode->reserved1,
1656 nt_devmode->reserved2,
1657 nt_devmode->panningwidth,
1658 nt_devmode->panningheight,
1659 nt_devmode->private);
1662 if (nt_devmode->private) {
1663 len += tdb_pack(buf+len, buflen-len, "B",
1664 nt_devmode->driverextra,
1665 nt_devmode->private);
1668 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1673 /****************************************************************************
1674 ****************************************************************************/
1675 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1679 while (param != NULL) {
1680 len += tdb_pack(buf+len, buflen-len, "pfdB",
1689 len += tdb_pack(buf+len, buflen-len, "p", param);
1695 /****************************************************************************
1696 delete a printer - this just deletes the printer info file, any open
1697 handles are not affected
1698 ****************************************************************************/
1699 uint32 del_a_printer(char *sharename)
1704 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
1705 dos_to_unix(key, True); /* Convert key to unix-codepage */
1708 kbuf.dsize=strlen(key)+1;
1710 tdb_delete(tdb, kbuf);
1714 /* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
1715 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
1716 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
1717 /****************************************************************************
1718 ****************************************************************************/
1719 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1723 int buflen, len, ret;
1724 TDB_DATA kbuf, dbuf;
1727 * in addprinter: no servername and the printer is the name
1728 * in setprinter: servername is \\server
1729 * and printer is \\server\\printer
1731 * Samba manages only local printers.
1732 * we currently don't support things like path=\\other_server\printer
1735 if (info->servername[0]!='\0') {
1736 trim_string(info->printername, info->servername, NULL);
1737 trim_string(info->printername, "\\", NULL);
1738 info->servername[0]='\0';
1742 * JFM: one day I'll forget.
1743 * below that's info->portname because that's the SAMBA sharename
1744 * and I made NT 'thinks' it's the portname
1745 * the info->sharename is the thing you can name when you add a printer
1746 * that's the short-name when you create shared printer for 95/98
1747 * So I've made a limitation in SAMBA: you can only have 1 printer model
1748 * behind a SAMBA share.
1756 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1759 info->default_priority,
1776 info->printprocessor,
1780 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1782 len += pack_specifics(info->specific, buf+len, buflen-len);
1784 if (buflen != len) {
1785 buf = (char *)Realloc(buf, len);
1791 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, info->sharename);
1792 dos_to_unix(key, True); /* Convert key to unix-codepage */
1795 kbuf.dsize = strlen(key)+1;
1799 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1802 DEBUG(8, ("error updating printer to tdb on disk\n"));
1806 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1807 info->sharename, info->drivername, info->portname, len));
1813 /****************************************************************************
1814 ****************************************************************************/
1815 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1817 NT_PRINTER_PARAM *current;
1819 DEBUG(108,("add_a_specific_param\n"));
1821 (*param)->next=NULL;
1823 if (info_2->specific == NULL)
1825 info_2->specific=*param;
1829 current=info_2->specific;
1830 while (current->next != NULL) {
1831 current=current->next;
1833 current->next=*param;
1839 /****************************************************************************
1840 ****************************************************************************/
1841 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1843 NT_PRINTER_PARAM *current;
1844 NT_PRINTER_PARAM *previous;
1846 current=info_2->specific;
1849 if (current==NULL) return (False);
1851 if ( !strcmp(current->value, param->value) &&
1852 (strlen(current->value)==strlen(param->value)) ) {
1853 DEBUG(109,("deleting first value\n"));
1854 info_2->specific=current->next;
1855 safe_free(current->data);
1857 DEBUG(109,("deleted first value\n"));
1861 current=previous->next;
1863 while ( current!=NULL ) {
1864 if (!strcmp(current->value, param->value) &&
1865 strlen(current->value)==strlen(param->value) ) {
1866 DEBUG(109,("deleting current value\n"));
1867 previous->next=current->next;
1868 safe_free(current->data);
1870 DEBUG(109,("deleted current value\n"));
1874 previous=previous->next;
1875 current=current->next;
1880 /****************************************************************************
1881 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
1882 ****************************************************************************/
1883 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
1885 NT_PRINTER_PARAM *param = *param_ptr;
1890 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
1893 safe_free(param->data);
1899 /****************************************************************************
1900 Malloc and return an NT devicemode.
1901 ****************************************************************************/
1903 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
1906 * should I init this ones ???
1907 nt_devmode->devicename
1911 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
1913 if (nt_devmode == NULL) {
1914 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
1918 ZERO_STRUCTP(nt_devmode);
1920 safe_strcpy(adevice, default_devicename, sizeof(adevice));
1921 fstrcpy(nt_devmode->devicename, adevice);
1923 fstrcpy(nt_devmode->formname, "Letter");
1925 nt_devmode->specversion = 0x0401;
1926 nt_devmode->driverversion = 0x0400;
1927 nt_devmode->size = 0x00DC;
1928 nt_devmode->driverextra = 0x0000;
1929 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
1930 DEFAULTSOURCE | COPIES | SCALE |
1931 PAPERSIZE | ORIENTATION;
1932 nt_devmode->orientation = 1;
1933 nt_devmode->papersize = PAPER_LETTER;
1934 nt_devmode->paperlength = 0;
1935 nt_devmode->paperwidth = 0;
1936 nt_devmode->scale = 0x64;
1937 nt_devmode->copies = 01;
1938 nt_devmode->defaultsource = BIN_FORMSOURCE;
1939 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
1940 nt_devmode->color = COLOR_MONOCHROME;
1941 nt_devmode->duplex = DUP_SIMPLEX;
1942 nt_devmode->yresolution = 0;
1943 nt_devmode->ttoption = TT_SUBDEV;
1944 nt_devmode->collate = COLLATE_FALSE;
1945 nt_devmode->icmmethod = 0;
1946 nt_devmode->icmintent = 0;
1947 nt_devmode->mediatype = 0;
1948 nt_devmode->dithertype = 0;
1950 /* non utilisés par un driver d'imprimante */
1951 nt_devmode->logpixels = 0;
1952 nt_devmode->bitsperpel = 0;
1953 nt_devmode->pelswidth = 0;
1954 nt_devmode->pelsheight = 0;
1955 nt_devmode->displayflags = 0;
1956 nt_devmode->displayfrequency = 0;
1957 nt_devmode->reserved1 = 0;
1958 nt_devmode->reserved2 = 0;
1959 nt_devmode->panningwidth = 0;
1960 nt_devmode->panningheight = 0;
1962 nt_devmode->private = NULL;
1966 /****************************************************************************
1967 Deepcopy an NT devicemode.
1968 ****************************************************************************/
1970 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
1972 NT_DEVICEMODE *new_nt_devicemode = NULL;
1974 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
1975 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1979 new_nt_devicemode->private = NULL;
1980 if (nt_devicemode->private != NULL) {
1981 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
1982 safe_free(new_nt_devicemode);
1983 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1988 return new_nt_devicemode;
1991 /****************************************************************************
1992 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
1993 ****************************************************************************/
1995 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
1997 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
1999 if(nt_devmode == NULL)
2002 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
2004 if(nt_devmode->private)
2005 safe_free(nt_devmode->private);
2007 safe_free(nt_devmode);
2008 *devmode_ptr = NULL;
2011 /****************************************************************************
2012 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
2013 ****************************************************************************/
2014 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
2016 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
2017 NT_PRINTER_PARAM *param_ptr;
2022 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
2024 free_nt_devicemode(&info->devmode);
2026 for(param_ptr = info->specific; param_ptr; ) {
2027 NT_PRINTER_PARAM *tofree = param_ptr;
2029 param_ptr = param_ptr->next;
2030 free_nt_printer_param(&tofree);
2033 safe_free(*info_ptr);
2038 /****************************************************************************
2039 ****************************************************************************/
2040 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2044 NT_DEVICEMODE devmode;
2046 ZERO_STRUCT(devmode);
2048 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2050 if (!*nt_devmode) return len;
2052 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2056 &devmode.specversion,
2057 &devmode.driverversion,
2059 &devmode.driverextra,
2060 &devmode.orientation,
2062 &devmode.paperlength,
2063 &devmode.paperwidth,
2066 &devmode.defaultsource,
2067 &devmode.printquality,
2070 &devmode.yresolution,
2076 &devmode.bitsperpel,
2078 &devmode.pelsheight,
2079 &devmode.displayflags,
2080 &devmode.displayfrequency,
2084 &devmode.dithertype,
2087 &devmode.panningwidth,
2088 &devmode.panningheight,
2091 if (devmode.private) {
2092 /* the len in tdb_unpack is an int value and
2093 * devmode.driverextra is only a short
2095 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2096 devmode.driverextra=(uint16)extra_len;
2098 /* check to catch an invalid TDB entry so we don't segfault */
2099 if (devmode.driverextra == 0) {
2100 devmode.private = NULL;
2104 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2106 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2107 if (devmode.private)
2108 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2113 /****************************************************************************
2114 ****************************************************************************/
2115 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2118 NT_PRINTER_PARAM param, *p;
2123 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2126 len += tdb_unpack(buf+len, buflen-len, "fdB",
2132 *list = memdup(¶m, sizeof(param));
2134 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2141 /****************************************************************************
2142 get a default printer info 2 struct
2143 ****************************************************************************/
2144 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2146 extern pstring global_myname;
2148 NT_PRINTER_INFO_LEVEL_2 info;
2152 snum = lp_servicenumber(sharename);
2154 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2155 slprintf(info.printername, sizeof(info.printername), "\\\\%s\\%s",
2156 global_myname, sharename);
2157 fstrcpy(info.sharename, sharename);
2158 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2159 fstrcpy(info.drivername, lp_printerdriver(snum));
2161 if (!*info.drivername)
2162 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2164 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2166 pstrcpy(info.comment, "");
2167 fstrcpy(info.printprocessor, "winprint");
2168 fstrcpy(info.datatype, "RAW");
2170 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2171 | PRINTER_ATTRIBUTE_LOCAL \
2172 | PRINTER_ATTRIBUTE_RAW_ONLY \
2173 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2175 info.starttime = 0; /* Minutes since 12:00am GMT */
2176 info.untiltime = 0; /* Minutes since 12:00am GMT */
2178 info.default_priority = 1;
2179 info.setuptime = (uint32)time(NULL);
2181 #if 1 /* JRA - NO NOT CHANGE ! */
2182 info.devmode = NULL;
2185 * We should not return a default devicemode, as this causes
2186 * Win2K to not send the correct one on PCL drivers. It needs to
2187 * see a null devicemode so it can then overwrite the devicemode
2188 * on OpenPrinterEx. Yes this *is* insane :-). JRA.
2190 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2194 /* This will get the current RPC talloc context, but we should be
2195 passing this as a parameter... fixme... JRA ! */
2197 if (!nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf))
2200 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2202 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2211 free_nt_devicemode(&info.devmode);
2215 /****************************************************************************
2216 ****************************************************************************/
2217 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2220 NT_PRINTER_INFO_LEVEL_2 info;
2222 TDB_DATA kbuf, dbuf;
2223 fstring printername;
2227 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
2228 dos_to_unix(key, True); /* Convert key to unix-codepage */
2231 kbuf.dsize = strlen(key)+1;
2233 dbuf = tdb_fetch(tdb, kbuf);
2235 return get_a_printer_2_default(info_ptr, sharename);
2237 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2240 &info.default_priority,
2257 info.printprocessor,
2261 /* Samba has to have shared raw drivers. */
2262 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2264 /* Restore the stripped strings. */
2265 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2266 slprintf(printername, sizeof(printername), "\\\\%s\\%s", global_myname,
2268 fstrcpy(info.printername, printername);
2270 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2271 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2273 /* This will get the current RPC talloc context, but we should be
2274 passing this as a parameter... fixme... JRA ! */
2276 nt_printing_getsec(get_talloc_ctx(), sharename, &info.secdesc_buf);
2278 safe_free(dbuf.dptr);
2279 *info_ptr=memdup(&info, sizeof(info));
2281 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2282 sharename, info.printername, info.drivername));
2288 /****************************************************************************
2289 debugging function, dump at level 6 the struct in the logs
2290 ****************************************************************************/
2291 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2294 NT_PRINTER_INFO_LEVEL_2 *info2;
2296 DEBUG(106,("Dumping printer at level [%d]\n", level));
2302 if (printer.info_2 == NULL)
2306 info2=printer.info_2;
2308 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2309 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2310 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2311 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2312 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2313 DEBUGADD(106,("status:[%d]\n", info2->status));
2314 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2315 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2316 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2317 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2318 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2320 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2321 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2322 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2323 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2324 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2325 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2326 DEBUGADD(106,("location:[%s]\n", info2->location));
2327 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2328 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2329 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2330 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2336 DEBUGADD(1,("Level not implemented\n"));
2344 /****************************************************************************
2345 Get the parameters we can substitute in an NT print job.
2346 ****************************************************************************/
2348 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2350 NT_PRINTER_INFO_LEVEL *printer = NULL;
2352 **printername = **sharename = **portname = '\0';
2354 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2357 fstrcpy(*printername, printer->info_2->printername);
2358 fstrcpy(*sharename, printer->info_2->sharename);
2359 fstrcpy(*portname, printer->info_2->portname);
2361 free_a_printer(&printer, 2);
2365 * The function below are the high level ones.
2366 * only those ones must be called from the spoolss code.
2370 /****************************************************************************
2371 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2372 ****************************************************************************/
2374 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2378 dump_a_printer(printer, level);
2384 printer.info_2->c_setprinter++;
2385 result=update_a_printer_2(printer.info_2);
2396 /****************************************************************************
2397 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2398 We split this out from mod_a_printer as it updates the id's and timestamps.
2399 ****************************************************************************/
2401 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2405 dump_a_printer(printer, level);
2412 * Update the changestamp.
2413 * Note we must *not* do this in mod_a_printer().
2416 time_t time_unix = time(NULL);
2417 unix_to_nt_time(&time_nt, time_unix);
2418 if (printer.info_2->changeid==time_nt.low)
2419 printer.info_2->changeid++;
2421 printer.info_2->changeid=time_nt.low;
2423 printer.info_2->c_setprinter++;
2425 result=update_a_printer_2(printer.info_2);
2436 /****************************************************************************
2437 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2438 ****************************************************************************/
2440 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2443 NT_PRINTER_INFO_LEVEL *printer = NULL;
2447 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
2453 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
2454 DEBUG(0,("get_a_printer: malloc fail.\n"));
2457 ZERO_STRUCTP(printer);
2458 result=get_a_printer_2(&printer->info_2, sharename);
2460 dump_a_printer(*printer, level);
2461 *pp_printer = printer;
2472 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
2477 /****************************************************************************
2478 Deletes a NT_PRINTER_INFO_LEVEL struct.
2479 ****************************************************************************/
2481 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
2484 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
2486 DEBUG(104,("freeing a printer at level [%d]\n", level));
2488 if (printer == NULL)
2495 if (printer->info_2 != NULL)
2497 free_nt_printer_info_level_2(&printer->info_2);
2516 /****************************************************************************
2517 ****************************************************************************/
2518 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2521 DEBUG(104,("adding a printer at level [%d]\n", level));
2522 dump_a_printer_driver(driver, level);
2528 result=add_a_printer_driver_3(driver.info_3);
2534 result=add_a_printer_driver_6(driver.info_6);
2544 /****************************************************************************
2545 ****************************************************************************/
2546 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2547 fstring printername, fstring architecture, uint32 version)
2555 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2564 dump_a_printer_driver(*driver, level);
2568 /****************************************************************************
2569 ****************************************************************************/
2570 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2578 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2579 if (driver.info_3 != NULL)
2581 info3=driver.info_3;
2582 safe_free(info3->dependentfiles);
2583 ZERO_STRUCTP(info3);
2595 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2596 if (driver.info_6 != NULL)
2598 info6=driver.info_6;
2599 safe_free(info6->dependentfiles);
2600 safe_free(info6->previousnames);
2601 ZERO_STRUCTP(info6);
2618 /****************************************************************************
2619 ****************************************************************************/
2620 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2621 fstring value, uint8 **data, uint32 *type, uint32 *len)
2623 /* right now that's enough ! */
2624 NT_PRINTER_PARAM *param;
2627 param=printer.info_2->specific;
2629 while (param != NULL && i < param_index) {
2637 /* exited because it exist */
2639 StrnCpy(value, param->value, sizeof(fstring)-1);
2640 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2643 ZERO_STRUCTP(*data);
2644 memcpy(*data, param->data, param->data_len);
2645 *len=param->data_len;
2649 /****************************************************************************
2650 ****************************************************************************/
2651 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2652 fstring value, uint8 **data, uint32 *type, uint32 *len)
2654 /* right now that's enough ! */
2655 NT_PRINTER_PARAM *param;
2657 DEBUG(10, ("get_specific_param\n"));
2659 param=printer.info_2->specific;
2661 while (param != NULL)
2663 #if 1 /* JRA - I think this should be case insensitive.... */
2664 if ( strequal(value, param->value)
2666 if ( !strcmp(value, param->value)
2668 && strlen(value)==strlen(param->value))
2676 DEBUGADD(10, ("get_specific_param: found one param\n"));
2677 /* exited because it exist */
2680 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2683 memcpy(*data, param->data, param->data_len);
2684 *len=param->data_len;
2686 DEBUGADD(10, ("get_specific_param: exit true\n"));
2689 DEBUGADD(10, ("get_specific_param: exit false\n"));
2693 /****************************************************************************
2694 Store a security desc for a printer.
2695 ****************************************************************************/
2697 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
2699 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2700 SEC_DESC_BUF *old_secdesc_ctr = NULL;
2702 TALLOC_CTX *mem_ctx = NULL;
2706 mem_ctx = talloc_init();
2707 if (mem_ctx == NULL)
2710 /* The old owner and group sids of the security descriptor are not
2711 present when new ACEs are added or removed by changing printer
2712 permissions through NT. If they are NULL in the new security
2713 descriptor then copy them over from the old one. */
2715 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
2716 DOM_SID *owner_sid, *group_sid;
2717 SEC_ACL *dacl, *sacl;
2718 SEC_DESC *psd = NULL;
2721 nt_printing_getsec(mem_ctx, printername, &old_secdesc_ctr);
2723 /* Pick out correct owner and group sids */
2725 owner_sid = secdesc_ctr->sec->owner_sid ?
2726 secdesc_ctr->sec->owner_sid :
2727 old_secdesc_ctr->sec->owner_sid;
2729 group_sid = secdesc_ctr->sec->grp_sid ?
2730 secdesc_ctr->sec->grp_sid :
2731 old_secdesc_ctr->sec->grp_sid;
2733 dacl = secdesc_ctr->sec->dacl ?
2734 secdesc_ctr->sec->dacl :
2735 old_secdesc_ctr->sec->dacl;
2737 sacl = secdesc_ctr->sec->sacl ?
2738 secdesc_ctr->sec->sacl :
2739 old_secdesc_ctr->sec->sacl;
2741 /* Make a deep copy of the security descriptor */
2743 psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision,
2744 owner_sid, group_sid,
2749 new_secdesc_ctr = make_sec_desc_buf(mem_ctx, size, psd);
2752 if (!new_secdesc_ctr) {
2753 new_secdesc_ctr = secdesc_ctr;
2756 /* Store the security descriptor in a tdb */
2758 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
2759 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
2761 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
2763 status = ERROR_INVALID_FUNCTION;
2767 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2769 if (tdb_prs_store(tdb, key, &ps)==0) {
2772 DEBUG(1,("Failed to store secdesc for %s\n", printername));
2773 status = ERROR_INVALID_FUNCTION;
2776 /* Free mallocated memory */
2782 talloc_destroy(mem_ctx);
2786 /****************************************************************************
2787 Construct a default security descriptor buffer for a printer.
2788 ****************************************************************************/
2790 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
2794 SEC_ACL *psa = NULL;
2795 SEC_DESC_BUF *sdb = NULL;
2796 SEC_DESC *psd = NULL;
2799 enum SID_NAME_USE name_type;
2801 /* Create an ACE where Everyone is allowed to print */
2803 init_sec_access(&sa, PRINTER_ACE_PRINT);
2804 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2805 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2807 /* Make the security descriptor owned by the Administrators group
2808 on the PDC of the domain. */
2810 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
2811 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2814 /* Backup plan - make printer owned by admins or root. This should
2815 emulate a lanman printer as security settings can't be
2818 if (!lookup_name( "Printer Administrators", &owner_sid, &name_type) &&
2819 !lookup_name( "Administrators", &owner_sid, &name_type) &&
2820 !lookup_name( "Administrator", &owner_sid, &name_type) &&
2821 !lookup_name("root", &owner_sid, &name_type)) {
2822 sid_copy(&owner_sid, &global_sid_World);
2826 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
2827 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2828 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
2829 SEC_ACE_FLAG_INHERIT_ONLY);
2831 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
2832 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2833 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2835 /* The ACL revision number in rpc_secdesc.h differs from the one
2836 created by NT when setting ACE entries in printer
2837 descriptors. NT4 complains about the property being edited by a
2840 if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) {
2841 psd = make_sec_desc(ctx, SEC_DESC_REVISION,
2843 NULL, psa, &sd_size);
2847 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2851 sdb = make_sec_desc_buf(ctx, sd_size, psd);
2853 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2854 (unsigned int)sd_size));
2859 /****************************************************************************
2860 Get a security desc for a printer.
2861 ****************************************************************************/
2863 BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
2869 if ((temp = strchr(printername + 2, '\\'))) {
2870 printername = temp + 1;
2873 /* Fetch security descriptor from tdb */
2875 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2877 if (tdb_prs_fetch(tdb, key, &ps, ctx)!=0 ||
2878 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
2880 DEBUG(4,("using default secdesc for %s\n", printername));
2882 if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
2889 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2890 this security descriptor has been created when winbindd was
2891 down. Take ownership of security descriptor. */
2893 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
2895 enum SID_NAME_USE name_type;
2897 /* Change sd owner to workgroup administrator */
2899 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
2901 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2902 SEC_DESC *psd = NULL;
2907 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2909 psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision,
2911 (*secdesc_ctr)->sec->grp_sid,
2912 (*secdesc_ctr)->sec->sacl,
2913 (*secdesc_ctr)->sec->dacl,
2916 new_secdesc_ctr = make_sec_desc_buf(ctx, size, psd);
2918 /* Swap with other one */
2920 *secdesc_ctr = new_secdesc_ctr;
2924 nt_printing_setsec(printername, *secdesc_ctr);
2928 if (DEBUGLEVEL >= 10) {
2929 SEC_ACL *acl = (*secdesc_ctr)->sec->dacl;
2932 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
2933 printername, acl->num_aces));
2935 for (i = 0; i < acl->num_aces; i++) {
2938 sid_to_string(sid_str, &acl->ace[i].sid);
2940 DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
2941 acl->ace[i].type, acl->ace[i].flags,
2942 acl->ace[i].info.mask));
2952 1: level not implemented
2953 2: file doesn't exist
2954 3: can't allocate memory
2955 4: can't free memory
2956 5: non existant struct
2960 A printer and a printer driver are 2 different things.
2961 NT manages them separatelly, Samba does the same.
2962 Why ? Simply because it's easier and it makes sense !
2964 Now explanation: You have 3 printers behind your samba server,
2965 2 of them are the same make and model (laser A and B). But laser B
2966 has an 3000 sheet feeder and laser A doesn't such an option.
2967 Your third printer is an old dot-matrix model for the accounting :-).
2969 If the /usr/local/samba/lib directory (default dir), you will have
2970 5 files to describe all of this.
2972 3 files for the printers (1 by printer):
2975 NTprinter_accounting
2976 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2977 NTdriver_printer model X
2978 NTdriver_printer model Y
2980 jfm: I should use this comment for the text file to explain
2981 same thing for the forms BTW.
2982 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2986 /* Convert generic access rights to printer object specific access rights.
2987 It turns out that NT4 security descriptors use generic access rights and
2988 NT5 the object specific ones. */
2990 void map_printer_permissions(SEC_DESC *sd)
2994 for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) {
2995 se_map_generic(&sd->dacl->ace[i].info.mask,
2996 &printer_generic_mapping);
3000 /****************************************************************************
3001 Check a user has permissions to perform the given operation. We use the
3002 permission constants defined in include/rpc_spoolss.h to check the various
3003 actions we perform when checking printer access.
3005 PRINTER_ACCESS_ADMINISTER:
3006 print_queue_pause, print_queue_resume, update_printer_sec,
3007 update_printer, spoolss_addprinterex_level_2,
3008 _spoolss_setprinterdata
3013 JOB_ACCESS_ADMINISTER:
3014 print_job_delete, print_job_pause, print_job_resume,
3017 ****************************************************************************/
3018 BOOL print_access_check(struct current_user *user, int snum, int access_type)
3020 SEC_DESC_BUF *secdesc = NULL;
3021 uint32 access_granted, status;
3024 TALLOC_CTX *mem_ctx = NULL;
3025 extern struct current_user current_user;
3027 /* If user is NULL then use the current_user structure */
3029 if (!user) user = ¤t_user;
3031 /* Always allow root or printer admins to do anything */
3033 if (user->uid == 0 ||
3034 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
3038 /* Get printer name */
3040 pname = PRINTERNAME(snum);
3042 if (!pname || !*pname) {
3047 /* Get printer security descriptor */
3049 if(!(mem_ctx = talloc_init())) {
3054 nt_printing_getsec(mem_ctx, pname, &secdesc);
3056 if (access_type == JOB_ACCESS_ADMINISTER) {
3057 SEC_DESC_BUF *parent_secdesc = secdesc;
3059 /* Create a child security descriptor to check permissions
3060 against. This is because print jobs are child objects
3061 objects of a printer. */
3063 secdesc = se_create_child_secdesc(mem_ctx, parent_secdesc->sec, False);
3065 /* Now this is the bit that really confuses me. The access
3066 type needs to be changed from JOB_ACCESS_ADMINISTER to
3067 PRINTER_ACCESS_ADMINISTER for this to work. Something
3068 to do with the child (job) object becoming like a
3071 access_type = PRINTER_ACCESS_ADMINISTER;
3076 map_printer_permissions(secdesc->sec);
3078 result = se_access_check(secdesc->sec, user, access_type,
3079 &access_granted, &status);
3081 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3083 talloc_destroy(mem_ctx);
3091 /****************************************************************************
3092 Check the time parameters allow a print operation.
3093 *****************************************************************************/
3095 BOOL print_time_access_check(int snum)
3097 NT_PRINTER_INFO_LEVEL *printer = NULL;
3099 time_t now = time(NULL);
3103 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3106 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3110 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3112 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3115 free_a_printer(&printer, 2);
3123 /****************************************************************************
3124 Attempt to write a default device.
3125 *****************************************************************************/
3127 uint32 printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
3129 NT_PRINTER_INFO_LEVEL *printer = NULL;
3134 * Don't bother if no default devicemode was sent.
3137 if (printer_default->devmode_cont.devmode == NULL)
3140 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3141 return ERROR_ACCESS_DENIED;
3144 * Just ignore it if we already have a devmode.
3147 if (printer->info_2->devmode != NULL)
3151 * We don't have a devicemode and we're trying to write
3152 * one. Check we have the access needed.
3154 DEBUG(5,("printer_write_default_dev: access: %x\n", printer_default->access_required));
3156 if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
3157 PRINTER_ACCESS_ADMINISTER) {
3158 DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
3159 result = ERROR_ACCESS_DENIED;
3163 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
3164 DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
3165 lp_servicename(snum) ));
3166 result = ERROR_ACCESS_DENIED;
3167 /*result = NT_STATUS_NO_PROBLEMO;*/
3171 DEBUG(5,("printer_write_default_dev: updating, check OK.\n"));
3174 * Convert the on the wire devicemode format to the internal one.
3177 if (!convert_devicemode(printer->info_2->printername,
3178 printer_default->devmode_cont.devmode,
3179 &printer->info_2->devmode)) {
3180 result = ERROR_NOT_ENOUGH_MEMORY;
3185 * Finally write back to the tdb.
3188 if (add_a_printer(*printer, 2)!=0) {
3189 result = ERROR_ACCESS_DENIED;
3195 free_a_printer(&printer, 2);