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;
643 struct smb_passwd *smb_pass;
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 smb_pass = getsmbpwuid(user->uid);
666 if(smb_pass == NULL) {
667 DEBUG(0,("move_driver_to_download_area: Unable to get smbpasswd 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, smb_pass->smb_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 snprintf(adevice, sizeof(adevice), "\\\\%s\\%s", global_myname, default_devicename);
1435 fstrcpy(nt_devmode->devicename, adevice);
1438 fstrcpy(nt_devmode->formname, "Letter");
1440 nt_devmode->specversion = 0x0401;
1441 nt_devmode->driverversion = 0x0400;
1442 nt_devmode->size = 0x00DC;
1443 nt_devmode->driverextra = 0x0000;
1444 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
1445 DEFAULTSOURCE | COPIES | SCALE |
1446 PAPERSIZE | ORIENTATION;
1447 nt_devmode->orientation = 1;
1448 nt_devmode->papersize = PAPER_LETTER;
1449 nt_devmode->paperlength = 0;
1450 nt_devmode->paperwidth = 0;
1451 nt_devmode->scale = 0x64;
1452 nt_devmode->copies = 01;
1453 nt_devmode->defaultsource = BIN_FORMSOURCE;
1454 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
1455 nt_devmode->color = COLOR_MONOCHROME;
1456 nt_devmode->duplex = DUP_SIMPLEX;
1457 nt_devmode->yresolution = 0;
1458 nt_devmode->ttoption = TT_SUBDEV;
1459 nt_devmode->collate = COLLATE_FALSE;
1460 nt_devmode->icmmethod = 0;
1461 nt_devmode->icmintent = 0;
1462 nt_devmode->mediatype = 0;
1463 nt_devmode->dithertype = 0;
1465 /* non utilisés par un driver d'imprimante */
1466 nt_devmode->logpixels = 0;
1467 nt_devmode->bitsperpel = 0;
1468 nt_devmode->pelswidth = 0;
1469 nt_devmode->pelsheight = 0;
1470 nt_devmode->displayflags = 0;
1471 nt_devmode->displayfrequency = 0;
1472 nt_devmode->reserved1 = 0;
1473 nt_devmode->reserved2 = 0;
1474 nt_devmode->panningwidth = 0;
1475 nt_devmode->panningheight = 0;
1477 nt_devmode->private=NULL;
1482 /****************************************************************************
1483 Deepcopy an NT devicemode.
1484 ****************************************************************************/
1486 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
1488 NT_DEVICEMODE *new_nt_devicemode = NULL;
1490 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
1491 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1495 new_nt_devicemode->private = NULL;
1496 if (nt_devicemode->private != NULL) {
1497 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
1498 safe_free(new_nt_devicemode);
1499 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1504 return new_nt_devicemode;
1507 /****************************************************************************
1508 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
1509 ****************************************************************************/
1511 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
1513 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
1515 if(nt_devmode == NULL)
1518 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
1520 if(nt_devmode->private)
1521 safe_free(nt_devmode->private);
1523 safe_free(nt_devmode);
1524 *devmode_ptr = NULL;
1527 /****************************************************************************
1528 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
1529 ****************************************************************************/
1530 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
1532 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
1533 NT_PRINTER_PARAM *param_ptr;
1538 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
1540 free_nt_devicemode(&info->devmode);
1541 free_sec_desc_buf(&info->secdesc_buf);
1543 for(param_ptr = info->specific; param_ptr; ) {
1544 NT_PRINTER_PARAM *tofree = param_ptr;
1546 param_ptr = param_ptr->next;
1547 free_nt_printer_param(&tofree);
1550 safe_free(*info_ptr);
1555 /****************************************************************************
1556 ****************************************************************************/
1557 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
1561 NT_DEVICEMODE devmode;
1563 ZERO_STRUCT(devmode);
1565 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
1567 if (!*nt_devmode) return len;
1569 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1573 &devmode.specversion,
1574 &devmode.driverversion,
1576 &devmode.driverextra,
1577 &devmode.orientation,
1579 &devmode.paperlength,
1580 &devmode.paperwidth,
1583 &devmode.defaultsource,
1584 &devmode.printquality,
1587 &devmode.yresolution,
1593 &devmode.bitsperpel,
1595 &devmode.pelsheight,
1596 &devmode.displayflags,
1597 &devmode.displayfrequency,
1601 &devmode.dithertype,
1604 &devmode.panningwidth,
1605 &devmode.panningheight,
1608 if (devmode.private) {
1609 /* the len in tdb_unpack is an int value and
1610 * devmoce.driverextra is only a short
1612 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
1613 devmode.driverextra=(uint16)extra_len;
1616 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
1618 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
1619 if (devmode.private)
1620 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
1625 /****************************************************************************
1626 ****************************************************************************/
1627 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
1630 NT_PRINTER_PARAM param, *p;
1635 len += tdb_unpack(buf+len, buflen-len, "p", &p);
1638 len += tdb_unpack(buf+len, buflen-len, "fdB",
1644 *list = memdup(¶m, sizeof(param));
1646 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
1653 /****************************************************************************
1654 get a default printer info 2 struct
1655 ****************************************************************************/
1656 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
1658 extern pstring global_myname;
1660 NT_PRINTER_INFO_LEVEL_2 info;
1664 snum = lp_servicenumber(sharename);
1666 fstrcpy(info.servername, global_myname);
1667 fstrcpy(info.printername, sharename);
1668 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
1669 fstrcpy(info.drivername, lp_printerdriver(snum));
1670 pstrcpy(info.comment, "");
1671 fstrcpy(info.printprocessor, "winprint");
1672 fstrcpy(info.datatype, "RAW");
1674 info.attributes = PRINTER_ATTRIBUTE_SHARED \
1675 | PRINTER_ATTRIBUTE_LOCAL \
1676 | PRINTER_ATTRIBUTE_RAW_ONLY \
1677 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
1679 info.starttime = 0; /* Minutes since 12:00am GMT */
1680 info.untiltime = 0; /* Minutes since 12:00am GMT */
1682 info.default_priority = 1;
1683 info.setuptime = (uint32)time(NULL);
1685 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
1688 if (!nt_printing_getsec(sharename, &info.secdesc_buf))
1691 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
1693 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
1702 free_nt_devicemode(&info.devmode);
1703 if (info.secdesc_buf)
1704 free_sec_desc_buf(&info.secdesc_buf);
1708 /****************************************************************************
1709 ****************************************************************************/
1710 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
1713 NT_PRINTER_INFO_LEVEL_2 info;
1715 TDB_DATA kbuf, dbuf;
1719 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
1722 kbuf.dsize = strlen(key)+1;
1724 dbuf = tdb_fetch(tdb, kbuf);
1726 return get_a_printer_2_default(info_ptr, sharename);
1728 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
1731 &info.default_priority,
1748 info.printprocessor,
1752 /* Samba has to have shared raw drivers. */
1753 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
1755 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
1756 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
1758 nt_printing_getsec(sharename, &info.secdesc_buf);
1760 safe_free(dbuf.dptr);
1761 *info_ptr=memdup(&info, sizeof(info));
1763 DEBUG(9,("Unpacked printer [%s] running driver [%s]\n",
1764 sharename, info.drivername));
1770 /****************************************************************************
1771 debugging function, dump at level 6 the struct in the logs
1772 ****************************************************************************/
1773 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1776 NT_PRINTER_INFO_LEVEL_2 *info2;
1778 DEBUG(106,("Dumping printer at level [%d]\n", level));
1784 if (printer.info_2 == NULL)
1788 info2=printer.info_2;
1790 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
1791 DEBUGADD(106,("priority:[%d]\n", info2->priority));
1792 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
1793 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
1794 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
1795 DEBUGADD(106,("status:[%d]\n", info2->status));
1796 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
1797 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
1798 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
1799 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
1800 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
1802 DEBUGADD(106,("servername:[%s]\n", info2->servername));
1803 DEBUGADD(106,("printername:[%s]\n", info2->printername));
1804 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
1805 DEBUGADD(106,("portname:[%s]\n", info2->portname));
1806 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
1807 DEBUGADD(106,("comment:[%s]\n", info2->comment));
1808 DEBUGADD(106,("location:[%s]\n", info2->location));
1809 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
1810 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
1811 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
1812 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
1818 DEBUGADD(1,("Level not implemented\n"));
1826 /****************************************************************************
1827 Get the parameters we can substitute in an NT print job.
1828 ****************************************************************************/
1830 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
1832 NT_PRINTER_INFO_LEVEL *printer = NULL;
1834 **printername = **sharename = **portname = '\0';
1836 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
1839 fstrcpy(*printername, printer->info_2->printername);
1840 fstrcpy(*sharename, printer->info_2->sharename);
1841 fstrcpy(*portname, printer->info_2->portname);
1843 free_a_printer(&printer, 2);
1847 * The function below are the high level ones.
1848 * only those ones must be called from the spoolss code.
1852 /****************************************************************************
1853 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
1854 ****************************************************************************/
1856 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1860 dump_a_printer(printer, level);
1866 printer.info_2->c_setprinter++;
1867 success=update_a_printer_2(printer.info_2);
1878 /****************************************************************************
1879 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
1880 We split this out from mod_a_printer as it updates the id's and timestamps.
1881 ****************************************************************************/
1883 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
1887 dump_a_printer(printer, level);
1894 * Update the changestamp.
1895 * Note we must *not* do this in mod_a_printer().
1898 time_t time_unix = time(NULL);
1899 unix_to_nt_time(&time_nt, time_unix);
1900 printer.info_2->changeid=time_nt.low;
1902 printer.info_2->c_setprinter++;
1903 success=update_a_printer_2(printer.info_2);
1914 /****************************************************************************
1915 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
1916 ****************************************************************************/
1918 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
1921 NT_PRINTER_INFO_LEVEL *printer = NULL;
1925 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
1931 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
1932 DEBUG(0,("get_a_printer: malloc fail.\n"));
1935 ZERO_STRUCTP(printer);
1936 success=get_a_printer_2(&printer->info_2, sharename);
1938 dump_a_printer(*printer, level);
1939 *pp_printer = printer;
1950 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)success));
1955 /****************************************************************************
1956 Deletes a NT_PRINTER_INFO_LEVEL struct.
1957 ****************************************************************************/
1959 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
1962 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
1964 DEBUG(104,("freeing a printer at level [%d]\n", level));
1966 if (printer == NULL)
1973 if (printer->info_2 != NULL)
1975 free_nt_printer_info_level_2(&printer->info_2);
1994 /****************************************************************************
1995 ****************************************************************************/
1996 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1999 DEBUG(104,("adding a printer at level [%d]\n", level));
2000 dump_a_printer_driver(driver, level);
2006 success=add_a_printer_driver_3(driver.info_3);
2012 success=add_a_printer_driver_6(driver.info_6);
2022 /****************************************************************************
2023 ****************************************************************************/
2024 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2025 fstring printername, fstring architecture, uint32 version)
2033 success=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2042 dump_a_printer_driver(*driver, level);
2046 /****************************************************************************
2047 ****************************************************************************/
2048 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2056 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2057 if (driver.info_3 != NULL)
2059 info3=driver.info_3;
2060 safe_free(info3->dependentfiles);
2061 ZERO_STRUCTP(info3);
2073 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2074 if (driver.info_6 != NULL)
2076 info6=driver.info_6;
2077 safe_free(info6->dependentfiles);
2078 safe_free(info6->previousnames);
2079 ZERO_STRUCTP(info6);
2096 /****************************************************************************
2097 ****************************************************************************/
2098 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2099 fstring value, uint8 **data, uint32 *type, uint32 *len)
2101 /* right now that's enough ! */
2102 NT_PRINTER_PARAM *param;
2105 param=printer.info_2->specific;
2107 while (param != NULL && i < param_index) {
2115 /* exited because it exist */
2117 StrnCpy(value, param->value, sizeof(fstring)-1);
2118 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2121 ZERO_STRUCTP(*data);
2122 memcpy(*data, param->data, param->data_len);
2123 *len=param->data_len;
2127 /****************************************************************************
2128 ****************************************************************************/
2129 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2130 fstring value, uint8 **data, uint32 *type, uint32 *len)
2132 /* right now that's enough ! */
2133 NT_PRINTER_PARAM *param;
2135 DEBUG(105, ("get_specific_param\n"));
2137 param=printer.info_2->specific;
2139 while (param != NULL)
2141 #if 1 /* JRA - I think this should be case insensitive.... */
2142 if ( strequal(value, param->value)
2144 if ( !strcmp(value, param->value)
2146 && strlen(value)==strlen(param->value))
2152 DEBUG(106, ("found one param\n"));
2155 /* exited because it exist */
2158 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2161 memcpy(*data, param->data, param->data_len);
2162 *len=param->data_len;
2164 DEBUG(106, ("exit of get_specific_param:true\n"));
2167 DEBUG(106, ("exit of get_specific_param:false\n"));
2171 /****************************************************************************
2172 Store a security desc for a printer.
2173 ****************************************************************************/
2175 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
2178 TALLOC_CTX *mem_ctx = NULL;
2182 mem_ctx = talloc_init();
2183 if (mem_ctx == NULL) return False;
2185 /* Store the security descriptor in a tdb */
2187 prs_init(&ps, (uint32)sec_desc_size(secdesc_ctr->sec) +
2188 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
2190 if (!sec_io_desc_buf("nt_printing_setsec", &secdesc_ctr, &ps, 1)) {
2191 status = ERROR_INVALID_FUNCTION;
2195 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2197 if (tdb_prs_store(tdb, key, &ps)==0) {
2200 DEBUG(1,("Failed to store secdesc for %s\n", printername));
2201 status = ERROR_INVALID_FUNCTION;
2204 /* Free mallocated memory */
2209 if (mem_ctx) talloc_destroy(mem_ctx);
2214 /****************************************************************************
2215 Construct a default security descriptor buffer for a printer.
2216 ****************************************************************************/
2218 static SEC_DESC_BUF *construct_default_printer_sdb(void)
2222 SEC_ACL *psa = NULL;
2223 SEC_DESC_BUF *sdb = NULL;
2224 SEC_DESC *psd = NULL;
2227 enum SID_NAME_USE name_type;
2229 /* Create an ACE where Everyone is allowed to print */
2231 init_sec_access(&sa, PRINTER_ACE_PRINT);
2232 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2233 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2236 /* Make the security descriptor owned by the Administrators group
2237 on the PDC of the domain. */
2239 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
2240 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2243 /* Backup plan - make printer owned by admins or root. This should
2244 emulate a lanman printer as security settings can't be
2247 if (!lookup_name( "Printer Administrators", &owner_sid, &name_type) &&
2248 !lookup_name( "Administrators", &owner_sid, &name_type) &&
2249 !lookup_name( "Administrator", &owner_sid, &name_type) &&
2250 !lookup_name("root", &owner_sid, &name_type)) {
2251 sid_copy(&owner_sid, &global_sid_World);
2255 init_sec_access(&sa, PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT);
2256 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2257 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2259 /* The ACL revision number in rpc_secdesc.h differs from the one
2260 created by NT when setting ACE entries in printer
2261 descriptors. NT4 complains about the property being edited by a
2264 #define NT4_ACL_REVISION 0x2
2266 if ((psa = make_sec_acl(NT4_ACL_REVISION, 2, ace)) != NULL) {
2267 psd = make_sec_desc(SEC_DESC_REVISION,
2268 SEC_DESC_SELF_RELATIVE |
2269 SEC_DESC_DACL_PRESENT,
2271 NULL, psa, &sd_size);
2276 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2280 sdb = make_sec_desc_buf(sd_size, psd);
2282 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2283 (unsigned int)sd_size));
2285 free_sec_desc(&psd);
2289 /****************************************************************************
2290 Get a security desc for a printer.
2291 ****************************************************************************/
2293 BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
2296 TALLOC_CTX *mem_ctx = NULL;
2299 mem_ctx = talloc_init();
2300 if (mem_ctx == NULL)
2303 /* Fetch security descriptor from tdb */
2305 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2307 if (tdb_prs_fetch(tdb, key, &ps, mem_ctx)!=0 ||
2308 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
2310 DEBUG(4,("using default secdesc for %s\n", printername));
2312 if (!(*secdesc_ctr = construct_default_printer_sdb())) {
2313 talloc_destroy(mem_ctx);
2317 talloc_destroy(mem_ctx);
2321 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2322 this security descriptor has been created when winbindd was
2323 down. Take ownership of security descriptor. */
2325 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
2327 enum SID_NAME_USE name_type;
2329 /* Change sd owner to workgroup administrator */
2331 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
2333 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2334 SEC_DESC *psd = NULL;
2339 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2341 psd = make_sec_desc((*secdesc_ctr)->sec->revision,
2342 (*secdesc_ctr)->sec->type,
2344 (*secdesc_ctr)->sec->grp_sid,
2345 (*secdesc_ctr)->sec->sacl,
2346 (*secdesc_ctr)->sec->dacl,
2349 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2351 free_sec_desc(&psd);
2353 /* Swap with other one */
2355 free_sec_desc_buf(secdesc_ctr);
2356 *secdesc_ctr = new_secdesc_ctr;
2360 nt_printing_setsec(printername, *secdesc_ctr);
2365 talloc_destroy(mem_ctx);
2371 1: level not implemented
2372 2: file doesn't exist
2373 3: can't allocate memory
2374 4: can't free memory
2375 5: non existant struct
2379 A printer and a printer driver are 2 different things.
2380 NT manages them separatelly, Samba does the same.
2381 Why ? Simply because it's easier and it makes sense !
2383 Now explanation: You have 3 printers behind your samba server,
2384 2 of them are the same make and model (laser A and B). But laser B
2385 has an 3000 sheet feeder and laser A doesn't such an option.
2386 Your third printer is an old dot-matrix model for the accounting :-).
2388 If the /usr/local/samba/lib directory (default dir), you will have
2389 5 files to describe all of this.
2391 3 files for the printers (1 by printer):
2394 NTprinter_accounting
2395 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2396 NTdriver_printer model X
2397 NTdriver_printer model Y
2399 jfm: I should use this comment for the text file to explain
2400 same thing for the forms BTW.
2401 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2405 /****************************************************************************
2406 Check a user has permissions to perform the given operation. We use some
2407 constants defined in include/rpc_spoolss.h that look relevant to check
2408 the various actions we perform when checking printer access.
2410 PRINTER_ACCESS_ADMINISTER:
2411 print_queue_pause, print_queue_resume, update_printer_sec,
2412 update_printer, spoolss_addprinterex_level_2,
2413 _spoolss_setprinterdata
2418 JOB_ACCESS_ADMINISTER:
2419 print_job_delete, print_job_pause, print_job_resume,
2422 ****************************************************************************/
2423 BOOL print_access_check(struct current_user *user, int snum, int access_type)
2425 SEC_DESC_BUF *secdesc = NULL;
2426 uint32 access_granted, status, required_access = 0;
2430 extern struct current_user current_user;
2432 /* If user is NULL then use the current_user structure */
2434 if (!user) user = ¤t_user;
2436 /* Always allow root or printer admins to do anything */
2438 if (user->uid == 0 ||
2439 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
2443 /* Get printer name */
2445 pname = PRINTERNAME(snum);
2447 if (!pname || !*pname)
2448 pname = SERVICE(snum);
2450 if (!pname || !*pname) {
2455 /* Get printer security descriptor */
2457 nt_printing_getsec(pname, &secdesc);
2459 /* Check against NT4 ACE mask values. From observation these
2462 Access Type ACE Mask Constant
2463 -------------------------------------
2464 Full Control 0x10000000 PRINTER_ACE_FULL_CONTROL
2465 Print 0xe0000000 PRINTER_ACE_PRINT
2466 Manage Documents 0x00020000 PRINTER_ACE_MANAGE_DOCUMENTS
2469 switch (access_type) {
2470 case PRINTER_ACCESS_USE:
2471 required_access = PRINTER_ACE_PRINT;
2473 case PRINTER_ACCESS_ADMINISTER:
2474 required_access = PRINTER_ACE_MANAGE_DOCUMENTS |
2477 case JOB_ACCESS_ADMINISTER:
2478 required_access = PRINTER_ACE_MANAGE_DOCUMENTS;
2481 DEBUG(0, ("invalid value passed to print_access_check()\n"));
2486 /* The ACE for Full Control in a printer security descriptor
2487 doesn't seem to map properly to the access checking model. For
2488 it to work properly it should be the logical OR of all the other
2489 values, i.e PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT.
2490 This would cause the access check to simply fall out when we
2491 check against any subset of these bits. To get things to work,
2492 change every ACE mask of PRINTER_ACE_FULL_CONTROL to
2493 PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT before
2494 performing the access check. I'm sure there is a better way to
2497 if (secdesc && secdesc->sec && secdesc->sec->dacl &&
2498 secdesc->sec->dacl->ace) {
2499 for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
2500 if (secdesc->sec->dacl->ace[i].info.mask ==
2501 PRINTER_ACE_FULL_CONTROL) {
2502 secdesc->sec->dacl->ace[i].info.mask =
2503 PRINTER_ACE_MANAGE_DOCUMENTS |
2509 if ((result = se_access_check(secdesc->sec, user, required_access,
2510 &access_granted, &status))) {
2514 /* Check against NT5 ACE mask values. From observation these
2517 Access Type ACE Mask Constant
2518 -------------------------------------
2519 Full Control 0x000f000c PRINTER_ACE_NT5_FULL_CONTROL
2520 Print 0x00020008 PRINTER_ACE_NT5_PRINT
2521 Manage Documents 0x00020000 PRINTER_ACE_NT5_MANAGE_DOCUMENTS
2523 NT5 likes to rewrite the security descriptor and change the ACE
2524 masks from NT4 format to NT5 format making them unreadable by
2527 switch (access_type) {
2528 case PRINTER_ACCESS_USE:
2529 required_access = PRINTER_ACE_NT5_PRINT;
2531 case PRINTER_ACCESS_ADMINISTER:
2532 required_access = PRINTER_ACE_NT5_FULL_CONTROL;
2534 case JOB_ACCESS_ADMINISTER:
2535 required_access = PRINTER_ACE_NT5_MANAGE_DOCUMENTS;
2539 result = se_access_check(secdesc->sec, user, required_access,
2540 &access_granted, &status);
2545 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
2547 /* Free mallocated memory */
2549 free_sec_desc_buf(&secdesc);
2557 /****************************************************************************
2558 Check the time parameters allow a print operation.
2559 *****************************************************************************/
2561 BOOL print_time_access_check(int snum)
2563 NT_PRINTER_INFO_LEVEL *printer = NULL;
2565 time_t now = time(NULL);
2569 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2572 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
2576 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
2578 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
2581 free_a_printer(&printer, 2);