This commit was manufactured by cvs2svn to create branch 'SAMBA_2_2'.
[Samba.git] / source / printing / nt_printing.c
blob91679235cd70f6a09e5372f090d635a1bf6cdd73
1 #define OLD_NTDOMAIN 1
2 /*
3 * Unix SMB/Netbios implementation.
4 * Version 1.9.
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.
24 #include "includes.h"
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);
57 if (!tdb) {
58 DEBUG(0,("Failed to open nt drivers database\n"));
59 return False;
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);
72 return True;
76 /****************************************************************************
77 get a form struct list
78 ****************************************************************************/
79 int get_ntforms(nt_forms_struct **list)
81 TDB_DATA kbuf, newkey, dbuf;
82 nt_forms_struct form;
83 int ret;
84 int i;
85 int n = 0;
87 for (kbuf = tdb_firstkey(tdb);
88 kbuf.dptr;
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);
99 safe_free(dbuf.dptr);
100 if (ret != dbuf.dsize) continue;
102 /* allocate space and populate the list in correct order */
103 if (i+1 > n) {
104 *list = Realloc(*list, sizeof(nt_forms_struct)*(i+1));
105 n = i+1;
107 (*list)[i] = form;
110 /* we should never return a null forms list or NT gets unhappy */
111 if (n == 0) {
112 *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms));
113 n = sizeof(default_forms) / sizeof(default_forms[0]);
117 return n;
120 /****************************************************************************
121 write a form struct list
122 ****************************************************************************/
123 int write_ntforms(nt_forms_struct **list, int number)
125 pstring buf, key;
126 int len;
127 TDB_DATA kbuf,dbuf;
128 int i;
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,
135 (*list)[i].bottom);
136 if (len > sizeof(buf)) break;
137 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[i].name);
138 kbuf.dsize = strlen(key)+1;
139 kbuf.dptr = key;
140 dbuf.dsize = len;
141 dbuf.dptr = buf;
142 if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) break;
145 return i;
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)
153 int n=0;
154 BOOL update;
155 fstring form_name;
158 * NT tries to add forms even when
159 * they are already in the base
160 * only update the values if already present
163 update=False;
165 unistr2_to_ascii(form_name, &form->name, sizeof(form_name)-1);
166 for (n=0; n<*count; n++) {
167 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
168 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name));
169 update=True;
170 break;
174 if (update==False) {
175 if((*list=Realloc(*list, (n+1)*sizeof(nt_forms_struct))) == NULL)
176 return False;
177 unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name)-1);
178 (*count)++;
181 (*list)[n].flag=form->flags;
182 (*list)[n].width=form->size_x;
183 (*list)[n].length=form->size_y;
184 (*list)[n].left=form->left;
185 (*list)[n].top=form->top;
186 (*list)[n].right=form->right;
187 (*list)[n].bottom=form->bottom;
189 return True;
192 /****************************************************************************
193 delete a named form struct
194 ****************************************************************************/
195 BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
197 pstring key;
198 TDB_DATA kbuf;
199 int n=0;
200 fstring form_name;
202 *ret = 0;
204 if (*count == 1) {
206 * Don't delete the last form (no empty lists).
207 * CHECKME ! Is this correct ? JRA.
209 *ret = ERROR_INVALID_PARAMETER;
210 return False;
213 unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
215 for (n=0; n<*count; n++) {
216 if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
217 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
218 break;
222 if (n == *count) {
223 DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
224 *ret = ERROR_INVALID_PARAMETER;
225 return False;
228 slprintf(key, sizeof(key), "%s%s", FORMS_PREFIX, (*list)[n].name);
229 kbuf.dsize = strlen(key)+1;
230 kbuf.dptr = key;
231 if (tdb_delete(tdb, kbuf) != 0) {
232 *ret = ERROR_NOT_ENOUGH_MEMORY;
233 return False;
236 return True;
239 /****************************************************************************
240 update a form struct
241 ****************************************************************************/
242 void update_a_form(nt_forms_struct **list, const FORM *form, int count)
244 int n=0;
245 fstring form_name;
246 unistr2_to_ascii(form_name, &(form->name), sizeof(form_name)-1);
248 DEBUG(106, ("[%s]\n", form_name));
249 for (n=0; n<count; n++)
251 DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
252 if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
253 break;
256 if (n==count) return;
258 (*list)[n].flag=form->flags;
259 (*list)[n].width=form->size_x;
260 (*list)[n].length=form->size_y;
261 (*list)[n].left=form->left;
262 (*list)[n].top=form->top;
263 (*list)[n].right=form->right;
264 (*list)[n].bottom=form->bottom;
267 /****************************************************************************
268 get the nt drivers list
270 traverse the database and look-up the matching names
271 ****************************************************************************/
272 int get_ntdrivers(fstring **list, char *architecture, uint32 version)
274 int total=0;
275 fstring short_archi;
276 pstring key;
277 TDB_DATA kbuf, newkey;
279 get_short_archi(short_archi, architecture);
280 slprintf(key, sizeof(key), "%s%s/%d/", DRIVERS_PREFIX, short_archi, version);
282 for (kbuf = tdb_firstkey(tdb);
283 kbuf.dptr;
284 newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
285 if (strncmp(kbuf.dptr, key, strlen(key)) != 0) continue;
287 if((*list = Realloc(*list, sizeof(fstring)*(total+1))) == NULL)
288 return -1;
290 fstrcpy((*list)[total], kbuf.dptr+strlen(key));
291 total++;
294 return(total);
297 /****************************************************************************
298 function to do the mapping between the long architecture name and
299 the short one.
300 ****************************************************************************/
301 BOOL get_short_archi(char *short_archi, char *long_archi)
303 struct table {
304 char *long_archi;
305 char *short_archi;
308 struct table archi_table[]=
310 {"Windows 4.0", "WIN40" },
311 {"Windows NT x86", "W32X86" },
312 {"Windows NT R4000", "W32MIPS" },
313 {"Windows NT Alpha_AXP", "W32ALPHA" },
314 {"Windows NT PowerPC", "W32PPC" },
315 {NULL, "" }
318 int i=-1;
320 DEBUG(107,("Getting architecture dependant directory\n"));
321 do {
322 i++;
323 } while ( (archi_table[i].long_archi!=NULL ) &&
324 StrCaseCmp(long_archi, archi_table[i].long_archi) );
326 if (archi_table[i].long_archi==NULL) {
327 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
328 return FALSE;
331 StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
333 DEBUGADD(108,("index: [%d]\n", i));
334 DEBUGADD(108,("long architecture: [%s]\n", long_archi));
335 DEBUGADD(108,("short architecture: [%s]\n", short_archi));
337 return TRUE;
340 /****************************************************************************
341 Determine the correct cVersion associated with an architecture and driver
342 ****************************************************************************/
343 static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
344 struct current_user *user, uint32 *perr)
346 int cversion;
347 int access_mode;
348 int action;
349 int ecode;
350 char buf[PE_HEADER_SIZE];
351 ssize_t byte_count;
352 pstring driverpath;
353 fstring user_name;
354 fstring null_pw;
355 files_struct *fsp = NULL;
356 BOOL bad_path;
357 SMB_STRUCT_STAT st;
358 struct passwd *pass;
359 connection_struct *conn;
361 ZERO_STRUCT(st);
363 /* If architecture is Windows 95/98, the version is always 0. */
364 if (strcmp(architecture, "WIN40") == 0) {
365 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
366 return 0;
369 become_root();
370 pass = getpwuid(user->uid);
371 if(pass == NULL) {
372 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
373 (unsigned int)user->uid ));
374 unbecome_root();
375 *perr = ERROR_ACCESS_DENIED;
376 return -1;
378 unbecome_root();
380 /* connect to the print$ share under the same account as the user connected
381 * to the rpc pipe */
382 fstrcpy(user_name, pass->pw_name );
383 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
385 /* Null password is ok - we are already an authenticated user... */
386 *null_pw = '\0';
387 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
389 if (conn == NULL) {
390 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
391 *perr = (uint32)ecode;
392 return -1;
395 /* Save who we are - we are temporarily becoming the connection user. */
396 push_sec_ctx();
398 if (!become_user(conn, conn->vuid)) {
399 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
400 *perr = ERROR_ACCESS_DENIED;
401 pop_sec_ctx();
402 return -1;
405 /* Open the driver file (Portable Executable format) and determine the
406 * deriver the cversion. */
407 slprintf(driverpath, sizeof(driverpath), "%s/%s", architecture, driverpath_in);
409 unix_convert(driverpath,conn,NULL,&bad_path,&st);
411 fsp = open_file_shared(conn, driverpath, &st,
412 SET_OPEN_MODE(DOS_OPEN_RDONLY),
413 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
414 0, 0, &access_mode, &action);
415 if (!fsp) {
416 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
417 driverpath, errno));
418 *perr = ERROR_ACCESS_DENIED;
419 goto error_exit;
422 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
423 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
424 driverpath, byte_count));
425 *perr = NT_STATUS_FILE_INVALID;
426 goto error_exit;
429 /* Is this really a DOS header? */
430 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
431 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
432 driverpath, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
433 *perr = NT_STATUS_FILE_INVALID;
434 goto error_exit;
437 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
438 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
439 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
440 driverpath, errno));
441 *perr = NT_STATUS_FILE_INVALID;
442 goto error_exit;
445 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
446 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
447 driverpath, byte_count));
448 *perr = NT_STATUS_FILE_INVALID;
449 goto error_exit;
452 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
453 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
454 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) == PE_HEADER_MACHINE_I386) {
456 switch (SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)) {
457 case 4: cversion = 2; break; /* Win NT 4 */
458 case 5: cversion = 3; break; /* Win 2000 */
459 default:
460 DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
461 driverpath, SVAL(buf,PE_HEADER_MAJOR_OS_VER_OFFSET)));
462 *perr = NT_STATUS_FILE_INVALID;
463 goto error_exit;
465 } else {
466 DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
467 driverpath, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
468 *perr = NT_STATUS_FILE_INVALID;
469 goto error_exit;
472 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
473 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) == NE_HEADER_TARGOS_WIN ) {
475 switch (CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)) {
476 case 3: cversion = 0; break; /* Win 3.x / Win 9x / Win ME */
477 /* case ?: cversion = 1; break;*/ /* Win NT 3.51 ... needs research JRR */
478 default:
479 DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
480 driverpath, CVAL(buf,NE_HEADER_MAJOR_VER_OFFSET)));
481 *perr = NT_STATUS_FILE_INVALID;
482 goto error_exit;
484 } else {
485 DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
486 driverpath, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
487 *perr = NT_STATUS_FILE_INVALID;
488 goto error_exit;
491 } else {
492 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
493 driverpath, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
494 *perr = NT_STATUS_FILE_INVALID;
495 goto error_exit;
498 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
499 driverpath, cversion));
501 fsp->conn->vfs_ops.close(fsp, fsp->fd);
502 file_free(fsp);
503 close_cnum(conn, user->vuid);
504 pop_sec_ctx();
505 return cversion;
508 error_exit:
509 if(fsp) {
510 if(fsp->fd != -1)
511 fsp->conn->vfs_ops.close(fsp, fsp->fd);
512 file_free(fsp);
515 close_cnum(conn, user->vuid);
516 pop_sec_ctx();
517 return -1;
520 /****************************************************************************
521 ****************************************************************************/
522 static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
523 struct current_user *user)
525 fstring architecture;
526 fstring new_name;
527 char *p;
528 int i;
529 uint32 err;
531 /* clean up the driver name.
532 * we can get .\driver.dll
533 * or worse c:\windows\system\driver.dll !
535 /* using an intermediate string to not have overlaping memcpy()'s */
536 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
537 fstrcpy(new_name, p+1);
538 fstrcpy(driver->driverpath, new_name);
541 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
542 fstrcpy(new_name, p+1);
543 fstrcpy(driver->datafile, new_name);
546 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
547 fstrcpy(new_name, p+1);
548 fstrcpy(driver->configfile, new_name);
551 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
552 fstrcpy(new_name, p+1);
553 fstrcpy(driver->helpfile, new_name);
556 if (driver->dependentfiles) {
557 for (i=0; *driver->dependentfiles[i]; i++) {
558 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
559 fstrcpy(new_name, p+1);
560 fstrcpy(driver->dependentfiles[i], new_name);
565 get_short_archi(architecture, driver->environment);
567 /* jfm:7/16/2000 the client always sends the cversion=0.
568 * The server should check which version the driver is by reading
569 * the PE header of driver->driverpath.
571 * For Windows 95/98 the version is 0 (so the value sent is correct)
572 * For Windows NT (the architecture doesn't matter)
573 * NT 3.1: cversion=0
574 * NT 3.5/3.51: cversion=1
575 * NT 4: cversion=2
576 * NT2K: cversion=3
578 if ((driver->cversion = get_correct_cversion( architecture,
579 driver->driverpath, user, &err)) == -1)
580 return err;
582 return NT_STATUS_NO_PROBLEMO;
585 /****************************************************************************
586 ****************************************************************************/
587 static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
588 struct current_user *user)
590 fstring architecture;
591 fstring new_name;
592 char *p;
593 int i;
594 uint32 err;
596 /* clean up the driver name.
597 * we can get .\driver.dll
598 * or worse c:\windows\system\driver.dll !
600 /* using an intermediate string to not have overlaping memcpy()'s */
601 if ((p = strrchr(driver->driverpath,'\\')) != NULL) {
602 fstrcpy(new_name, p+1);
603 fstrcpy(driver->driverpath, new_name);
606 if ((p = strrchr(driver->datafile,'\\')) != NULL) {
607 fstrcpy(new_name, p+1);
608 fstrcpy(driver->datafile, new_name);
611 if ((p = strrchr(driver->configfile,'\\')) != NULL) {
612 fstrcpy(new_name, p+1);
613 fstrcpy(driver->configfile, new_name);
616 if ((p = strrchr(driver->helpfile,'\\')) != NULL) {
617 fstrcpy(new_name, p+1);
618 fstrcpy(driver->helpfile, new_name);
621 if (driver->dependentfiles) {
622 for (i=0; *driver->dependentfiles[i]; i++) {
623 if ((p = strrchr(driver->dependentfiles[i],'\\')) != NULL) {
624 fstrcpy(new_name, p+1);
625 fstrcpy(driver->dependentfiles[i], new_name);
630 get_short_archi(architecture, driver->environment);
632 /* jfm:7/16/2000 the client always sends the cversion=0.
633 * The server should check which version the driver is by reading
634 * the PE header of driver->driverpath.
636 * For Windows 95/98 the version is 0 (so the value sent is correct)
637 * For Windows NT (the architecture doesn't matter)
638 * NT 3.1: cversion=0
639 * NT 3.5/3.51: cversion=1
640 * NT 4: cversion=2
641 * NT2K: cversion=3
643 if ((driver->version = get_correct_cversion(architecture,
644 driver->driverpath, user, &err)) == -1)
645 return err;
647 return NT_STATUS_NO_PROBLEMO;
650 /****************************************************************************
651 ****************************************************************************/
652 uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
653 uint32 level, struct current_user *user)
655 switch (level) {
656 case 3:
658 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
659 driver=driver_abstract.info_3;
660 return clean_up_driver_struct_level_3(driver, user);
662 case 6:
664 NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
665 driver=driver_abstract.info_6;
666 return clean_up_driver_struct_level_6(driver, user);
668 default:
669 return ERROR_INVALID_PARAMETER;
673 /****************************************************************************
674 This function sucks and should be replaced. JRA.
675 ****************************************************************************/
677 static void convert_level_6_to_level3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dst, NT_PRINTER_DRIVER_INFO_LEVEL_6 *src)
679 dst->cversion = src->version;
681 fstrcpy( dst->name, src->name);
682 fstrcpy( dst->environment, src->environment);
683 fstrcpy( dst->driverpath, src->driverpath);
684 fstrcpy( dst->datafile, src->datafile);
685 fstrcpy( dst->configfile, src->configfile);
686 fstrcpy( dst->helpfile, src->helpfile);
687 fstrcpy( dst->monitorname, src->monitorname);
688 fstrcpy( dst->defaultdatatype, src->defaultdatatype);
689 dst->dependentfiles = src->dependentfiles;
692 #if 0 /* Debugging function */
694 static char* ffmt(unsigned char *c){
695 int i;
696 static char ffmt_str[17];
698 for (i=0; i<16; i++) {
699 if ((c[i] < ' ') || (c[i] > '~'))
700 ffmt_str[i]='.';
701 else
702 ffmt_str[i]=c[i];
704 ffmt_str[16]='\0';
705 return ffmt_str;
708 #endif
710 /****************************************************************************
711 Version information in Microsoft files is held in a VS_VERSION_INFO structure.
712 There are two case to be covered here: PE (Portable Executable) and NE (New
713 Executable) files. Both files support the same INFO structure, but PE files
714 store the signature in unicode, and NE files store it as !unicode.
715 ****************************************************************************/
716 static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
717 uint32 *minor)
719 int i;
720 char *buf;
721 ssize_t byte_count;
723 if ((buf=malloc(PE_HEADER_SIZE)) == NULL) {
724 DEBUG(0,("get_file_version: PE file [%s] PE Header malloc failed bytes = %d\n",
725 fname, PE_HEADER_SIZE));
726 goto error_exit;
729 /* Note: DOS_HEADER_SIZE < malloc'ed PE_HEADER_SIZE */
730 if ((byte_count = vfs_read_data(fsp, buf, DOS_HEADER_SIZE)) < DOS_HEADER_SIZE) {
731 DEBUG(3,("get_file_version: File [%s] DOS header too short, bytes read = %d\n",
732 fname, byte_count));
733 goto no_version_info;
736 /* Is this really a DOS header? */
737 if (SVAL(buf,DOS_HEADER_MAGIC_OFFSET) != DOS_HEADER_MAGIC) {
738 DEBUG(6,("get_file_version: File [%s] bad DOS magic = 0x%x\n",
739 fname, SVAL(buf,DOS_HEADER_MAGIC_OFFSET)));
740 goto no_version_info;
743 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
744 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) {
745 DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n",
746 fname, errno));
747 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
748 goto no_version_info;
751 if ((byte_count = vfs_read_data(fsp, buf, PE_HEADER_SIZE)) < PE_HEADER_SIZE) {
752 DEBUG(3,("get_file_version: File [%s] Windows header too short, bytes read = %d\n",
753 fname, byte_count));
754 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
755 goto no_version_info;
758 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
759 if (IVAL(buf,PE_HEADER_SIGNATURE_OFFSET) == PE_HEADER_SIGNATURE) {
760 int num_sections;
761 int section_table_bytes;
763 if (SVAL(buf,PE_HEADER_MACHINE_OFFSET) != PE_HEADER_MACHINE_I386) {
764 DEBUG(3,("get_file_version: PE file [%s] wrong machine = 0x%x\n",
765 fname, SVAL(buf,PE_HEADER_MACHINE_OFFSET)));
766 /* At this point, we assume the file is in error. It still could be somthing
767 * else besides a PE file, but it unlikely at this point.
769 goto error_exit;
772 /* get the section table */
773 num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
774 section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
775 free(buf);
776 if ((buf=malloc(section_table_bytes)) == NULL) {
777 DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
778 fname, section_table_bytes));
779 goto error_exit;
782 if ((byte_count = vfs_read_data(fsp, buf, section_table_bytes)) < section_table_bytes) {
783 DEBUG(3,("get_file_version: PE file [%s] Section header too short, bytes read = %d\n",
784 fname, byte_count));
785 goto error_exit;
788 /* Iterate the section table looking for the resource section ".rsrc" */
789 for (i = 0; i < num_sections; i++) {
790 int sec_offset = i * PE_HEADER_SECT_HEADER_SIZE;
792 if (strcmp(".rsrc", &buf[sec_offset+PE_HEADER_SECT_NAME_OFFSET]) == 0) {
793 int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
794 int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
796 free(buf);
797 if ((buf=malloc(section_bytes)) == NULL) {
798 DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
799 fname, section_bytes));
800 goto error_exit;
803 /* Seek to the start of the .rsrc section info */
804 if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) {
805 DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n",
806 fname, errno));
807 goto error_exit;
810 if ((byte_count = vfs_read_data(fsp, buf, section_bytes)) < section_bytes) {
811 DEBUG(3,("get_file_version: PE file [%s] .rsrc section too short, bytes read = %d\n",
812 fname, byte_count));
813 goto error_exit;
816 for (i=0; i<section_bytes-VS_VERSION_INFO_UNICODE_SIZE; i++) {
817 /* Scan for 1st 3 unicoded bytes followed by word aligned magic value */
818 if (buf[i] == 'V' && buf[i+1] == '\0' && buf[i+2] == 'S') {
819 /* Align to next long address */
820 int pos = (i + sizeof(VS_SIGNATURE)*2 + 3) & 0xfffffffc;
822 if (IVAL(buf,pos) == VS_MAGIC_VALUE) {
823 *major = IVAL(buf,pos+VS_MAJOR_OFFSET);
824 *minor = IVAL(buf,pos+VS_MINOR_OFFSET);
826 DEBUG(6,("get_file_version: PE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
827 fname, *major, *minor,
828 (*major>>16)&0xffff, *major&0xffff,
829 (*minor>>16)&0xffff, *minor&0xffff));
830 free(buf);
831 return True;
838 /* Version info not found, fall back to origin date/time */
839 DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
840 free(buf);
841 return False;
843 } else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
844 if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
845 DEBUG(3,("get_file_version: NE file [%s] wrong target OS = 0x%x\n",
846 fname, CVAL(buf,NE_HEADER_TARGET_OS_OFFSET)));
847 /* At this point, we assume the file is in error. It still could be somthing
848 * else besides a NE file, but it unlikely at this point. */
849 goto error_exit;
852 /* Allocate a bit more space to speed up things */
853 free(buf);
854 if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
855 DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
856 fname, PE_HEADER_SIZE));
857 goto error_exit;
860 /* This is a HACK! I got tired of trying to sort through the messy
861 * 'NE' file format. If anyone wants to clean this up please have at
862 * it, but this works. 'NE' files will eventually fade away. JRR */
863 while((byte_count = vfs_read_data(fsp, buf, VS_NE_BUF_SIZE)) > 0) {
864 /* Cover case that should not occur in a well formed 'NE' .dll file */
865 if (byte_count-VS_VERSION_INFO_SIZE <= 0) break;
867 for(i=0; i<byte_count; i++) {
868 /* Fast skip past data that can't possibly match */
869 if (buf[i] != 'V') continue;
871 /* Potential match data crosses buf boundry, move it to beginning
872 * of buf, and fill the buf with as much as it will hold. */
873 if (i>byte_count-VS_VERSION_INFO_SIZE) {
874 int bc;
876 memcpy(buf, &buf[i], byte_count-i);
877 if ((bc = vfs_read_data(fsp, &buf[byte_count-i], VS_NE_BUF_SIZE-
878 (byte_count-i))) < 0) {
880 DEBUG(0,("get_file_version: NE file [%s] Read error, errno=%d\n",
881 fname, errno));
882 goto error_exit;
885 byte_count = bc + (byte_count - i);
886 if (byte_count<VS_VERSION_INFO_SIZE) break;
888 i = 0;
891 /* Check that the full signature string and the magic number that
892 * follows exist (not a perfect solution, but the chances that this
893 * occurs in code is, well, remote. Yes I know I'm comparing the 'V'
894 * twice, as it is simpler to read the code. */
895 if (strcmp(&buf[i], VS_SIGNATURE) == 0) {
896 /* Compute skip alignment to next long address */
897 int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) +
898 sizeof(VS_SIGNATURE)) & 3;
899 if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue;
901 *major = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MAJOR_OFFSET);
902 *minor = IVAL(buf,i+sizeof(VS_SIGNATURE)+skip+VS_MINOR_OFFSET);
903 DEBUG(6,("get_file_version: NE file [%s] Version = %08x:%08x (%d.%d.%d.%d)\n",
904 fname, *major, *minor,
905 (*major>>16)&0xffff, *major&0xffff,
906 (*minor>>16)&0xffff, *minor&0xffff));
907 free(buf);
908 return True;
913 /* Version info not found, fall back to origin date/time */
914 DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
915 free(buf);
916 return False;
918 } else
919 /* Assume this isn't an error... the file just looks sort of like a PE/NE file */
920 DEBUG(3,("get_file_version: File [%s] unknown file format, signature = 0x%x\n",
921 fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
923 no_version_info:
924 free(buf);
925 return False;
927 error_exit:
928 free(buf);
929 return -1;
932 /****************************************************************************
933 Drivers for Microsoft systems contain multiple files. Often, multiple drivers
934 share one or more files. During the MS installation process files are checked
935 to insure that only a newer version of a shared file is installed over an
936 older version. There are several possibilities for this comparison. If there
937 is no previous version, the new one is newer (obviously). If either file is
938 missing the version info structure, compare the creation date (on Unix use
939 the modification date). Otherwise chose the numerically larger version number.
940 ****************************************************************************/
941 static int file_version_is_newer(connection_struct *conn, fstring new_file,
942 fstring old_file)
944 BOOL use_version = True;
945 pstring filepath;
947 uint32 new_major;
948 uint32 new_minor;
949 time_t new_create_time;
951 uint32 old_major;
952 uint32 old_minor;
953 time_t old_create_time;
955 int access_mode;
956 int action;
957 files_struct *fsp = NULL;
958 SMB_STRUCT_STAT st;
959 SMB_STRUCT_STAT stat_buf;
960 BOOL bad_path;
962 ZERO_STRUCT(st);
963 ZERO_STRUCT(stat_buf);
964 new_create_time = (time_t)0;
965 old_create_time = (time_t)0;
967 /* Get file version info (if available) for previous file (if it exists) */
968 pstrcpy(filepath, old_file);
970 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
972 fsp = open_file_shared(conn, filepath, &stat_buf,
973 SET_OPEN_MODE(DOS_OPEN_RDONLY),
974 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
975 0, 0, &access_mode, &action);
976 if (!fsp) {
977 /* Old file not found, so by definition new file is in fact newer */
978 DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
979 filepath, errno));
980 return True;
982 } else {
983 int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
984 if (ret == -1) goto error_exit;
986 if (!ret) {
987 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
988 old_file));
989 use_version = False;
990 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
991 old_create_time = st.st_mtime;
992 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
995 fsp->conn->vfs_ops.close(fsp, fsp->fd);
996 file_free(fsp);
999 /* Get file version info (if available) for new file */
1000 pstrcpy(filepath, new_file);
1001 unix_convert(filepath,conn,NULL,&bad_path,&stat_buf);
1003 fsp = open_file_shared(conn, filepath, &stat_buf,
1004 SET_OPEN_MODE(DOS_OPEN_RDONLY),
1005 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
1006 0, 0, &access_mode, &action);
1007 if (!fsp) {
1008 /* New file not found, this shouldn't occur if the caller did its job */
1009 DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
1010 filepath, errno));
1011 goto error_exit;
1013 } else {
1014 int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
1015 if (ret == -1) goto error_exit;
1017 if (!ret) {
1018 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
1019 new_file));
1020 use_version = False;
1021 if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit;
1022 new_create_time = st.st_mtime;
1023 DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
1026 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1027 file_free(fsp);
1029 if (use_version) {
1030 /* Compare versions and choose the larger version number */
1031 if (new_major > old_major ||
1032 (new_major == old_major && new_minor > old_minor)) {
1034 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1035 return True;
1037 else {
1038 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1039 return False;
1042 } else {
1043 /* Compare modification time/dates and choose the newest time/date */
1044 if (new_create_time > old_create_time) {
1045 DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
1046 return True;
1048 else {
1049 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
1050 return False;
1054 error_exit:
1055 if(fsp) {
1056 file_free(fsp);
1057 if(fsp->fd != -1)
1058 fsp->conn->vfs_ops.close(fsp, fsp->fd);
1060 return -1;
1063 /****************************************************************************
1064 ****************************************************************************/
1065 BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
1067 NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
1068 NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
1069 fstring architecture;
1070 pstring new_dir;
1071 pstring old_name;
1072 pstring new_name;
1073 fstring user_name;
1074 fstring null_pw;
1075 connection_struct *conn;
1076 pstring inbuf;
1077 pstring outbuf;
1078 struct passwd *pass;
1079 int ecode;
1080 int ver = 0;
1081 int outsize = 0;
1082 int i;
1084 *perr = 0;
1085 memset(inbuf, '\0', sizeof(inbuf));
1086 memset(outbuf, '\0', sizeof(outbuf));
1088 if (level==3)
1089 driver=driver_abstract.info_3;
1090 else if (level==6) {
1091 convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
1092 driver = &converted_driver;
1093 } else {
1094 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
1095 return False;
1098 get_short_archi(architecture, driver->environment);
1100 become_root();
1101 pass = getpwuid(user->uid);
1102 if(pass == NULL) {
1103 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1104 (unsigned int)user->uid ));
1105 unbecome_root();
1106 return False;
1108 unbecome_root();
1110 /* connect to the print$ share under the same account as the user connected to the rpc pipe */
1111 fstrcpy(user_name, pass->pw_name );
1112 DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
1114 /* Null password is ok - we are already an authenticated user... */
1115 *null_pw = '\0';
1116 conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
1118 if (conn == NULL) {
1119 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1120 *perr = (uint32)ecode;
1121 return False;
1125 * Save who we are - we are temporarily becoming the connection user.
1128 push_sec_ctx();
1130 if (!become_user(conn, conn->vuid)) {
1131 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name ));
1132 pop_sec_ctx();
1133 return False;
1137 * make the directories version and version\driver_name
1138 * under the architecture directory.
1140 DEBUG(5,("Creating first directory\n"));
1141 slprintf(new_dir, sizeof(new_dir), "%s/%d", architecture, driver->cversion);
1142 mkdir_internal(conn, inbuf, outbuf, new_dir);
1144 /* For each driver file, archi\filexxx.yyy, if there is a duplicate file
1145 * listed for this driver which has already been moved, skip it (note:
1146 * drivers may list the same file name several times. Then check if the
1147 * file already exists in archi\cversion\, if so, check that the version
1148 * info (or time stamps if version info is unavailable) is newer (or the
1149 * date is later). If it is, move it to archi\cversion\filexxx.yyy.
1150 * Otherwise, delete the file.
1152 * If a file is not moved to archi\cversion\ because of an error, all the
1153 * rest of the 'unmoved' driver files are removed from archi\. If one or
1154 * more of the driver's files was already moved to archi\cversion\, it
1155 * potentially leaves the driver in a partially updated state. Version
1156 * trauma will most likely occur if an client attempts to use any printer
1157 * bound to the driver. Perhaps a rewrite to make sure the moves can be
1158 * done is appropriate... later JRR
1161 DEBUG(5,("Moving files now !\n"));
1163 if (driver->driverpath && strlen(driver->driverpath)) {
1164 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->driverpath);
1165 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->driverpath);
1166 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1167 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1168 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1169 new_name, old_name));
1170 *perr = (uint32)SVAL(outbuf,smb_err);
1171 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1172 ver = -1;
1175 else
1176 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1179 if (driver->datafile && strlen(driver->datafile)) {
1180 if (!strequal(driver->datafile, driver->driverpath)) {
1181 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->datafile);
1182 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->datafile);
1183 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1184 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1185 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1186 new_name, old_name));
1187 *perr = (uint32)SVAL(outbuf,smb_err);
1188 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1189 ver = -1;
1192 else
1193 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1197 if (driver->configfile && strlen(driver->configfile)) {
1198 if (!strequal(driver->configfile, driver->driverpath) &&
1199 !strequal(driver->configfile, driver->datafile)) {
1200 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->configfile);
1201 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->configfile);
1202 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1203 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1204 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1205 new_name, old_name));
1206 *perr = (uint32)SVAL(outbuf,smb_err);
1207 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1208 ver = -1;
1211 else
1212 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1216 if (driver->helpfile && strlen(driver->helpfile)) {
1217 if (!strequal(driver->helpfile, driver->driverpath) &&
1218 !strequal(driver->helpfile, driver->datafile) &&
1219 !strequal(driver->helpfile, driver->configfile)) {
1220 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->helpfile);
1221 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->helpfile);
1222 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1223 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1224 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1225 new_name, old_name));
1226 *perr = (uint32)SVAL(outbuf,smb_err);
1227 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1228 ver = -1;
1231 else
1232 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1236 if (driver->dependentfiles) {
1237 for (i=0; *driver->dependentfiles[i]; i++) {
1238 if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
1239 !strequal(driver->dependentfiles[i], driver->datafile) &&
1240 !strequal(driver->dependentfiles[i], driver->configfile) &&
1241 !strequal(driver->dependentfiles[i], driver->helpfile)) {
1242 int j;
1243 for (j=0; j < i; j++) {
1244 if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
1245 goto NextDriver;
1249 slprintf(new_name, sizeof(new_name), "%s/%s", architecture, driver->dependentfiles[i]);
1250 slprintf(old_name, sizeof(old_name), "%s/%s", new_dir, driver->dependentfiles[i]);
1251 if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
1252 if ((outsize = rename_internals(conn, inbuf, outbuf, new_name, old_name, True)) != 0) {
1253 DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
1254 new_name, old_name));
1255 *perr = (uint32)SVAL(outbuf,smb_err);
1256 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1257 ver = -1;
1260 else
1261 unlink_internals(conn, inbuf, outbuf, 0, new_name);
1263 NextDriver: ;
1267 close_cnum(conn, user->vuid);
1268 pop_sec_ctx();
1270 return ver == -1 ? False : True;
1273 /****************************************************************************
1274 ****************************************************************************/
1275 static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
1277 int len, buflen;
1278 fstring architecture;
1279 pstring directory;
1280 pstring temp_name;
1281 pstring key;
1282 char *buf;
1283 int i, ret;
1284 TDB_DATA kbuf, dbuf;
1286 get_short_archi(architecture, driver->environment);
1288 /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx
1289 * \\server is added in the rpc server layer.
1290 * It does make sense to NOT store the server's name in the printer TDB.
1293 slprintf(directory, sizeof(directory), "\\print$\\%s\\%d\\", architecture, driver->cversion);
1296 fstrcpy(temp_name, driver->driverpath);
1297 slprintf(driver->driverpath, sizeof(driver->driverpath), "%s%s", directory, temp_name);
1299 fstrcpy(temp_name, driver->datafile);
1300 slprintf(driver->datafile, sizeof(driver->datafile), "%s%s", directory, temp_name);
1302 fstrcpy(temp_name, driver->configfile);
1303 slprintf(driver->configfile, sizeof(driver->configfile), "%s%s", directory, temp_name);
1305 fstrcpy(temp_name, driver->helpfile);
1306 slprintf(driver->helpfile, sizeof(driver->helpfile), "%s%s", directory, temp_name);
1308 if (driver->dependentfiles) {
1309 for (i=0; *driver->dependentfiles[i]; i++) {
1310 fstrcpy(temp_name, driver->dependentfiles[i]);
1311 slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i]), "%s%s", directory, temp_name);
1315 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, driver->cversion, driver->name);
1317 DEBUG(5,("add_a_printer_driver_3: Adding driver with key %s\n", key ));
1319 buf = NULL;
1320 len = buflen = 0;
1322 again:
1323 len = 0;
1324 len += tdb_pack(buf+len, buflen-len, "dffffffff",
1325 driver->cversion,
1326 driver->name,
1327 driver->environment,
1328 driver->driverpath,
1329 driver->datafile,
1330 driver->configfile,
1331 driver->helpfile,
1332 driver->monitorname,
1333 driver->defaultdatatype);
1335 if (driver->dependentfiles) {
1336 for (i=0; *driver->dependentfiles[i]; i++) {
1337 len += tdb_pack(buf+len, buflen-len, "f",
1338 driver->dependentfiles[i]);
1342 if (len != buflen) {
1343 buf = (char *)Realloc(buf, len);
1344 buflen = len;
1345 goto again;
1349 kbuf.dptr = key;
1350 kbuf.dsize = strlen(key)+1;
1351 dbuf.dptr = buf;
1352 dbuf.dsize = len;
1354 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1356 if (ret)
1357 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
1359 safe_free(buf);
1360 return ret;
1363 /****************************************************************************
1364 ****************************************************************************/
1365 static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
1367 NT_PRINTER_DRIVER_INFO_LEVEL_3 info3;
1369 ZERO_STRUCT(info3);
1370 info3.cversion = driver->version;
1371 fstrcpy(info3.name,driver->name);
1372 fstrcpy(info3.environment,driver->environment);
1373 fstrcpy(info3.driverpath,driver->driverpath);
1374 fstrcpy(info3.datafile,driver->datafile);
1375 fstrcpy(info3.configfile,driver->configfile);
1376 fstrcpy(info3.helpfile,driver->helpfile);
1377 fstrcpy(info3.monitorname,driver->monitorname);
1378 fstrcpy(info3.defaultdatatype,driver->defaultdatatype);
1379 info3.dependentfiles = driver->dependentfiles;
1381 return add_a_printer_driver_3(&info3);
1385 /****************************************************************************
1386 ****************************************************************************/
1387 static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
1389 NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
1391 ZERO_STRUCT(info);
1393 fstrcpy(info.name, in_prt);
1394 fstrcpy(info.defaultdatatype, "RAW");
1396 fstrcpy(info.driverpath, "");
1397 fstrcpy(info.datafile, "");
1398 fstrcpy(info.configfile, "");
1399 fstrcpy(info.helpfile, "");
1401 if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
1402 return ERROR_NOT_ENOUGH_MEMORY;
1404 memset(info.dependentfiles, '\0', 2*sizeof(fstring));
1405 fstrcpy(info.dependentfiles[0], "");
1407 *info_ptr = memdup(&info, sizeof(info));
1409 return 0;
1412 /****************************************************************************
1413 ****************************************************************************/
1414 static uint32 get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
1416 NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
1417 TDB_DATA kbuf, dbuf;
1418 fstring architecture;
1419 int len = 0;
1420 int i;
1421 pstring key;
1423 ZERO_STRUCT(driver);
1425 get_short_archi(architecture, in_arch);
1427 DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
1429 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
1431 kbuf.dptr = key;
1432 kbuf.dsize = strlen(key)+1;
1434 dbuf = tdb_fetch(tdb, kbuf);
1435 #if 0
1436 if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1437 #else
1438 if (!dbuf.dptr) return 5;
1439 #endif
1440 len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
1441 &driver.cversion,
1442 driver.name,
1443 driver.environment,
1444 driver.driverpath,
1445 driver.datafile,
1446 driver.configfile,
1447 driver.helpfile,
1448 driver.monitorname,
1449 driver.defaultdatatype);
1451 i=0;
1452 while (len < dbuf.dsize) {
1453 driver.dependentfiles = (fstring *)Realloc(driver.dependentfiles,
1454 sizeof(fstring)*(i+2));
1455 if (driver.dependentfiles == NULL)
1456 break;
1458 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f",
1459 &driver.dependentfiles[i]);
1460 i++;
1462 if (driver.dependentfiles != NULL)
1463 fstrcpy(driver.dependentfiles[i], "");
1465 safe_free(dbuf.dptr);
1467 if (len != dbuf.dsize) {
1468 if (driver.dependentfiles != NULL)
1469 safe_free(driver.dependentfiles);
1471 return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
1474 *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
1476 return 0;
1479 /****************************************************************************
1480 ****************************************************************************/
1481 uint32 get_a_printer_driver_9x_compatible(pstring line, fstring model)
1483 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1484 TDB_DATA kbuf;
1485 pstring key;
1486 int i;
1487 line[0] = '\0';
1489 slprintf(key, sizeof(key), "%s%s/%d/%s", DRIVERS_PREFIX, "WIN40", 0, model);
1490 DEBUG(10,("driver key: [%s]\n", key));
1492 kbuf.dptr = key;
1493 kbuf.dsize = strlen(key)+1;
1494 if (!tdb_exists(tdb, kbuf)) return False;
1496 ZERO_STRUCT(info3);
1497 get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
1499 DEBUGADD(10,("info3->name [%s]\n", info3->name));
1500 DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
1501 DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
1502 DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
1503 DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
1504 for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
1505 DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
1507 DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
1508 DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
1509 DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
1511 /*pstrcat(line, info3->name); pstrcat(line, ":");*/
1512 trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
1513 pstrcat(line, info3->configfile);
1514 pstrcat(line, ":");
1515 trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
1516 pstrcat(line, info3->datafile);
1517 pstrcat(line, ":");
1518 trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
1519 pstrcat(line, info3->helpfile);
1520 pstrcat(line, ":");
1521 trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
1522 pstrcat(line, info3->monitorname);
1523 pstrcat(line, ":");
1524 pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
1525 pstrcat(line, ":");
1527 for (i=0; info3->dependentfiles &&
1528 *info3->dependentfiles[i]; i++) {
1529 if (i) pstrcat(line, ","); /* don't end in a "," */
1530 trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
1531 pstrcat(line, info3->dependentfiles[i]);
1534 free(info3);
1536 return True;
1539 /****************************************************************************
1540 debugging function, dump at level 6 the struct in the logs
1541 ****************************************************************************/
1542 static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
1544 uint32 result;
1545 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
1546 int i;
1548 DEBUG(106,("Dumping printer driver at level [%d]\n", level));
1550 switch (level)
1552 case 3:
1554 if (driver.info_3 == NULL)
1555 result=5;
1556 else {
1557 info3=driver.info_3;
1559 DEBUGADD(106,("version:[%d]\n", info3->cversion));
1560 DEBUGADD(106,("name:[%s]\n", info3->name));
1561 DEBUGADD(106,("environment:[%s]\n", info3->environment));
1562 DEBUGADD(106,("driverpath:[%s]\n", info3->driverpath));
1563 DEBUGADD(106,("datafile:[%s]\n", info3->datafile));
1564 DEBUGADD(106,("configfile:[%s]\n", info3->configfile));
1565 DEBUGADD(106,("helpfile:[%s]\n", info3->helpfile));
1566 DEBUGADD(106,("monitorname:[%s]\n", info3->monitorname));
1567 DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
1569 for (i=0; info3->dependentfiles &&
1570 *info3->dependentfiles[i]; i++) {
1571 DEBUGADD(106,("dependentfile:[%s]\n",
1572 info3->dependentfiles[i]));
1574 result=0;
1576 break;
1578 default:
1579 DEBUGADD(1,("Level not implemented\n"));
1580 result=1;
1581 break;
1584 return result;
1587 /****************************************************************************
1588 ****************************************************************************/
1589 static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
1591 int len = 0;
1593 len += tdb_pack(buf+len, buflen-len, "p", nt_devmode);
1595 if (!nt_devmode) return len;
1597 len += tdb_pack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
1598 nt_devmode->devicename,
1599 nt_devmode->formname,
1601 nt_devmode->specversion,
1602 nt_devmode->driverversion,
1603 nt_devmode->size,
1604 nt_devmode->driverextra,
1605 nt_devmode->orientation,
1606 nt_devmode->papersize,
1607 nt_devmode->paperlength,
1608 nt_devmode->paperwidth,
1609 nt_devmode->scale,
1610 nt_devmode->copies,
1611 nt_devmode->defaultsource,
1612 nt_devmode->printquality,
1613 nt_devmode->color,
1614 nt_devmode->duplex,
1615 nt_devmode->yresolution,
1616 nt_devmode->ttoption,
1617 nt_devmode->collate,
1618 nt_devmode->logpixels,
1620 nt_devmode->fields,
1621 nt_devmode->bitsperpel,
1622 nt_devmode->pelswidth,
1623 nt_devmode->pelsheight,
1624 nt_devmode->displayflags,
1625 nt_devmode->displayfrequency,
1626 nt_devmode->icmmethod,
1627 nt_devmode->icmintent,
1628 nt_devmode->mediatype,
1629 nt_devmode->dithertype,
1630 nt_devmode->reserved1,
1631 nt_devmode->reserved2,
1632 nt_devmode->panningwidth,
1633 nt_devmode->panningheight,
1634 nt_devmode->private);
1637 if (nt_devmode->private) {
1638 len += tdb_pack(buf+len, buflen-len, "B",
1639 nt_devmode->driverextra,
1640 nt_devmode->private);
1643 DEBUG(8,("Packed devicemode [%s]\n", nt_devmode->formname));
1645 return len;
1648 /****************************************************************************
1649 ****************************************************************************/
1650 static int pack_specifics(NT_PRINTER_PARAM *param, char *buf, int buflen)
1652 int len = 0;
1654 while (param != NULL) {
1655 len += tdb_pack(buf+len, buflen-len, "pfdB",
1656 param,
1657 param->value,
1658 param->type,
1659 param->data_len,
1660 param->data);
1661 param=param->next;
1664 len += tdb_pack(buf+len, buflen-len, "p", param);
1666 return len;
1670 /****************************************************************************
1671 delete a printer - this just deletes the printer info file, any open
1672 handles are not affected
1673 ****************************************************************************/
1674 uint32 del_a_printer(char *sharename)
1676 pstring key;
1677 TDB_DATA kbuf;
1679 slprintf(key, sizeof(key), "%s%s",
1680 PRINTERS_PREFIX, sharename);
1682 kbuf.dptr=key;
1683 kbuf.dsize=strlen(key)+1;
1685 tdb_delete(tdb, kbuf);
1686 return 0;
1689 /****************************************************************************
1690 ****************************************************************************/
1691 static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
1693 pstring key;
1694 char *buf;
1695 int buflen, len, ret;
1696 TDB_DATA kbuf, dbuf;
1699 * in addprinter: no servername and the printer is the name
1700 * in setprinter: servername is \\server
1701 * and printer is \\server\\printer
1703 * Samba manages only local printers.
1704 * we currently don't support things like path=\\other_server\printer
1707 if (info->servername[0]!='\0') {
1708 trim_string(info->printername, info->servername, NULL);
1709 trim_string(info->printername, "\\", NULL);
1710 info->servername[0]='\0';
1714 * JFM: one day I'll forget.
1715 * below that's info->portname because that's the SAMBA sharename
1716 * and I made NT 'thinks' it's the portname
1717 * the info->sharename is the thing you can name when you add a printer
1718 * that's the short-name when you create shared printer for 95/98
1719 * So I've made a limitation in SAMBA: you can only have 1 printer model
1720 * behind a SAMBA share.
1723 buf = NULL;
1724 buflen = 0;
1726 again:
1727 len = 0;
1728 len += tdb_pack(buf+len, buflen-len, "dddddddddddfffffPfffff",
1729 info->attributes,
1730 info->priority,
1731 info->default_priority,
1732 info->starttime,
1733 info->untiltime,
1734 info->status,
1735 info->cjobs,
1736 info->averageppm,
1737 info->changeid,
1738 info->c_setprinter,
1739 info->setuptime,
1740 info->servername,
1741 info->printername,
1742 info->sharename,
1743 info->portname,
1744 info->drivername,
1745 info->comment,
1746 info->location,
1747 info->sepfile,
1748 info->printprocessor,
1749 info->datatype,
1750 info->parameters);
1752 len += pack_devicemode(info->devmode, buf+len, buflen-len);
1753 len += pack_specifics(info->specific, buf+len, buflen-len);
1755 if (buflen != len) {
1756 buf = (char *)Realloc(buf, len);
1757 buflen = len;
1758 goto again;
1762 slprintf(key, sizeof(key), "%s%s",
1763 PRINTERS_PREFIX, info->sharename);
1765 kbuf.dptr = key;
1766 kbuf.dsize = strlen(key)+1;
1767 dbuf.dptr = buf;
1768 dbuf.dsize = len;
1770 ret = tdb_store(tdb, kbuf, dbuf, TDB_REPLACE);
1772 if (ret == -1)
1773 DEBUG(8, ("error updating printer to tdb on disk\n"));
1775 safe_free(buf);
1777 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1778 info->sharename, info->drivername, info->portname, len));
1780 return ret;
1784 /****************************************************************************
1785 ****************************************************************************/
1786 void add_a_specific_param(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM **param)
1788 NT_PRINTER_PARAM *current;
1790 DEBUG(108,("add_a_specific_param\n"));
1792 (*param)->next=NULL;
1794 if (info_2->specific == NULL)
1796 info_2->specific=*param;
1798 else
1800 current=info_2->specific;
1801 while (current->next != NULL) {
1802 current=current->next;
1804 current->next=*param;
1807 *param = NULL;
1810 /****************************************************************************
1811 ****************************************************************************/
1812 BOOL unlink_specific_param_if_exist(NT_PRINTER_INFO_LEVEL_2 *info_2, NT_PRINTER_PARAM *param)
1814 NT_PRINTER_PARAM *current;
1815 NT_PRINTER_PARAM *previous;
1817 current=info_2->specific;
1818 previous=current;
1820 if (current==NULL) return (False);
1822 if ( !strcmp(current->value, param->value) &&
1823 (strlen(current->value)==strlen(param->value)) ) {
1824 DEBUG(109,("deleting first value\n"));
1825 info_2->specific=current->next;
1826 safe_free(current->data);
1827 safe_free(current);
1828 DEBUG(109,("deleted first value\n"));
1829 return (True);
1832 current=previous->next;
1834 while ( current!=NULL ) {
1835 if (!strcmp(current->value, param->value) &&
1836 strlen(current->value)==strlen(param->value) ) {
1837 DEBUG(109,("deleting current value\n"));
1838 previous->next=current->next;
1839 safe_free(current->data);
1840 safe_free(current);
1841 DEBUG(109,("deleted current value\n"));
1842 return(True);
1845 previous=previous->next;
1846 current=current->next;
1848 return (False);
1851 /****************************************************************************
1852 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_PARAM.
1853 ****************************************************************************/
1854 void free_nt_printer_param(NT_PRINTER_PARAM **param_ptr)
1856 NT_PRINTER_PARAM *param = *param_ptr;
1858 if(param == NULL)
1859 return;
1861 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
1863 if(param->data)
1864 safe_free(param->data);
1866 safe_free(param);
1867 *param_ptr = NULL;
1870 /****************************************************************************
1871 Malloc and return an NT devicemode.
1872 ****************************************************************************/
1874 NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
1877 * should I init this ones ???
1878 nt_devmode->devicename
1881 char adevice[32];
1882 NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
1884 if (nt_devmode == NULL) {
1885 DEBUG(0,("construct_nt_devicemode: malloc fail.\n"));
1886 return NULL;
1889 ZERO_STRUCTP(nt_devmode);
1891 safe_strcpy(adevice, default_devicename, sizeof(adevice));
1892 fstrcpy(nt_devmode->devicename, adevice);
1894 fstrcpy(nt_devmode->formname, "Letter");
1896 nt_devmode->specversion = 0x0401;
1897 nt_devmode->driverversion = 0x0400;
1898 nt_devmode->size = 0x00DC;
1899 nt_devmode->driverextra = 0x0000;
1900 nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
1901 DEFAULTSOURCE | COPIES | SCALE |
1902 PAPERSIZE | ORIENTATION;
1903 nt_devmode->orientation = 1;
1904 nt_devmode->papersize = PAPER_LETTER;
1905 nt_devmode->paperlength = 0;
1906 nt_devmode->paperwidth = 0;
1907 nt_devmode->scale = 0x64;
1908 nt_devmode->copies = 01;
1909 nt_devmode->defaultsource = BIN_FORMSOURCE;
1910 nt_devmode->printquality = RES_HIGH; /* 0x0258 */
1911 nt_devmode->color = COLOR_MONOCHROME;
1912 nt_devmode->duplex = DUP_SIMPLEX;
1913 nt_devmode->yresolution = 0;
1914 nt_devmode->ttoption = TT_SUBDEV;
1915 nt_devmode->collate = COLLATE_FALSE;
1916 nt_devmode->icmmethod = 0;
1917 nt_devmode->icmintent = 0;
1918 nt_devmode->mediatype = 0;
1919 nt_devmode->dithertype = 0;
1921 /* non utilisés par un driver d'imprimante */
1922 nt_devmode->logpixels = 0;
1923 nt_devmode->bitsperpel = 0;
1924 nt_devmode->pelswidth = 0;
1925 nt_devmode->pelsheight = 0;
1926 nt_devmode->displayflags = 0;
1927 nt_devmode->displayfrequency = 0;
1928 nt_devmode->reserved1 = 0;
1929 nt_devmode->reserved2 = 0;
1930 nt_devmode->panningwidth = 0;
1931 nt_devmode->panningheight = 0;
1933 nt_devmode->private=NULL;
1935 return nt_devmode;
1938 /****************************************************************************
1939 Deepcopy an NT devicemode.
1940 ****************************************************************************/
1942 NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
1944 NT_DEVICEMODE *new_nt_devicemode = NULL;
1946 if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
1947 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1948 return NULL;
1951 new_nt_devicemode->private = NULL;
1952 if (nt_devicemode->private != NULL) {
1953 if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
1954 safe_free(new_nt_devicemode);
1955 DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
1956 return NULL;
1960 return new_nt_devicemode;
1963 /****************************************************************************
1964 Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
1965 ****************************************************************************/
1967 void free_nt_devicemode(NT_DEVICEMODE **devmode_ptr)
1969 NT_DEVICEMODE *nt_devmode = *devmode_ptr;
1971 if(nt_devmode == NULL)
1972 return;
1974 DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
1976 if(nt_devmode->private)
1977 safe_free(nt_devmode->private);
1979 safe_free(nt_devmode);
1980 *devmode_ptr = NULL;
1983 /****************************************************************************
1984 Clean up and deallocate a (maybe partially) allocated NT_PRINTER_INFO_LEVEL_2.
1985 ****************************************************************************/
1986 static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
1988 NT_PRINTER_INFO_LEVEL_2 *info = *info_ptr;
1989 NT_PRINTER_PARAM *param_ptr;
1991 if(info == NULL)
1992 return;
1994 DEBUG(106,("free_nt_printer_info_level_2: deleting info\n"));
1996 free_nt_devicemode(&info->devmode);
1997 free_sec_desc_buf(&info->secdesc_buf);
1999 for(param_ptr = info->specific; param_ptr; ) {
2000 NT_PRINTER_PARAM *tofree = param_ptr;
2002 param_ptr = param_ptr->next;
2003 free_nt_printer_param(&tofree);
2006 safe_free(*info_ptr);
2007 *info_ptr = NULL;
2011 /****************************************************************************
2012 ****************************************************************************/
2013 static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
2015 int len = 0;
2016 int extra_len = 0;
2017 NT_DEVICEMODE devmode;
2019 ZERO_STRUCT(devmode);
2021 len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
2023 if (!*nt_devmode) return len;
2025 len += tdb_unpack(buf+len, buflen-len, "ffwwwwwwwwwwwwwwwwwwddddddddddddddp",
2026 devmode.devicename,
2027 devmode.formname,
2029 &devmode.specversion,
2030 &devmode.driverversion,
2031 &devmode.size,
2032 &devmode.driverextra,
2033 &devmode.orientation,
2034 &devmode.papersize,
2035 &devmode.paperlength,
2036 &devmode.paperwidth,
2037 &devmode.scale,
2038 &devmode.copies,
2039 &devmode.defaultsource,
2040 &devmode.printquality,
2041 &devmode.color,
2042 &devmode.duplex,
2043 &devmode.yresolution,
2044 &devmode.ttoption,
2045 &devmode.collate,
2046 &devmode.logpixels,
2048 &devmode.fields,
2049 &devmode.bitsperpel,
2050 &devmode.pelswidth,
2051 &devmode.pelsheight,
2052 &devmode.displayflags,
2053 &devmode.displayfrequency,
2054 &devmode.icmmethod,
2055 &devmode.icmintent,
2056 &devmode.mediatype,
2057 &devmode.dithertype,
2058 &devmode.reserved1,
2059 &devmode.reserved2,
2060 &devmode.panningwidth,
2061 &devmode.panningheight,
2062 &devmode.private);
2064 if (devmode.private) {
2065 /* the len in tdb_unpack is an int value and
2066 * devmoce.driverextra is only a short
2068 len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private);
2069 devmode.driverextra=(uint16)extra_len;
2071 /* check to catch an invalid TDB entry so we don't segfault */
2072 if (devmode.driverextra == 0) {
2073 devmode.private = NULL;
2077 *nt_devmode = (NT_DEVICEMODE *)memdup(&devmode, sizeof(devmode));
2079 DEBUG(8,("Unpacked devicemode [%s](%s)\n", devmode.devicename, devmode.formname));
2080 if (devmode.private)
2081 DEBUG(8,("with a private section of %d bytes\n", devmode.driverextra));
2083 return len;
2086 /****************************************************************************
2087 ****************************************************************************/
2088 static int unpack_specifics(NT_PRINTER_PARAM **list, char *buf, int buflen)
2090 int len = 0;
2091 NT_PRINTER_PARAM param, *p;
2093 *list = NULL;
2095 while (1) {
2096 len += tdb_unpack(buf+len, buflen-len, "p", &p);
2097 if (!p) break;
2099 len += tdb_unpack(buf+len, buflen-len, "fdB",
2100 param.value,
2101 &param.type,
2102 &param.data_len,
2103 &param.data);
2104 param.next = *list;
2105 *list = memdup(&param, sizeof(param));
2107 DEBUG(8,("specific: [%s], len: %d\n", param.value, param.data_len));
2110 return len;
2114 /****************************************************************************
2115 get a default printer info 2 struct
2116 ****************************************************************************/
2117 static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2119 extern pstring global_myname;
2120 int snum;
2121 NT_PRINTER_INFO_LEVEL_2 info;
2123 ZERO_STRUCT(info);
2125 snum = lp_servicenumber(sharename);
2127 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2128 slprintf(info.printername, sizeof(info.printername), "\\\\%s\\%s",
2129 global_myname, sharename);
2130 fstrcpy(info.sharename, sharename);
2131 fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
2132 fstrcpy(info.drivername, lp_printerdriver(snum));
2134 if (!*info.drivername)
2135 fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
2137 DEBUG(10,("get_a_printer_2_default: driver name set to [%s]\n", info.drivername));
2139 pstrcpy(info.comment, "");
2140 fstrcpy(info.printprocessor, "winprint");
2141 fstrcpy(info.datatype, "RAW");
2143 info.attributes = PRINTER_ATTRIBUTE_SHARED \
2144 | PRINTER_ATTRIBUTE_LOCAL \
2145 | PRINTER_ATTRIBUTE_RAW_ONLY \
2146 | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
2148 info.starttime = 0; /* Minutes since 12:00am GMT */
2149 info.untiltime = 0; /* Minutes since 12:00am GMT */
2150 info.priority = 1;
2151 info.default_priority = 1;
2152 info.setuptime = (uint32)time(NULL);
2154 if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
2155 goto fail;
2157 if (!nt_printing_getsec(sharename, &info.secdesc_buf))
2158 goto fail;
2160 *info_ptr = (NT_PRINTER_INFO_LEVEL_2 *)memdup(&info, sizeof(info));
2161 if (! *info_ptr) {
2162 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2163 goto fail;
2166 return (0);
2168 fail:
2170 if (info.devmode)
2171 free_nt_devicemode(&info.devmode);
2172 if (info.secdesc_buf)
2173 free_sec_desc_buf(&info.secdesc_buf);
2174 return 2;
2177 /****************************************************************************
2178 ****************************************************************************/
2179 static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
2181 pstring key;
2182 NT_PRINTER_INFO_LEVEL_2 info;
2183 int len = 0;
2184 TDB_DATA kbuf, dbuf;
2185 fstring printername;
2187 ZERO_STRUCT(info);
2189 slprintf(key, sizeof(key), "%s%s", PRINTERS_PREFIX, sharename);
2191 kbuf.dptr = key;
2192 kbuf.dsize = strlen(key)+1;
2194 dbuf = tdb_fetch(tdb, kbuf);
2195 if (!dbuf.dptr)
2196 return get_a_printer_2_default(info_ptr, sharename);
2198 len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "dddddddddddfffffPfffff",
2199 &info.attributes,
2200 &info.priority,
2201 &info.default_priority,
2202 &info.starttime,
2203 &info.untiltime,
2204 &info.status,
2205 &info.cjobs,
2206 &info.averageppm,
2207 &info.changeid,
2208 &info.c_setprinter,
2209 &info.setuptime,
2210 info.servername,
2211 info.printername,
2212 info.sharename,
2213 info.portname,
2214 info.drivername,
2215 info.comment,
2216 info.location,
2217 info.sepfile,
2218 info.printprocessor,
2219 info.datatype,
2220 info.parameters);
2222 /* Samba has to have shared raw drivers. */
2223 info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
2225 /* Restore the stripped strings. */
2226 slprintf(info.servername, sizeof(info.servername), "\\\\%s", global_myname);
2227 slprintf(printername, sizeof(printername), "\\\\%s\\%s", global_myname,
2228 info.printername);
2229 fstrcpy(info.printername, printername);
2231 len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
2232 len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
2234 nt_printing_getsec(sharename, &info.secdesc_buf);
2236 safe_free(dbuf.dptr);
2237 *info_ptr=memdup(&info, sizeof(info));
2239 DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
2240 sharename, info.printername, info.drivername));
2243 return 0;
2246 /****************************************************************************
2247 debugging function, dump at level 6 the struct in the logs
2248 ****************************************************************************/
2249 static uint32 dump_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2251 uint32 result;
2252 NT_PRINTER_INFO_LEVEL_2 *info2;
2254 DEBUG(106,("Dumping printer at level [%d]\n", level));
2256 switch (level)
2258 case 2:
2260 if (printer.info_2 == NULL)
2261 result=5;
2262 else
2264 info2=printer.info_2;
2266 DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
2267 DEBUGADD(106,("priority:[%d]\n", info2->priority));
2268 DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
2269 DEBUGADD(106,("starttime:[%d]\n", info2->starttime));
2270 DEBUGADD(106,("untiltime:[%d]\n", info2->untiltime));
2271 DEBUGADD(106,("status:[%d]\n", info2->status));
2272 DEBUGADD(106,("cjobs:[%d]\n", info2->cjobs));
2273 DEBUGADD(106,("averageppm:[%d]\n", info2->averageppm));
2274 DEBUGADD(106,("changeid:[%d]\n", info2->changeid));
2275 DEBUGADD(106,("c_setprinter:[%d]\n", info2->c_setprinter));
2276 DEBUGADD(106,("setuptime:[%d]\n", info2->setuptime));
2278 DEBUGADD(106,("servername:[%s]\n", info2->servername));
2279 DEBUGADD(106,("printername:[%s]\n", info2->printername));
2280 DEBUGADD(106,("sharename:[%s]\n", info2->sharename));
2281 DEBUGADD(106,("portname:[%s]\n", info2->portname));
2282 DEBUGADD(106,("drivername:[%s]\n", info2->drivername));
2283 DEBUGADD(106,("comment:[%s]\n", info2->comment));
2284 DEBUGADD(106,("location:[%s]\n", info2->location));
2285 DEBUGADD(106,("sepfile:[%s]\n", info2->sepfile));
2286 DEBUGADD(106,("printprocessor:[%s]\n", info2->printprocessor));
2287 DEBUGADD(106,("datatype:[%s]\n", info2->datatype));
2288 DEBUGADD(106,("parameters:[%s]\n", info2->parameters));
2289 result=0;
2291 break;
2293 default:
2294 DEBUGADD(1,("Level not implemented\n"));
2295 result=1;
2296 break;
2299 return result;
2302 /****************************************************************************
2303 Get the parameters we can substitute in an NT print job.
2304 ****************************************************************************/
2306 void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
2308 NT_PRINTER_INFO_LEVEL *printer = NULL;
2310 **printername = **sharename = **portname = '\0';
2312 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
2313 return;
2315 fstrcpy(*printername, printer->info_2->printername);
2316 fstrcpy(*sharename, printer->info_2->sharename);
2317 fstrcpy(*portname, printer->info_2->portname);
2319 free_a_printer(&printer, 2);
2323 * The function below are the high level ones.
2324 * only those ones must be called from the spoolss code.
2325 * JFM.
2328 /****************************************************************************
2329 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2330 ****************************************************************************/
2332 uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2334 uint32 result;
2336 dump_a_printer(printer, level);
2338 switch (level)
2340 case 2:
2342 printer.info_2->c_setprinter++;
2343 result=update_a_printer_2(printer.info_2);
2344 break;
2346 default:
2347 result=1;
2348 break;
2351 return result;
2354 /****************************************************************************
2355 Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
2356 We split this out from mod_a_printer as it updates the id's and timestamps.
2357 ****************************************************************************/
2359 uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
2361 uint32 result;
2363 dump_a_printer(printer, level);
2365 switch (level)
2367 case 2:
2370 * Update the changestamp.
2371 * Note we must *not* do this in mod_a_printer().
2373 NTTIME time_nt;
2374 time_t time_unix = time(NULL);
2375 unix_to_nt_time(&time_nt, time_unix);
2376 printer.info_2->changeid=time_nt.low;
2378 printer.info_2->c_setprinter++;
2379 result=update_a_printer_2(printer.info_2);
2380 break;
2382 default:
2383 result=1;
2384 break;
2387 return result;
2390 /****************************************************************************
2391 Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
2392 ****************************************************************************/
2394 uint32 get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename)
2396 uint32 result;
2397 NT_PRINTER_INFO_LEVEL *printer = NULL;
2399 *pp_printer = NULL;
2401 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
2403 switch (level)
2405 case 2:
2407 if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
2408 DEBUG(0,("get_a_printer: malloc fail.\n"));
2409 return 1;
2411 ZERO_STRUCTP(printer);
2412 result=get_a_printer_2(&printer->info_2, sharename);
2413 if (result == 0) {
2414 dump_a_printer(*printer, level);
2415 *pp_printer = printer;
2416 } else {
2417 safe_free(printer);
2419 break;
2421 default:
2422 result=1;
2423 break;
2426 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename, (unsigned int)level, (unsigned int)result));
2428 return result;
2431 /****************************************************************************
2432 Deletes a NT_PRINTER_INFO_LEVEL struct.
2433 ****************************************************************************/
2435 uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level)
2437 uint32 result;
2438 NT_PRINTER_INFO_LEVEL *printer = *pp_printer;
2440 DEBUG(104,("freeing a printer at level [%d]\n", level));
2442 if (printer == NULL)
2443 return 0;
2445 switch (level)
2447 case 2:
2449 if (printer->info_2 != NULL)
2451 free_nt_printer_info_level_2(&printer->info_2);
2452 result=0;
2454 else
2456 result=4;
2458 break;
2460 default:
2461 result=1;
2462 break;
2465 safe_free(printer);
2466 *pp_printer = NULL;
2467 return result;
2470 /****************************************************************************
2471 ****************************************************************************/
2472 uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2474 uint32 result;
2475 DEBUG(104,("adding a printer at level [%d]\n", level));
2476 dump_a_printer_driver(driver, level);
2478 switch (level)
2480 case 3:
2482 result=add_a_printer_driver_3(driver.info_3);
2483 break;
2486 case 6:
2488 result=add_a_printer_driver_6(driver.info_6);
2489 break;
2491 default:
2492 result=1;
2493 break;
2496 return result;
2498 /****************************************************************************
2499 ****************************************************************************/
2500 uint32 get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
2501 fstring printername, fstring architecture, uint32 version)
2503 uint32 result;
2505 switch (level)
2507 case 3:
2509 result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
2510 break;
2512 default:
2513 result=1;
2514 break;
2517 if (result == 0)
2518 dump_a_printer_driver(*driver, level);
2519 return result;
2522 /****************************************************************************
2523 ****************************************************************************/
2524 uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
2526 uint32 result;
2528 switch (level)
2530 case 3:
2532 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
2533 if (driver.info_3 != NULL)
2535 info3=driver.info_3;
2536 safe_free(info3->dependentfiles);
2537 ZERO_STRUCTP(info3);
2538 safe_free(info3);
2539 result=0;
2541 else
2543 result=4;
2545 break;
2547 case 6:
2549 NT_PRINTER_DRIVER_INFO_LEVEL_6 *info6;
2550 if (driver.info_6 != NULL)
2552 info6=driver.info_6;
2553 safe_free(info6->dependentfiles);
2554 safe_free(info6->previousnames);
2555 ZERO_STRUCTP(info6);
2556 safe_free(info6);
2557 result=0;
2559 else
2561 result=4;
2563 break;
2565 default:
2566 result=1;
2567 break;
2569 return result;
2572 /****************************************************************************
2573 ****************************************************************************/
2574 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
2575 fstring value, uint8 **data, uint32 *type, uint32 *len)
2577 /* right now that's enough ! */
2578 NT_PRINTER_PARAM *param;
2579 int i=0;
2581 param=printer.info_2->specific;
2583 while (param != NULL && i < param_index) {
2584 param=param->next;
2585 i++;
2588 if (param == NULL)
2589 return False;
2591 /* exited because it exist */
2592 *type=param->type;
2593 StrnCpy(value, param->value, sizeof(fstring)-1);
2594 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2595 if(*data == NULL)
2596 return False;
2597 ZERO_STRUCTP(*data);
2598 memcpy(*data, param->data, param->data_len);
2599 *len=param->data_len;
2600 return True;
2603 /****************************************************************************
2604 ****************************************************************************/
2605 BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
2606 fstring value, uint8 **data, uint32 *type, uint32 *len)
2608 /* right now that's enough ! */
2609 NT_PRINTER_PARAM *param;
2611 DEBUG(105, ("get_specific_param\n"));
2613 param=printer.info_2->specific;
2615 while (param != NULL)
2617 #if 1 /* JRA - I think this should be case insensitive.... */
2618 if ( strequal(value, param->value)
2619 #else
2620 if ( !strcmp(value, param->value)
2621 #endif
2622 && strlen(value)==strlen(param->value))
2623 break;
2625 param=param->next;
2628 DEBUG(106, ("found one param\n"));
2629 if (param != NULL)
2631 /* exited because it exist */
2632 *type=param->type;
2634 *data=(uint8 *)malloc(param->data_len*sizeof(uint8));
2635 if(*data == NULL)
2636 return False;
2637 memcpy(*data, param->data, param->data_len);
2638 *len=param->data_len;
2640 DEBUG(106, ("exit of get_specific_param:true\n"));
2641 return (True);
2643 DEBUG(106, ("exit of get_specific_param:false\n"));
2644 return (False);
2647 /****************************************************************************
2648 Store a security desc for a printer.
2649 ****************************************************************************/
2651 uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
2653 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2654 SEC_DESC_BUF *old_secdesc_ctr = NULL;
2655 prs_struct ps;
2656 TALLOC_CTX *mem_ctx = NULL;
2657 fstring key;
2658 uint32 status;
2660 mem_ctx = talloc_init();
2661 if (mem_ctx == NULL)
2662 return False;
2664 /* The old owner and group sids of the security descriptor are not
2665 present when new ACEs are added or removed by changing printer
2666 permissions through NT. If they are NULL in the new security
2667 descriptor then copy them over from the old one. */
2669 if (!secdesc_ctr->sec->owner_sid || !secdesc_ctr->sec->grp_sid) {
2670 DOM_SID *owner_sid, *group_sid;
2671 SEC_ACL *dacl, *sacl;
2672 SEC_DESC *psd = NULL;
2673 size_t size;
2675 nt_printing_getsec(printername, &old_secdesc_ctr);
2677 /* Pick out correct owner and group sids */
2679 owner_sid = secdesc_ctr->sec->owner_sid ?
2680 secdesc_ctr->sec->owner_sid :
2681 old_secdesc_ctr->sec->owner_sid;
2683 group_sid = secdesc_ctr->sec->grp_sid ?
2684 secdesc_ctr->sec->grp_sid :
2685 old_secdesc_ctr->sec->grp_sid;
2687 dacl = secdesc_ctr->sec->dacl ?
2688 secdesc_ctr->sec->dacl :
2689 old_secdesc_ctr->sec->dacl;
2691 sacl = secdesc_ctr->sec->sacl ?
2692 secdesc_ctr->sec->sacl :
2693 old_secdesc_ctr->sec->sacl;
2695 /* Make a deep copy of the security descriptor */
2697 psd = make_sec_desc(secdesc_ctr->sec->revision,
2698 owner_sid, group_sid,
2699 sacl,
2700 dacl,
2701 &size);
2703 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2705 /* Free up memory */
2707 free_sec_desc(&psd);
2708 free_sec_desc_buf(&old_secdesc_ctr);
2711 if (!new_secdesc_ctr) {
2712 new_secdesc_ctr = secdesc_ctr;
2715 /* Store the security descriptor in a tdb */
2717 prs_init(&ps, (uint32)sec_desc_size(new_secdesc_ctr->sec) +
2718 sizeof(SEC_DESC_BUF), 4, mem_ctx, MARSHALL);
2720 if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
2721 &ps, 1)) {
2722 status = ERROR_INVALID_FUNCTION;
2723 goto out;
2726 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2728 if (tdb_prs_store(tdb, key, &ps)==0) {
2729 status = 0;
2730 } else {
2731 DEBUG(1,("Failed to store secdesc for %s\n", printername));
2732 status = ERROR_INVALID_FUNCTION;
2735 /* Free mallocated memory */
2737 out:
2738 free_sec_desc_buf(&old_secdesc_ctr);
2740 if (new_secdesc_ctr != secdesc_ctr) {
2741 free_sec_desc_buf(&new_secdesc_ctr);
2744 prs_mem_free(&ps);
2745 if (mem_ctx)
2746 talloc_destroy(mem_ctx);
2747 return status;
2750 /****************************************************************************
2751 Construct a default security descriptor buffer for a printer.
2752 ****************************************************************************/
2754 static SEC_DESC_BUF *construct_default_printer_sdb(void)
2756 SEC_ACE ace[3];
2757 SEC_ACCESS sa;
2758 SEC_ACL *psa = NULL;
2759 SEC_DESC_BUF *sdb = NULL;
2760 SEC_DESC *psd = NULL;
2761 DOM_SID owner_sid;
2762 size_t sd_size;
2763 enum SID_NAME_USE name_type;
2765 /* Create an ACE where Everyone is allowed to print */
2767 init_sec_access(&sa, PRINTER_ACE_PRINT);
2768 init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
2769 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2771 /* Make the security descriptor owned by the Administrators group
2772 on the PDC of the domain. */
2774 if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
2775 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2776 } else {
2778 /* Backup plan - make printer owned by admins or root. This should
2779 emulate a lanman printer as security settings can't be
2780 changed. */
2782 if (!lookup_name( "Printer Administrators", &owner_sid, &name_type) &&
2783 !lookup_name( "Administrators", &owner_sid, &name_type) &&
2784 !lookup_name( "Administrator", &owner_sid, &name_type) &&
2785 !lookup_name("root", &owner_sid, &name_type)) {
2786 sid_copy(&owner_sid, &global_sid_World);
2790 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
2791 init_sec_ace(&ace[1], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2792 sa, SEC_ACE_FLAG_OBJECT_INHERIT |
2793 SEC_ACE_FLAG_INHERIT_ONLY);
2795 init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
2796 init_sec_ace(&ace[2], &owner_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
2797 sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
2799 /* The ACL revision number in rpc_secdesc.h differs from the one
2800 created by NT when setting ACE entries in printer
2801 descriptors. NT4 complains about the property being edited by a
2802 NT5 machine. */
2804 #define NT4_ACL_REVISION 0x2
2806 if ((psa = make_sec_acl(NT4_ACL_REVISION, 3, ace)) != NULL) {
2807 psd = make_sec_desc(SEC_DESC_REVISION,
2808 &owner_sid, NULL,
2809 NULL, psa, &sd_size);
2810 free_sec_acl(&psa);
2813 if (!psd) {
2814 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
2815 return NULL;
2818 sdb = make_sec_desc_buf(sd_size, psd);
2820 DEBUG(4,("construct_default_printer_sdb: size = %u.\n",
2821 (unsigned int)sd_size));
2823 free_sec_desc(&psd);
2824 return sdb;
2827 /****************************************************************************
2828 Get a security desc for a printer.
2829 ****************************************************************************/
2831 BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr)
2833 prs_struct ps;
2834 TALLOC_CTX *mem_ctx = NULL;
2835 fstring key;
2837 mem_ctx = talloc_init();
2838 if (mem_ctx == NULL)
2839 return False;
2841 /* Fetch security descriptor from tdb */
2843 slprintf(key, sizeof(key), "SECDESC/%s", printername);
2845 if (tdb_prs_fetch(tdb, key, &ps, mem_ctx)!=0 ||
2846 !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
2848 DEBUG(4,("using default secdesc for %s\n", printername));
2850 if (!(*secdesc_ctr = construct_default_printer_sdb())) {
2851 talloc_destroy(mem_ctx);
2852 return False;
2855 talloc_destroy(mem_ctx);
2856 return True;
2859 /* If security descriptor is owned by S-1-1-0 and winbindd is up,
2860 this security descriptor has been created when winbindd was
2861 down. Take ownership of security descriptor. */
2863 if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
2864 DOM_SID owner_sid;
2865 enum SID_NAME_USE name_type;
2867 /* Change sd owner to workgroup administrator */
2869 if (winbind_lookup_name(lp_workgroup(), &owner_sid,
2870 &name_type)) {
2871 SEC_DESC_BUF *new_secdesc_ctr = NULL;
2872 SEC_DESC *psd = NULL;
2873 size_t size;
2875 /* Create new sd */
2877 sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
2879 psd = make_sec_desc((*secdesc_ctr)->sec->revision,
2880 &owner_sid,
2881 (*secdesc_ctr)->sec->grp_sid,
2882 (*secdesc_ctr)->sec->sacl,
2883 (*secdesc_ctr)->sec->dacl,
2884 &size);
2886 new_secdesc_ctr = make_sec_desc_buf(size, psd);
2888 free_sec_desc(&psd);
2890 /* Swap with other one */
2892 free_sec_desc_buf(secdesc_ctr);
2893 *secdesc_ctr = new_secdesc_ctr;
2895 /* Set it */
2897 nt_printing_setsec(printername, *secdesc_ctr);
2901 if (DEBUGLEVEL >= 10) {
2902 SEC_ACL *acl = (*secdesc_ctr)->sec->dacl;
2903 int i;
2905 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
2906 printername, acl->num_aces));
2908 for (i = 0; i < acl->num_aces; i++) {
2909 fstring sid_str;
2911 sid_to_string(sid_str, &acl->ace[i].sid);
2913 DEBUG(10, ("%s 0x%08x\n", sid_str,
2914 acl->ace[i].info.mask));
2918 prs_mem_free(&ps);
2919 talloc_destroy(mem_ctx);
2920 return True;
2923 /* error code:
2924 0: everything OK
2925 1: level not implemented
2926 2: file doesn't exist
2927 3: can't allocate memory
2928 4: can't free memory
2929 5: non existant struct
2933 A printer and a printer driver are 2 different things.
2934 NT manages them separatelly, Samba does the same.
2935 Why ? Simply because it's easier and it makes sense !
2937 Now explanation: You have 3 printers behind your samba server,
2938 2 of them are the same make and model (laser A and B). But laser B
2939 has an 3000 sheet feeder and laser A doesn't such an option.
2940 Your third printer is an old dot-matrix model for the accounting :-).
2942 If the /usr/local/samba/lib directory (default dir), you will have
2943 5 files to describe all of this.
2945 3 files for the printers (1 by printer):
2946 NTprinter_laser A
2947 NTprinter_laser B
2948 NTprinter_accounting
2949 2 files for the drivers (1 for the laser and 1 for the dot matrix)
2950 NTdriver_printer model X
2951 NTdriver_printer model Y
2953 jfm: I should use this comment for the text file to explain
2954 same thing for the forms BTW.
2955 Je devrais mettre mes commentaires en francais, ca serait mieux :-)
2959 /****************************************************************************
2960 Check a user has permissions to perform the given operation. We use some
2961 constants defined in include/rpc_spoolss.h that look relevant to check
2962 the various actions we perform when checking printer access.
2964 PRINTER_ACCESS_ADMINISTER:
2965 print_queue_pause, print_queue_resume, update_printer_sec,
2966 update_printer, spoolss_addprinterex_level_2,
2967 _spoolss_setprinterdata
2969 PRINTER_ACCESS_USE:
2970 print_job_start
2972 JOB_ACCESS_ADMINISTER:
2973 print_job_delete, print_job_pause, print_job_resume,
2974 print_queue_purge
2976 ****************************************************************************/
2977 BOOL print_access_check(struct current_user *user, int snum, int access_type)
2979 SEC_DESC_BUF *secdesc = NULL;
2980 uint32 access_granted, status, required_access = 0;
2981 BOOL result;
2982 char *pname;
2983 extern struct current_user current_user;
2985 /* If user is NULL then use the current_user structure */
2987 if (!user) user = &current_user;
2989 /* Always allow root or printer admins to do anything */
2991 if (user->uid == 0 ||
2992 user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
2993 return True;
2996 /* Get printer name */
2998 pname = PRINTERNAME(snum);
3000 if (!pname || !*pname)
3001 pname = SERVICE(snum);
3003 if (!pname || !*pname) {
3004 errno = EACCES;
3005 return False;
3008 /* Get printer security descriptor */
3010 nt_printing_getsec(pname, &secdesc);
3012 /* Check against NT4 ACE mask values. From observation these
3013 values are:
3015 Access Type ACE Mask Constant
3016 -------------------------------------
3017 Full Control 0x10000000 PRINTER_ACE_FULL_CONTROL
3018 Print 0xe0000000 PRINTER_ACE_PRINT
3019 Manage Documents 0x00020000 PRINTER_ACE_MANAGE_DOCUMENTS
3022 switch (access_type) {
3023 case PRINTER_ACCESS_USE:
3024 required_access = PRINTER_ACE_PRINT;
3025 break;
3026 case PRINTER_ACCESS_ADMINISTER:
3028 * This should be set to PRINTER_ACE_FULL_CONTROL, not to
3029 * (PRINTER_ACE_PRINT | PRINTER_ACE_MANAGE_DOCUMENTS).
3030 * Doing the latter gives anyone with both PRINTER_ACE_PRINT
3031 * and PRINTER_ACE_MANAGE_DOCUMENTS (in any combination of ACLs)
3032 * full control over all printer functions. This isn't what
3033 * we want.
3035 required_access = PRINTER_ACE_FULL_CONTROL;
3036 break;
3037 case JOB_ACCESS_ADMINISTER:
3038 required_access = PRINTER_ACE_MANAGE_DOCUMENTS;
3039 break;
3040 default:
3041 DEBUG(0, ("invalid value passed to print_access_check()\n"));
3042 result = False;
3043 goto done;
3046 if ((result = se_access_check(secdesc->sec, user, required_access,
3047 &access_granted, &status))) {
3048 goto done;
3051 /* Check against NT5 ACE mask values. From observation these
3052 values are:
3054 Access Type ACE Mask Constant
3055 -------------------------------------
3056 Full Control 0x000f000c PRINTER_ACE_NT5_FULL_CONTROL
3057 Print 0x00020008 PRINTER_ACE_NT5_PRINT
3058 Manage Documents 0x00020000 PRINTER_ACE_NT5_MANAGE_DOCUMENTS
3060 NT5 likes to rewrite the security descriptor and change the ACE
3061 masks from NT4 format to NT5 format making them unreadable by
3062 NT4 clients. */
3064 switch (access_type) {
3065 case PRINTER_ACCESS_USE:
3066 required_access = PRINTER_ACE_NT5_PRINT;
3067 break;
3068 case PRINTER_ACCESS_ADMINISTER:
3069 required_access = PRINTER_ACE_NT5_FULL_CONTROL;
3070 break;
3071 case JOB_ACCESS_ADMINISTER:
3072 required_access = PRINTER_ACE_NT5_MANAGE_DOCUMENTS;
3073 break;
3076 result = se_access_check(secdesc->sec, user, required_access,
3077 &access_granted, &status);
3079 /* Check access */
3081 done:
3082 DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
3084 /* Free mallocated memory */
3086 free_sec_desc_buf(&secdesc);
3088 if (!result)
3089 errno = EACCES;
3091 return result;
3094 /****************************************************************************
3095 Check the time parameters allow a print operation.
3096 *****************************************************************************/
3098 BOOL print_time_access_check(int snum)
3100 NT_PRINTER_INFO_LEVEL *printer = NULL;
3101 BOOL ok = False;
3102 time_t now = time(NULL);
3103 struct tm *t;
3104 uint32 mins;
3106 if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
3107 return False;
3109 if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
3110 ok = True;
3112 t = gmtime(&now);
3113 mins = (uint32)t->tm_hour*60 + (uint32)t->tm_min;
3115 if (mins >= printer->info_2->starttime && mins <= printer->info_2->untiltime)
3116 ok = True;
3118 free_a_printer(&printer, 2);
3120 if (!ok)
3121 errno = EACCES;
3123 return ok;
3127 #undef OLD_NTDOMAIN