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 && update==False; n++)
168 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
170 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
177 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
179 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
183 (*list)[n].flag=form->flags;
184 (*list)[n].width=form->size_x;
185 (*list)[n].length=form->size_y;
186 (*list)[n].left=form->left;
187 (*list)[n].top=form->top;
188 (*list)[n].right=form->right;
189 (*list)[n].bottom=form->bottom;
194 /****************************************************************************
195 delete a named form struct
196 ****************************************************************************/
197 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
208 * Don't delete the last form (no empty lists).
209 * CHECKME ! Is this correct ? JRA.
211 *ret = ERROR_INVALID_PARAMETER;
215 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
217 for (n=0; n<*count; n++) {
218 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
219 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
225 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
226 *ret = ERROR_INVALID_PARAMETER;
230 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[n].name);
231 kbuf.dsize = strlen(key)+1;
233 if (tdb_delete(tdb, kbuf) != 0) {
234 *ret = ERROR_NOT_ENOUGH_MEMORY;
241 /****************************************************************************
243 ****************************************************************************/
244 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
248 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
250 DEBUG(106, ("[%s]\n", form_name));
251 for (n=0; n<count; n++)
253 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
254 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
258 if (n==count) return;
260 (*list)[n].flag=form->flags;
261 (*list)[n].width=form->size_x;
262 (*list)[n].length=form->size_y;
263 (*list)[n].left=form->left;
264 (*list)[n].top=form->top;
265 (*list)[n].right=form->right;
266 (*list)[n].bottom=form->bottom;
269 /****************************************************************************
270 get the nt drivers list
272 traverse the database and look-up the matching names
273 ****************************************************************************/
274 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
279 TDB_DATA kbuf, newkey;
281 get_short_archi(short_archi, architecture);
282 slprintf(key, sizeof(key), "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
284 for (kbuf = tdb_firstkey(tdb);
286 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
287 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
289 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
292 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
299 /****************************************************************************
300 function to do the mapping between the long architecture name and
302 ****************************************************************************/
303 BOOL get_short_archi(char *short_archi, char *long_archi)
310 struct table archi_table[]=
312 {"Windows 4.0", "WIN40" },
313 {"Windows NT x86", "W32X86" },
314 {"Windows NT R4000", "W32MIPS" },
315 {"Windows NT Alpha_AXP", "W32ALPHA" },
316 {"Windows NT PowerPC", "W32PPC" },
322 DEBUG(107,("Getting architecture dependant directory\n"));
325 } while ( (archi_table[i].long_archi!=NULL ) &&
326 StrCaseCmp(long_archi, archi_table[i].long_archi) );
328 if (archi_table[i].long_archi==NULL) {
329 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
333 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
335 DEBUGADD(108,("index: [%d]\n", i));
336 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
337 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
342 /****************************************************************************
343 Determine the correct cVersion associated with an architecture and driver
344 ****************************************************************************/
345 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in)
351 char buf[PE_HEADER_SIZE];
354 /* If architecture is Windows 95/98, the version is always 0. */
355 if (strcmp(architecture, "WIN40") == 0) {
356 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
360 /* Open the driver file (Portable Executable format) and determine the
361 * deriver the cversion.
363 if ((service = find_service("print$")) == -1) {
364 DEBUG(3,("get_correct_cversion: Can't find print$ service\n"));
368 slprintf(driverpath, sizeof(driverpath), "%s/%s/%s",
369 lp_pathname(service), architecture, driverpath_in);
371 dos_to_unix(driverpath, True);
373 if ((fd = sys_open(driverpath, O_RDONLY, 0)) == -1) {
374 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
379 if ((byte_count = read(fd, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
380 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
381 driverpath, byte_count));
385 /* Is this really a DOS header? */
386 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
387 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
388 driverpath, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
392 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
393 if (sys_lseek(fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
394 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
399 if ((byte_count = read(fd, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
400 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
401 driverpath, byte_count));
406 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
407 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
408 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) == PE_HEADER_MACHINE_I386) {
410 switch (SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)) {
411 case 4: cversion = 2; break; /* Win NT 4 */
412 case 5: cversion = 3; break; /* Win 2000 */
414 DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
415 driverpath, SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)));
419 DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
420 driverpath, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
424 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
425 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) == NE_HEADER_TARGOS_WIN ) {
427 switch (CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)) {
428 case 3: cversion = 0; break; /* Win 3.x / Win 9x / Win ME */
429 /* case ?: cversion = 1; break;*/ /* Win NT 3.51 ... needs research JRR */
431 DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
432 driverpath, CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)));
436 DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
437 driverpath, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
442 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
443 driverpath, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
447 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
448 driverpath, cversion));
458 /****************************************************************************
459 ****************************************************************************/
460 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
462 fstring architecture;
467 /* clean up the driver name.
468 * we can get .\driver.dll
469 * or worse c:\windows\system\driver.dll !
471 /* using an intermediate string to not have overlaping memcpy()'s */
472 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
473 fstrcpy(new_name, p+1);
474 fstrcpy(driver->driverpath, new_name);
477 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
478 fstrcpy(new_name, p+1);
479 fstrcpy(driver->datafile, new_name);
482 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
483 fstrcpy(new_name, p+1);
484 fstrcpy(driver->configfile, new_name);
487 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
488 fstrcpy(new_name, p+1);
489 fstrcpy(driver->helpfile, new_name);
492 if (driver->dependentfiles) {
493 for (i=0; *driver->dependentfiles[i]; i++) {
494 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
495 fstrcpy(new_name, p+1);
496 fstrcpy(driver->dependentfiles[i], new_name);
501 get_short_archi(architecture, driver->environment);
503 /* jfm:7/16/2000 the client always sends the cversion=0.
504 * The server should check which version the driver is by reading
505 * the PE header of driver->driverpath.
507 * For Windows 95/98 the version is 0 (so the value sent is correct)
508 * For Windows NT (the architecture doesn't matter)
510 * NT 3.5/3.51: cversion=1
514 if ((driver->cversion = get_correct_cversion(architecture,
515 driver->driverpath)) == -1)
516 return NT_STATUS_FILE_INVALID; /* Not the best error. Fix JRR */
518 return NT_STATUS_NO_PROBLEMO;
521 /****************************************************************************
522 ****************************************************************************/
523 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
525 fstring architecture;
530 /* clean up the driver name.
531 * we can get .\driver.dll
532 * or worse c:\windows\system\driver.dll !
534 /* using an intermediate string to not have overlaping memcpy()'s */
535 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
536 fstrcpy(new_name, p+1);
537 fstrcpy(driver->driverpath, new_name);
540 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
541 fstrcpy(new_name, p+1);
542 fstrcpy(driver->datafile, new_name);
545 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
546 fstrcpy(new_name, p+1);
547 fstrcpy(driver->configfile, new_name);
550 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
551 fstrcpy(new_name, p+1);
552 fstrcpy(driver->helpfile, new_name);
555 if (driver->dependentfiles) {
556 for (i=0; *driver->dependentfiles[i]; i++) {
557 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
558 fstrcpy(new_name, p+1);
559 fstrcpy(driver->dependentfiles[i], new_name);
564 get_short_archi(architecture, driver->environment);
566 /* jfm:7/16/2000 the client always sends the cversion=0.
567 * The server should check which version the driver is by reading
568 * the PE header of driver->driverpath.
570 * For Windows 95/98 the version is 0 (so the value sent is correct)
571 * For Windows NT (the architecture doesn't matter)
573 * NT 3.5/3.51: cversion=1
577 if ((driver->version = get_correct_cversion(architecture,
578 driver->driverpath)) == -1)
579 return NT_STATUS_FILE_INVALID; /* Not the best error. Fix JRR */
581 return NT_STATUS_NO_PROBLEMO;
584 /****************************************************************************
585 ****************************************************************************/
586 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level)
591 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
592 driver=driver_abstract.info_3;
593 return clean_up_driver_struct_level_3(driver);
598 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
599 driver=driver_abstract.info_6;
600 return clean_up_driver_struct_level_6(driver);
604 return ERROR_INVALID_PARAMETER;
608 /****************************************************************************
609 This function sucks and should be replaced. JRA.
610 ****************************************************************************/
612 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
614 dst->cversion = src->version;
616 fstrcpy( dst->name, src->name);
617 fstrcpy( dst->environment, src->environment);
618 fstrcpy( dst->driverpath, src->driverpath);
619 fstrcpy( dst->datafile, src->datafile);
620 fstrcpy( dst->configfile, src->configfile);
621 fstrcpy( dst->helpfile, src->helpfile);
622 fstrcpy( dst->monitorname, src->monitorname);
623 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
624 dst->dependentfiles = src->dependentfiles;
628 /****************************************************************************
629 ****************************************************************************/
630 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
632 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
633 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
634 fstring architecture;
640 connection_struct *conn;
649 memset(inbuf, '\0', sizeof(inbuf));
650 memset(outbuf, '\0', sizeof(outbuf));
653 driver=driver_abstract.info_3;
655 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
656 driver = &converted_driver;
658 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
662 get_short_archi(architecture, driver->environment);
665 pass = getpwuid(user->uid);
667 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
668 (unsigned int)user->uid ));
674 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
675 fstrcpy(user_name, pass->pw_name );
676 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
678 /* Null password is ok - we are already an authenticated user... */
680 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
683 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
684 *perr = (uint32)ecode;
689 * Save who we are - we are temporarily becoming the connection user.
694 if (!become_user(conn, conn->vuid)) {
695 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
701 * make the directories version and version\driver_name
702 * under the architecture directory.
704 DEBUG(5,("Creating first directory\n"));
705 slprintf(new_dir, sizeof(new_dir), "%s\\%d", architecture, driver->cversion);
706 mkdir_internal(conn, inbuf, outbuf, new_dir);
708 /* move all the files, one by one,
709 * from archi\filexxx.yyy to
710 * archi\version\filexxx.yyy
712 * Note: drivers may list the same file name in several places. This
713 * causes problems on a second attempt to move the file. JRR
715 * Note: use the replace flag on rename_internals() call, otherwise it
716 * is very difficult to change previously installed drivers... the Windows
717 * GUI offers the user the choice to replace or keep exisitng driver. JRR
720 DEBUG(5,("Moving file now !\n"));
722 if (driver->driverpath && strlen(driver->driverpath)) {
723 slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->driverpath);
724 slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->driverpath);
725 if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
726 DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
727 old_name, new_name ));
728 close_cnum(conn, user->vuid);
730 *perr = (uint32)SVAL(outbuf,smb_err);
735 if (driver->datafile && strlen(driver->datafile)) {
736 if (!strequal(driver->datafile, driver->driverpath)) {
737 slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->datafile);
738 slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->datafile);
739 if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
740 DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
741 old_name, new_name ));
742 close_cnum(conn, user->vuid);
744 *perr = (uint32)SVAL(outbuf,smb_err);
750 if (driver->configfile && strlen(driver->configfile)) {
751 if (!strequal(driver->configfile, driver->driverpath) &&
752 !strequal(driver->configfile, driver->datafile)) {
753 slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->configfile);
754 slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->configfile);
755 if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
756 DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
757 old_name, new_name ));
758 close_cnum(conn, user->vuid);
760 *perr = (uint32)SVAL(outbuf,smb_err);
766 if (driver->helpfile && strlen(driver->helpfile)) {
767 if (!strequal(driver->helpfile, driver->driverpath) &&
768 !strequal(driver->helpfile, driver->datafile) &&
769 !strequal(driver->helpfile, driver->configfile)) {
770 slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->helpfile);
771 slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->helpfile);
772 if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
773 DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
774 old_name, new_name ));
775 close_cnum(conn, user->vuid);
777 *perr = (uint32)SVAL(outbuf,smb_err);
783 if (driver->dependentfiles) {
784 for (i=0; *driver->dependentfiles[i]; i++) {
785 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
786 !strequal(driver->dependentfiles[i], driver->datafile) &&
787 !strequal(driver->dependentfiles[i], driver->configfile) &&
788 !strequal(driver->dependentfiles[i], driver->helpfile)) {
790 for (j=0; j < i; j++) {
791 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
796 slprintf(old_name, sizeof(old_name), "%s\\%s", architecture, driver->dependentfiles[i]);
797 slprintf(new_name, sizeof(new_name), "%s\\%s", new_dir, driver->dependentfiles[i]);
798 if ((outsize = rename_internals(conn, inbuf, outbuf, old_name, new_name, True)) != 0) {
799 DEBUG(0,("move_driver_to_download_area: Unable to rename %s to %s\n",
800 old_name, new_name ));
801 close_cnum(conn, user->vuid);
803 *perr = (uint32)SVAL(outbuf,smb_err);
811 close_cnum(conn, user->vuid);
817 /****************************************************************************
818 ****************************************************************************/
819 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
822 fstring architecture;
830 get_short_archi(architecture, driver->environment);
832 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
833 * \\server is added in the rpc server layer.
834 * It does make sense to NOT store the server's name in the printer TDB.
837 slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
840 fstrcpy(temp_name, driver->driverpath);
841 slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
843 fstrcpy(temp_name, driver->datafile);
844 slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
846 fstrcpy(temp_name, driver->configfile);
847 slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
849 fstrcpy(temp_name, driver->helpfile);
850 slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
852 if (driver->dependentfiles) {
853 for (i=0; *driver->dependentfiles[i]; i++) {
854 fstrcpy(temp_name, driver->dependentfiles[i]);
855 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
859 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
861 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
868 len += tdb_pack(buf+len, buflen-len, "dffffffff",
877 driver->defaultdatatype);
879 if (driver->dependentfiles) {
880 for (i=0; *driver->dependentfiles[i]; i++) {
881 len += tdb_pack(buf+len, buflen-len, "f",
882 driver->dependentfiles[i]);
887 buf = (char *)Realloc(buf, len);
894 kbuf.dsize = strlen(key)+1;
898 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
901 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
907 /****************************************************************************
908 ****************************************************************************/
909 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
911 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
914 info3.cversion = driver->version;
915 fstrcpy(info3.name,driver->name);
916 fstrcpy(info3.environment,driver->environment);
917 fstrcpy(info3.driverpath,driver->driverpath);
918 fstrcpy(info3.datafile,driver->datafile);
919 fstrcpy(info3.configfile,driver->configfile);
920 fstrcpy(info3.helpfile,driver->helpfile);
921 fstrcpy(info3.monitorname,driver->monitorname);
922 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
923 info3.dependentfiles = driver->dependentfiles;
925 return add_a_printer_driver_3(&info3);
929 /****************************************************************************
930 ****************************************************************************/
931 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
933 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
937 fstrcpy(info.name, in_prt);
938 fstrcpy(info.defaultdatatype, "RAW");
940 fstrcpy(info.driverpath, "");
941 fstrcpy(info.datafile, "");
942 fstrcpy(info.configfile, "");
943 fstrcpy(info.helpfile, "");
945 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
946 return ERROR_NOT_ENOUGH_MEMORY;
948 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
949 fstrcpy(info.dependentfiles[0], "");
951 *info_ptr = memdup(&info, sizeof(info));
956 /****************************************************************************
957 ****************************************************************************/
958 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
960 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
962 fstring architecture;
969 get_short_archi(architecture, in_arch);
971 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
973 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
976 kbuf.dsize = strlen(key)+1;
978 dbuf = tdb_fetch(tdb, kbuf);
980 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
982 if (!dbuf.dptr) return 5;
984 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
993 driver.defaultdatatype);
996 while (len < dbuf.dsize) {
997 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
998 sizeof(fstring)*(i+2));
999 if (driver.dependentfiles == NULL)
1002 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1003 &driver.dependentfiles[i]);
1006 if (driver.dependentfiles != NULL)
1007 fstrcpy(driver.dependentfiles[i], "");
1009 safe_free(dbuf.dptr);
1011 if (len != dbuf.dsize) {
1012 if (driver.dependentfiles != NULL)
1013 safe_free(driver.dependentfiles);
1015 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1018 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1023 /****************************************************************************
1024 ****************************************************************************/
1025 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1027 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1033 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1034 DEBUG(10,("driver key: [%s]\n", key));
1037 kbuf.dsize = strlen(key)+1;
1038 if (!tdb_exists(tdb, kbuf)) return False;
1041 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1043 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1044 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1045 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1046 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1047 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1048 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1049 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1051 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1052 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1053 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1055 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1056 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1057 pstrcat(line, info3->configfile);
1059 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1060 pstrcat(line, info3->datafile);
1062 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1063 pstrcat(line, info3->helpfile);
1065 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1066 pstrcat(line, info3->monitorname);
1068 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1071 for (i=0; info3->dependentfiles &&
1072 *info3->dependentfiles[i]; i++) {
1073 if (i) pstrcat(line, ","); /* don't end in a "," */
1074 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1075 pstrcat(line, info3->dependentfiles[i]);
1083 /****************************************************************************
1084 debugging function, dump at level 6 the struct in the logs
1085 ****************************************************************************/
1086 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1089 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1092 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1098 if (driver.info_3 == NULL)
1101 info3=driver.info_3;
1103 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1104 DEBUGADD(106,("name:[%s]\n", info3->name));
1105 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1106 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1107 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1108 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1109 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1110 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1111 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1113 for (i=0; info3->dependentfiles &&
1114 *info3->dependentfiles[i]; i++) {
1115 DEBUGADD(106,("dependentfile:[%s]\n",
1116 info3->dependentfiles[i]));
1123 DEBUGADD(1,("Level not implemented\n"));
1131 /****************************************************************************
1132 ****************************************************************************/
1133 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1137 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1139 if (!nt_devmode) return len;
1141 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1142 nt_devmode->devicename,
1143 nt_devmode->formname,
1145 nt_devmode->specversion,
1146 nt_devmode->driverversion,
1148 nt_devmode->driverextra,
1149 nt_devmode->orientation,
1150 nt_devmode->papersize,
1151 nt_devmode->paperlength,
1152 nt_devmode->paperwidth,
1155 nt_devmode->defaultsource,
1156 nt_devmode->printquality,
1159 nt_devmode->yresolution,
1160 nt_devmode->ttoption,
1161 nt_devmode->collate,
1162 nt_devmode->logpixels,
1165 nt_devmode->bitsperpel,
1166 nt_devmode->pelswidth,
1167 nt_devmode->pelsheight,
1168 nt_devmode->displayflags,
1169 nt_devmode->displayfrequency,
1170 nt_devmode->icmmethod,
1171 nt_devmode->icmintent,
1172 nt_devmode->mediatype,
1173 nt_devmode->dithertype,
1174 nt_devmode->reserved1,
1175 nt_devmode->reserved2,
1176 nt_devmode->panningwidth,
1177 nt_devmode->panningheight,
1178 nt_devmode->private);
1181 if (nt_devmode->private) {
1182 len += tdb_pack(buf+len, buflen-len, "B",
1183 nt_devmode->driverextra,
1184 nt_devmode->private);
1187 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1192 /****************************************************************************
1193 ****************************************************************************/
1194 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1198 while (param != NULL) {
1199 len += tdb_pack(buf+len, buflen-len, "pfdB",
1208 len += tdb_pack(buf+len, buflen-len, "p", param);
1214 /****************************************************************************
1215 delete a printer - this just deletes the printer info file, any open
1216 handles are not affected
1217 ****************************************************************************/
1218 uint32 del_a_printer(char *sharename)
1223 slprintf(key, sizeof(key), "%s%s",
1224 PRINTERS_PREFIX, sharename);
1227 kbuf.dsize=strlen(key)+1;
1229 tdb_delete(tdb, kbuf);
1233 /****************************************************************************
1234 ****************************************************************************/
1235 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1239 int buflen, len, ret;
1240 TDB_DATA kbuf, dbuf;
1243 * in addprinter: no servername and the printer is the name
1244 * in setprinter: servername is \\server
1245 * and printer is \\server\\printer
1247 * Samba manages only local printers.
1248 * we currently don't support things like path=\\other_server\printer
1251 if (info->servername[0]!='\0') {
1252 trim_string(info->printername, info->servername, NULL);
1253 trim_string(info->printername, "\\", NULL);
1254 info->servername[0]='\0';
1258 * JFM: one day I'll forget.
1259 * below that's info->portname because that's the SAMBA sharename
1260 * and I made NT 'thinks' it's the portname
1261 * the info->sharename is the thing you can name when you add a printer
1262 * that's the short-name when you create shared printer for 95/98
1263 * So I've made a limitation in SAMBA: you can only have 1 printer model
1264 * behind a SAMBA share.
1272 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1275 info->default_priority,
1292 info->printprocessor,
1296 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1297 len += pack_specifics(info->specific, buf+len, buflen-len);
1299 if (buflen != len) {
1300 buf = (char *)Realloc(buf, len);
1306 slprintf(key, sizeof(key), "%s%s",
1307 PRINTERS_PREFIX, info->sharename);
1310 kbuf.dsize = strlen(key)+1;
1314 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1317 DEBUG(8, ("error updating printer to tdb on disk\n"));
1321 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1322 info->sharename, info->drivername, info->portname, len));
1328 /****************************************************************************
1329 ****************************************************************************/
1330 BOOL add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1332 NT_PRINTER_PARAM *current;
1334 DEBUG(108,("add_a_specific_param\n"));
1338 if (info_2->specific == NULL)
1340 info_2->specific=param;
1344 current=info_2->specific;
1345 while (current->next != NULL) {
1346 current=current->next;
1348 current->next=param;
1353 /****************************************************************************
1354 ****************************************************************************/
1355 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1357 NT_PRINTER_PARAM *current;
1358 NT_PRINTER_PARAM *previous;
1360 current=info_2->specific;
1363 if (current==NULL) return (False);
1365 if ( !strcmp(current->value, param->value) &&
1366 (strlen(current->value)==strlen(param->value)) ) {
1367 DEBUG(109,("deleting first value\n"));
1368 info_2->specific=current->next;
1369 safe_free(current->data);
1371 DEBUG(109,("deleted first value\n"));
1375 current=previous->next;
1377 while ( current!=NULL ) {
1378 if (!strcmp(current->value, param->value) &&
1379 strlen(current->value)==strlen(param->value) ) {
1380 DEBUG(109,("deleting current value\n"));
1381 previous->next=current->next;
1382 safe_free(current->data);
1384 DEBUG(109,("deleted current value\n"));
1388 previous=previous->next;
1389 current=current->next;
1394 /****************************************************************************
1395 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
1396 ****************************************************************************/
1397 static void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
1399 NT_PRINTER_PARAM *param = *param_ptr;
1404 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
1407 safe_free(param->data);
1413 /****************************************************************************
1414 Malloc and return an NT devicemode.
1415 ****************************************************************************/
1417 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
1420 * should I init this ones ???
1421 nt_devmode->devicename
1425 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
1427 if (nt_devmode == NULL) {
1428 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
1432 ZERO_STRUCTP(nt_devmode);
1434 safe_strcpy(adevice, default_devicename, sizeof(adevice));
1435 fstrcpy(nt_devmode->devicename, adevice);
1437 fstrcpy(nt_devmode->formname, "Letter");
1439 nt_devmode->specversion = 0x0401;
1440 nt_devmode->driverversion = 0x0400;
1441 nt_devmode->size = 0x00DC;
1442 nt_devmode->driverextra = 0x0000;
1443 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
1444 DEFAULTSOURCE | COPIES | SCALE |
1445 PAPERSIZE | ORIENTATION;
1446 nt_devmode->orientation = 1;
1447 nt_devmode->papersize = PAPER_LETTER;
1448 nt_devmode->paperlength = 0;
1449 nt_devmode->paperwidth = 0;
1450 nt_devmode->scale = 0x64;
1451 nt_devmode->copies = 01;
1452 nt_devmode->defaultsource = BIN_FORMSOURCE;
1453 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
1454 nt_devmode->color = COLOR_MONOCHROME;
1455 nt_devmode->duplex = DUP_SIMPLEX;
1456 nt_devmode->yresolution = 0;
1457 nt_devmode->ttoption = TT_SUBDEV;
1458 nt_devmode->collate = COLLATE_FALSE;
1459 nt_devmode->icmmethod = 0;
1460 nt_devmode->icmintent = 0;
1461 nt_devmode->mediatype = 0;
1462 nt_devmode->dithertype = 0;
1464 /* non utilisés par un driver d'imprimante */
1465 nt_devmode->logpixels = 0;
1466 nt_devmode->bitsperpel = 0;
1467 nt_devmode->pelswidth = 0;
1468 nt_devmode->pelsheight = 0;
1469 nt_devmode->displayflags = 0;
1470 nt_devmode->displayfrequency = 0;
1471 nt_devmode->reserved1 = 0;
1472 nt_devmode->reserved2 = 0;
1473 nt_devmode->panningwidth = 0;
1474 nt_devmode->panningheight = 0;
1476 nt_devmode->private=NULL;
1481 /****************************************************************************
1482 Deepcopy an NT devicemode.
1483 ****************************************************************************/
1485 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
1487 NT_DEVICEMODE *new_nt_devicemode = NULL;
1489 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
1490 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1494 new_nt_devicemode->private = NULL;
1495 if (nt_devicemode->private != NULL) {
1496 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
1497 safe_free(new_nt_devicemode);
1498 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1503 return new_nt_devicemode;
1506 /****************************************************************************
1507 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
1508 ****************************************************************************/
1510 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
1512 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
1514 if(nt_devmode == NULL)
1517 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
1519 if(nt_devmode->private)
1520 safe_free(nt_devmode->private);
1522 safe_free(nt_devmode);
1523 *devmode_ptr = NULL;
1526 /****************************************************************************
1527 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
1528 ****************************************************************************/
1529 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
1531 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
1532 NT_PRINTER_PARAM *param_ptr;
1537 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
1539 free_nt_devicemode(&info->devmode);
1540 free_sec_desc_buf(&info->secdesc_buf);
1542 for(param_ptr = info->specific; param_ptr; ) {
1543 NT_PRINTER_PARAM *tofree = param_ptr;
1545 param_ptr = param_ptr->next;
1546 free_nt_printer_param(&tofree);
1549 safe_free(*info_ptr);
1554 /****************************************************************************
1555 ****************************************************************************/
1556 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
1560 NT_DEVICEMODE devmode;
1562 ZERO_STRUCT(devmode);
1564 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
1566 if (!*nt_devmode) return len;
1568 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1572 &devmode.specversion,
1573 &devmode.driverversion,
1575 &devmode.driverextra,
1576 &devmode.orientation,
1578 &devmode.paperlength,
1579 &devmode.paperwidth,
1582 &devmode.defaultsource,
1583 &devmode.printquality,
1586 &devmode.yresolution,
1592 &devmode.bitsperpel,
1594 &devmode.pelsheight,
1595 &devmode.displayflags,
1596 &devmode.displayfrequency,
1600 &devmode.dithertype,
1603 &devmode.panningwidth,
1604 &devmode.panningheight,
1607 if (devmode.private) {
1608 /* the len in tdb_unpack is an int value and
1609 * devmoce.driverextra is only a short
1611 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
1612 devmode.driverextra=(uint16)extra_len;
1615 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
1617 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
1618 if (devmode.private)
1619 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
1624 /****************************************************************************
1625 ****************************************************************************/
1626 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
1629 NT_PRINTER_PARAM param, *p;
1634 len += tdb_unpack(buf+len, buflen-len, "p", &p);
1637 len += tdb_unpack(buf+len, buflen-len, "fdB",
1643 *list = memdup(¶m, sizeof(param));
1645 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
1652 /****************************************************************************
1653 get a default printer info 2 struct
1654 ****************************************************************************/
1655 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
1657 extern pstring global_myname;
1659 NT_PRINTER_INFO_LEVEL_2 info;
1663 snum = lp_servicenumber(sharename);
1665 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
1666 slprintf(info.printername, sizeof(info.printername), "\\\\%s\\%s",
1667 global_myname, sharename);
1668 fstrcpy(info.sharename, sharename);
1669 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
1670 fstrcpy(info.drivername, lp_printerdriver(snum));
1671 pstrcpy(info.comment, "");
1672 fstrcpy(info.printprocessor, "winprint");
1673 fstrcpy(info.datatype, "RAW");
1675 info.attributes = PRINTER_ATTRIBUTE_SHARED \
1676 | PRINTER_ATTRIBUTE_LOCAL \
1677 | PRINTER_ATTRIBUTE_RAW_ONLY \
1678 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
1680 info.starttime = 0; /* Minutes since 12:00am GMT */
1681 info.untiltime = 0; /* Minutes since 12:00am GMT */
1683 info.default_priority = 1;
1684 info.setuptime = (uint32)time(NULL);
1686 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
1689 if (!nt_printing_getsec(sharename, &info.secdesc_buf))
1692 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
1694 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
1703 free_nt_devicemode(&info.devmode);
1704 if (info.secdesc_buf)
1705 free_sec_desc_buf(&info.secdesc_buf);
1709 /****************************************************************************
1710 ****************************************************************************/
1711 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
1714 NT_PRINTER_INFO_LEVEL_2 info;
1716 TDB_DATA kbuf, dbuf;
1717 fstring printername;
1721 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
1724 kbuf.dsize = strlen(key)+1;
1726 dbuf = tdb_fetch(tdb, kbuf);
1728 return get_a_printer_2_default(info_ptr, sharename);
1730 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
1733 &info.default_priority,
1750 info.printprocessor,
1754 /* Samba has to have shared raw drivers. */
1755 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
1757 /* Restore the stripped strings. */
1758 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
1759 slprintf(printername, sizeof(printername), "\\\\%s\\%s", global_myname,
1761 fstrcpy(info.printername, printername);
1763 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
1764 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
1766 nt_printing_getsec(sharename, &info.secdesc_buf);
1768 safe_free(dbuf.dptr);
1769 *info_ptr=memdup(&info, sizeof(info));
1771 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
1772 sharename, info.printername, info.drivername));
1778 /****************************************************************************
1779 debugging function, dump at level 6 the struct in the logs
1780 ****************************************************************************/
1781 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1784 NT_PRINTER_INFO_LEVEL_2 *info2;
1786 DEBUG(106,("Dumping printer at level [%d]\n", level));
1792 if (printer.info_2 == NULL)
1796 info2=printer.info_2;
1798 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
1799 DEBUGADD(106,("priority:[%d]\n", info2->priority));
1800 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
1801 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
1802 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
1803 DEBUGADD(106,("status:[%d]\n", info2->status));
1804 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
1805 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
1806 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
1807 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
1808 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
1810 DEBUGADD(106,("servername:[%s]\n", info2->servername));
1811 DEBUGADD(106,("printername:[%s]\n", info2->printername));
1812 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
1813 DEBUGADD(106,("portname:[%s]\n", info2->portname));
1814 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
1815 DEBUGADD(106,("comment:[%s]\n", info2->comment));
1816 DEBUGADD(106,("location:[%s]\n", info2->location));
1817 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
1818 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
1819 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
1820 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
1826 DEBUGADD(1,("Level not implemented\n"));
1834 /****************************************************************************
1835 Get the parameters we can substitute in an NT print job.
1836 ****************************************************************************/
1838 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
1840 NT_PRINTER_INFO_LEVEL *printer = NULL;
1842 **printername = **sharename = **portname = '\0';
1844 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1847 fstrcpy(*printername, printer->info_2->printername);
1848 fstrcpy(*sharename, printer->info_2->sharename);
1849 fstrcpy(*portname, printer->info_2->portname);
1851 free_a_printer(&printer, 2);
1855 * The function below are the high level ones.
1856 * only those ones must be called from the spoolss code.
1860 /****************************************************************************
1861 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
1862 ****************************************************************************/
1864 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1868 dump_a_printer(printer, level);
1874 printer.info_2->c_setprinter++;
1875 success=update_a_printer_2(printer.info_2);
1886 /****************************************************************************
1887 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
1888 We split this out from mod_a_printer as it updates the id's and timestamps.
1889 ****************************************************************************/
1891 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1895 dump_a_printer(printer, level);
1902 * Update the changestamp.
1903 * Note we must *not* do this in mod_a_printer().
1906 time_t time_unix = time(NULL);
1907 unix_to_nt_time(&time_nt, time_unix);
1908 printer.info_2->changeid=time_nt.low;
1910 printer.info_2->c_setprinter++;
1911 success=update_a_printer_2(printer.info_2);
1922 /****************************************************************************
1923 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
1924 ****************************************************************************/
1926 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
1929 NT_PRINTER_INFO_LEVEL *printer = NULL;
1933 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
1939 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
1940 DEBUG(0,("get_a_printer: malloc fail.\n"));
1943 ZERO_STRUCTP(printer);
1944 success=get_a_printer_2(&printer->info_2, sharename);
1946 dump_a_printer(*printer, level);
1947 *pp_printer = printer;
1958 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)success));
1963 /****************************************************************************
1964 Deletes a NT_PRINTER_INFO_LEVEL struct.
1965 ****************************************************************************/
1967 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
1970 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
1972 DEBUG(104,("freeing a printer at level [%d]\n", level));
1974 if (printer == NULL)
1981 if (printer->info_2 != NULL)
1983 free_nt_printer_info_level_2(&printer->info_2);
2002 /****************************************************************************
2003 ****************************************************************************/
2004 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2007 DEBUG(104,("adding a printer at level [%d]\n", level));
2008 dump_a_printer_driver(driver, level);
2014 success=add_a_printer_driver_3(driver.info_3);
2020 success=add_a_printer_driver_6(driver.info_6);
2030 /****************************************************************************
2031 ****************************************************************************/
2032 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2033 fstring printername, fstring architecture, uint32 version)
2041 success=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2050 dump_a_printer_driver(*driver, level);
2054 /****************************************************************************
2055 ****************************************************************************/
2056 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2064 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2065 if (driver.info_3 != NULL)
2067 info3=driver.info_3;
2068 safe_free(info3->dependentfiles);
2069 ZERO_STRUCTP(info3);
2081 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2082 if (driver.info_6 != NULL)
2084 info6=driver.info_6;
2085 safe_free(info6->dependentfiles);
2086 safe_free(info6->previousnames);
2087 ZERO_STRUCTP(info6);
2104 /****************************************************************************
2105 ****************************************************************************/
2106 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2107 fstring value, uint8 **data, uint32 *type, uint32 *len)
2109 /* right now that's enough ! */
2110 NT_PRINTER_PARAM *param;
2113 param=printer.info_2->specific;
2115 while (param != NULL && i < param_index) {
2123 /* exited because it exist */
2125 StrnCpy(value, param->value, sizeof(fstring)-1);
2126 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2129 ZERO_STRUCTP(*data);
2130 memcpy(*data, param->data, param->data_len);
2131 *len=param->data_len;
2135 /****************************************************************************
2136 ****************************************************************************/
2137 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2138 fstring value, uint8 **data, uint32 *type, uint32 *len)
2140 /* right now that's enough ! */
2141 NT_PRINTER_PARAM *param;
2143 DEBUG(105, ("get_specific_param\n"));
2145 param=printer.info_2->specific;
2147 while (param != NULL)
2149 #if 1 /* JRA - I think this should be case insensitive.... */
2150 if ( strequal(value, param->value)
2152 if ( !strcmp(value, param->value)
2154 && strlen(value)==strlen(param->value))
2160 DEBUG(106, ("found one param\n"));
2163 /* exited because it exist */
2166 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2169 memcpy(*data, param->data, param->data_len);
2170 *len=param->data_len;
2172 DEBUG(106, ("exit of get_specific_param:true\n"));
2175 DEBUG(106, ("exit of get_specific_param:false\n"));
2179 /****************************************************************************
2180 Store a security desc for a printer.
2181 ****************************************************************************/
2183 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
2186 TALLOC_CTX *mem_ctx = NULL;
2190 mem_ctx = talloc_init();
2191 if (mem_ctx == NULL) return False;
2193 /* Store the security descriptor in a tdb */
2195 prs_init(&ps, (uint32)sec_desc_size(secdesc_ctr->sec) +
2196 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
2198 if (!sec_io_desc_buf("nt_printing_setsec", &secdesc_ctr, &ps, 1)) {
2199 status = ERROR_INVALID_FUNCTION;
2203 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2205 if (tdb_prs_store(tdb, key, &ps)==0) {
2208 DEBUG(1,("Failed to store secdesc for %s\n", printername));
2209 status = ERROR_INVALID_FUNCTION;
2212 /* Free mallocated memory */
2217 if (mem_ctx) talloc_destroy(mem_ctx);
2222 /****************************************************************************
2223 Construct a default security descriptor buffer for a printer.
2224 ****************************************************************************/
2226 static SEC_DESC_BUF *construct_default_printer_sdb(void)
2230 SEC_ACL *psa = NULL;
2231 SEC_DESC_BUF *sdb = NULL;
2232 SEC_DESC *psd = NULL;
2235 enum SID_NAME_USE name_type;
2237 /* Create an ACE where Everyone is allowed to print */
2239 init_sec_access(&sa, PRINTER_ACE_PRINT);
2240 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2241 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2244 /* Make the security descriptor owned by the Administrators group
2245 on the PDC of the domain. */
2247 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
2248 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2251 /* Backup plan - make printer owned by admins or root. This should
2252 emulate a lanman printer as security settings can't be
2255 if (!lookup_name( "Printer Administrators", &owner_sid, &name_type) &&
2256 !lookup_name( "Administrators", &owner_sid, &name_type) &&
2257 !lookup_name( "Administrator", &owner_sid, &name_type) &&
2258 !lookup_name("root", &owner_sid, &name_type)) {
2259 sid_copy(&owner_sid, &global_sid_World);
2263 init_sec_access(&sa, PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT);
2264 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2265 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2267 /* The ACL revision number in rpc_secdesc.h differs from the one
2268 created by NT when setting ACE entries in printer
2269 descriptors. NT4 complains about the property being edited by a
2272 #define NT4_ACL_REVISION 0x2
2274 if ((psa = make_sec_acl(NT4_ACL_REVISION, 2, ace)) != NULL) {
2275 psd = make_sec_desc(SEC_DESC_REVISION,
2276 SEC_DESC_SELF_RELATIVE |
2277 SEC_DESC_DACL_PRESENT,
2279 NULL, psa, &sd_size);
2284 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2288 sdb = make_sec_desc_buf(sd_size, psd);
2290 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2291 (unsigned int)sd_size));
2293 free_sec_desc(&psd);
2297 /****************************************************************************
2298 Get a security desc for a printer.
2299 ****************************************************************************/
2301 BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
2304 TALLOC_CTX *mem_ctx = NULL;
2307 mem_ctx = talloc_init();
2308 if (mem_ctx == NULL)
2311 /* Fetch security descriptor from tdb */
2313 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2315 if (tdb_prs_fetch(tdb, key, &ps, mem_ctx)!=0 ||
2316 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
2318 DEBUG(4,("using default secdesc for %s\n", printername));
2320 if (!(*secdesc_ctr = construct_default_printer_sdb())) {
2321 talloc_destroy(mem_ctx);
2325 talloc_destroy(mem_ctx);
2329 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2330 this security descriptor has been created when winbindd was
2331 down. Take ownership of security descriptor. */
2333 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
2335 enum SID_NAME_USE name_type;
2337 /* Change sd owner to workgroup administrator */
2339 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
2341 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2342 SEC_DESC *psd = NULL;
2347 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2349 psd = make_sec_desc((*secdesc_ctr)->sec->revision,
2350 (*secdesc_ctr)->sec->type,
2352 (*secdesc_ctr)->sec->grp_sid,
2353 (*secdesc_ctr)->sec->sacl,
2354 (*secdesc_ctr)->sec->dacl,
2357 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2359 free_sec_desc(&psd);
2361 /* Swap with other one */
2363 free_sec_desc_buf(secdesc_ctr);
2364 *secdesc_ctr = new_secdesc_ctr;
2368 nt_printing_setsec(printername, *secdesc_ctr);
2373 talloc_destroy(mem_ctx);
2379 1: level not implemented
2380 2: file doesn't exist
2381 3: can't allocate memory
2382 4: can't free memory
2383 5: non existant struct
2387 A printer and a printer driver are 2 different things.
2388 NT manages them separatelly, Samba does the same.
2389 Why ? Simply because it's easier and it makes sense !
2391 Now explanation: You have 3 printers behind your samba server,
2392 2 of them are the same make and model (laser A and B). But laser B
2393 has an 3000 sheet feeder and laser A doesn't such an option.
2394 Your third printer is an old dot-matrix model for the accounting :-).
2396 If the /usr/local/samba/lib directory (default dir), you will have
2397 5 files to describe all of this.
2399 3 files for the printers (1 by printer):
2402 NTprinter_accounting
2403 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2404 NTdriver_printer model X
2405 NTdriver_printer model Y
2407 jfm: I should use this comment for the text file to explain
2408 same thing for the forms BTW.
2409 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2413 /****************************************************************************
2414 Check a user has permissions to perform the given operation. We use some
2415 constants defined in include/rpc_spoolss.h that look relevant to check
2416 the various actions we perform when checking printer access.
2418 PRINTER_ACCESS_ADMINISTER:
2419 print_queue_pause, print_queue_resume, update_printer_sec,
2420 update_printer, spoolss_addprinterex_level_2,
2421 _spoolss_setprinterdata
2426 JOB_ACCESS_ADMINISTER:
2427 print_job_delete, print_job_pause, print_job_resume,
2430 ****************************************************************************/
2431 BOOL print_access_check(struct current_user *user, int snum, int access_type)
2433 SEC_DESC_BUF *secdesc = NULL;
2434 uint32 access_granted, status, required_access = 0;
2438 extern struct current_user current_user;
2440 /* If user is NULL then use the current_user structure */
2442 if (!user) user = ¤t_user;
2444 /* Always allow root or printer admins to do anything */
2446 if (user->uid == 0 ||
2447 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
2451 /* Get printer name */
2453 pname = PRINTERNAME(snum);
2455 if (!pname || !*pname)
2456 pname = SERVICE(snum);
2458 if (!pname || !*pname) {
2463 /* Get printer security descriptor */
2465 nt_printing_getsec(pname, &secdesc);
2467 /* Check against NT4 ACE mask values. From observation these
2470 Access Type ACE Mask Constant
2471 -------------------------------------
2472 Full Control 0x10000000 PRINTER_ACE_FULL_CONTROL
2473 Print 0xe0000000 PRINTER_ACE_PRINT
2474 Manage Documents 0x00020000 PRINTER_ACE_MANAGE_DOCUMENTS
2477 switch (access_type) {
2478 case PRINTER_ACCESS_USE:
2479 required_access = PRINTER_ACE_PRINT;
2481 case PRINTER_ACCESS_ADMINISTER:
2482 required_access = PRINTER_ACE_MANAGE_DOCUMENTS |
2485 case JOB_ACCESS_ADMINISTER:
2486 required_access = PRINTER_ACE_MANAGE_DOCUMENTS;
2489 DEBUG(0, ("invalid value passed to print_access_check()\n"));
2494 /* The ACE for Full Control in a printer security descriptor
2495 doesn't seem to map properly to the access checking model. For
2496 it to work properly it should be the logical OR of all the other
2497 values, i.e PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT.
2498 This would cause the access check to simply fall out when we
2499 check against any subset of these bits. To get things to work,
2500 change every ACE mask of PRINTER_ACE_FULL_CONTROL to
2501 PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT before
2502 performing the access check. I'm sure there is a better way to
2505 if (secdesc && secdesc->sec && secdesc->sec->dacl &&
2506 secdesc->sec->dacl->ace) {
2507 for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
2508 if (secdesc->sec->dacl->ace[i].info.mask ==
2509 PRINTER_ACE_FULL_CONTROL) {
2510 secdesc->sec->dacl->ace[i].info.mask =
2511 PRINTER_ACE_MANAGE_DOCUMENTS |
2517 if ((result = se_access_check(secdesc->sec, user, required_access,
2518 &access_granted, &status))) {
2522 /* Check against NT5 ACE mask values. From observation these
2525 Access Type ACE Mask Constant
2526 -------------------------------------
2527 Full Control 0x000f000c PRINTER_ACE_NT5_FULL_CONTROL
2528 Print 0x00020008 PRINTER_ACE_NT5_PRINT
2529 Manage Documents 0x00020000 PRINTER_ACE_NT5_MANAGE_DOCUMENTS
2531 NT5 likes to rewrite the security descriptor and change the ACE
2532 masks from NT4 format to NT5 format making them unreadable by
2535 switch (access_type) {
2536 case PRINTER_ACCESS_USE:
2537 required_access = PRINTER_ACE_NT5_PRINT;
2539 case PRINTER_ACCESS_ADMINISTER:
2540 required_access = PRINTER_ACE_NT5_FULL_CONTROL;
2542 case JOB_ACCESS_ADMINISTER:
2543 required_access = PRINTER_ACE_NT5_MANAGE_DOCUMENTS;
2547 result = se_access_check(secdesc->sec, user, required_access,
2548 &access_granted, &status);
2553 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
2555 /* Free mallocated memory */
2557 free_sec_desc_buf(&secdesc);
2565 /****************************************************************************
2566 Check the time parameters allow a print operation.
2567 *****************************************************************************/
2569 BOOL print_time_access_check(int snum)
2571 NT_PRINTER_INFO_LEVEL *printer = NULL;
2573 time_t now = time(NULL);
2577 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2580 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
2584 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2586 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
2589 free_a_printer(&printer, 2);