3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-2000,
7 * Copyright (C) Jean François Micouleau 1998-2000.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern int DEBUGLEVEL
;
27 extern pstring global_myname
;
28 extern DOM_SID global_sid_World
;
30 static TDB_CONTEXT
*tdb
; /* used for driver files */
32 #define FORMS_PREFIX "FORMS/"
33 #define DRIVERS_PREFIX "DRIVERS/"
34 #define PRINTERS_PREFIX "PRINTERS/"
36 #define DATABASE_VERSION 1
38 /* We need one default form to support our default printer. Msoft adds the
39 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
40 array index). Letter is always first, so (for the current code) additions
41 always put things in the correct order. */
42 static nt_forms_struct default_forms
[] = {
43 {"Letter", 0x2, 0x34b5b, 0x44367, 0x0, 0x0, 0x34b5b, 0x44367},
47 /****************************************************************************
48 open the NT printing tdb
49 ****************************************************************************/
50 BOOL
nt_printing_init(void)
52 static pid_t local_pid
;
53 char *vstring
= "INFO/version";
55 if (tdb
&& local_pid
== sys_getpid()) return True
;
56 tdb
= tdb_open(lock_path("ntdrivers.tdb"), 0, 0, O_RDWR
|O_CREAT
, 0600);
58 DEBUG(0,("Failed to open nt drivers database\n"));
62 local_pid
= sys_getpid();
64 /* handle a Samba upgrade */
65 tdb_lock_bystring(tdb
, vstring
);
66 if (tdb_fetch_int(tdb
, vstring
) != DATABASE_VERSION
) {
67 tdb_traverse(tdb
, (tdb_traverse_func
)tdb_delete
, NULL
);
68 tdb_store_int(tdb
, vstring
, DATABASE_VERSION
);
70 tdb_unlock_bystring(tdb
, vstring
);
76 /****************************************************************************
77 get a form struct list
78 ****************************************************************************/
79 int get_ntforms(nt_forms_struct
**list
)
81 TDB_DATA kbuf
, newkey
, dbuf
;
87 for (kbuf
= tdb_firstkey(tdb
);
89 newkey
= tdb_nextkey(tdb
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
90 if (strncmp(kbuf
.dptr
, FORMS_PREFIX
, strlen(FORMS_PREFIX
)) != 0) continue;
92 dbuf
= tdb_fetch(tdb
, kbuf
);
93 if (!dbuf
.dptr
) continue;
95 fstrcpy(form
.name
, kbuf
.dptr
+strlen(FORMS_PREFIX
));
96 ret
= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dddddddd",
97 &i
, &form
.flag
, &form
.width
, &form
.length
, &form
.left
,
98 &form
.top
, &form
.right
, &form
.bottom
);
100 if (ret
!= dbuf
.dsize
) continue;
102 /* allocate space and populate the list in correct order */
104 *list
= Realloc(*list
, sizeof(nt_forms_struct
)*(i
+1));
110 /* we should never return a null forms list or NT gets unhappy */
112 *list
= (nt_forms_struct
*)memdup(&default_forms
[0], sizeof(default_forms
));
113 n
= sizeof(default_forms
) / sizeof(default_forms
[0]);
120 /****************************************************************************
121 write a form struct list
122 ****************************************************************************/
123 int write_ntforms(nt_forms_struct
**list
, int number
)
130 for (i
=0;i
<number
;i
++) {
131 /* save index, so list is rebuilt in correct order */
132 len
= tdb_pack(buf
, sizeof(buf
), "dddddddd",
133 i
, (*list
)[i
].flag
, (*list
)[i
].width
, (*list
)[i
].length
,
134 (*list
)[i
].left
, (*list
)[i
].top
, (*list
)[i
].right
,
136 if (len
> sizeof(buf
)) break;
137 slprintf(key
, sizeof(key
), "%s%s", FORMS_PREFIX
, (*list
)[i
].name
);
138 kbuf
.dsize
= strlen(key
)+1;
142 if (tdb_store(tdb
, kbuf
, dbuf
, TDB_REPLACE
) != 0) break;
148 /****************************************************************************
149 add a form struct at the end of the list
150 ****************************************************************************/
151 BOOL
add_a_form(nt_forms_struct
**list
, const FORM
*form
, int *count
)
158 * NT tries to add forms even when
159 * they are already in the base
160 * only update the values if already present
165 unistr2_to_ascii(form_name
, &form
->name
, sizeof(form_name
)-1);
166 for (n
=0; n
<*count
; n
++) {
167 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
168 DEBUG(103, ("NT workaround, [%s] already exists\n", form_name
));
175 if((*list
=Realloc(*list
, (n
+1)*sizeof(nt_forms_struct
))) == NULL
)
177 unistr2_to_ascii((*list
)[n
].name
, &form
->name
, sizeof((*list
)[n
].name
)-1);
181 (*list
)[n
].flag
=form
->flags
;
182 (*list
)[n
].width
=form
->size_x
;
183 (*list
)[n
].length
=form
->size_y
;
184 (*list
)[n
].left
=form
->left
;
185 (*list
)[n
].top
=form
->top
;
186 (*list
)[n
].right
=form
->right
;
187 (*list
)[n
].bottom
=form
->bottom
;
192 /****************************************************************************
193 delete a named form struct
194 ****************************************************************************/
195 BOOL
delete_a_form(nt_forms_struct
**list
, UNISTR2
*del_name
, int *count
, uint32
*ret
)
206 * Don't delete the last form (no empty lists).
207 * CHECKME ! Is this correct ? JRA.
209 *ret
= ERROR_INVALID_PARAMETER
;
213 unistr2_to_ascii(form_name
, del_name
, sizeof(form_name
)-1);
215 for (n
=0; n
<*count
; n
++) {
216 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
))) {
217 DEBUG(103, ("delete_a_form, [%s] in list\n", form_name
));
223 DEBUG(10,("delete_a_form, [%s] not found\n", form_name
));
224 *ret
= ERROR_INVALID_PARAMETER
;
228 slprintf(key
, sizeof(key
), "%s%s", FORMS_PREFIX
, (*list
)[n
].name
);
229 kbuf
.dsize
= strlen(key
)+1;
231 if (tdb_delete(tdb
, kbuf
) != 0) {
232 *ret
= ERROR_NOT_ENOUGH_MEMORY
;
239 /****************************************************************************
241 ****************************************************************************/
242 void update_a_form(nt_forms_struct
**list
, const FORM
*form
, int count
)
246 unistr2_to_ascii(form_name
, &(form
->name
), sizeof(form_name
)-1);
248 DEBUG(106, ("[%s]\n", form_name
));
249 for (n
=0; n
<count
; n
++)
251 DEBUGADD(106, ("n [%d]:[%s]\n", n
, (*list
)[n
].name
));
252 if (!strncmp((*list
)[n
].name
, form_name
, strlen(form_name
)))
256 if (n
==count
) return;
258 (*list
)[n
].flag
=form
->flags
;
259 (*list
)[n
].width
=form
->size_x
;
260 (*list
)[n
].length
=form
->size_y
;
261 (*list
)[n
].left
=form
->left
;
262 (*list
)[n
].top
=form
->top
;
263 (*list
)[n
].right
=form
->right
;
264 (*list
)[n
].bottom
=form
->bottom
;
267 /****************************************************************************
268 get the nt drivers list
270 traverse the database and look-up the matching names
271 ****************************************************************************/
272 int get_ntdrivers(fstring
**list
, char *architecture
, uint32 version
)
277 TDB_DATA kbuf
, newkey
;
279 get_short_archi(short_archi
, architecture
);
280 slprintf(key
, sizeof(key
), "%s%s/%d/", DRIVERS_PREFIX
, short_archi
, version
);
282 for (kbuf
= tdb_firstkey(tdb
);
284 newkey
= tdb_nextkey(tdb
, kbuf
), safe_free(kbuf
.dptr
), kbuf
=newkey
) {
285 if (strncmp(kbuf
.dptr
, key
, strlen(key
)) != 0) continue;
287 if((*list
= Realloc(*list
, sizeof(fstring
)*(total
+1))) == NULL
)
290 fstrcpy((*list
)[total
], kbuf
.dptr
+strlen(key
));
297 /****************************************************************************
298 function to do the mapping between the long architecture name and
300 ****************************************************************************/
301 BOOL
get_short_archi(char *short_archi
, char *long_archi
)
308 struct table archi_table
[]=
310 {"Windows 4.0", "WIN40" },
311 {"Windows NT x86", "W32X86" },
312 {"Windows NT R4000", "W32MIPS" },
313 {"Windows NT Alpha_AXP", "W32ALPHA" },
314 {"Windows NT PowerPC", "W32PPC" },
320 DEBUG(107,("Getting architecture dependant directory\n"));
323 } while ( (archi_table
[i
].long_archi
!=NULL
) &&
324 StrCaseCmp(long_archi
, archi_table
[i
].long_archi
) );
326 if (archi_table
[i
].long_archi
==NULL
) {
327 DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi
));
331 StrnCpy (short_archi
, archi_table
[i
].short_archi
, strlen(archi_table
[i
].short_archi
));
333 DEBUGADD(108,("index: [%d]\n", i
));
334 DEBUGADD(108,("long architecture: [%s]\n", long_archi
));
335 DEBUGADD(108,("short architecture: [%s]\n", short_archi
));
340 /****************************************************************************
341 Determine the correct cVersion associated with an architecture and driver
342 ****************************************************************************/
343 static uint32
get_correct_cversion(fstring architecture
, fstring driverpath_in
,
344 struct current_user
*user
, uint32
*perr
)
350 char buf
[PE_HEADER_SIZE
];
355 files_struct
*fsp
= NULL
;
359 connection_struct
*conn
;
363 /* If architecture is Windows 95/98, the version is always 0. */
364 if (strcmp(architecture
, "WIN40") == 0) {
365 DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
370 pass
= getpwuid(user
->uid
);
372 DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
373 (unsigned int)user
->uid
));
375 *perr
= ERROR_ACCESS_DENIED
;
380 /* connect to the print$ share under the same account as the user connected
382 fstrcpy(user_name
, pass
->pw_name
);
383 DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user
->uid
, user_name
));
385 /* Null password is ok - we are already an authenticated user... */
387 conn
= make_connection("print$", user_name
, null_pw
, 0, "A:", user
->vuid
, &ecode
);
390 DEBUG(0,("get_correct_cversion: Unable to connect\n"));
391 *perr
= (uint32
)ecode
;
395 /* Save who we are - we are temporarily becoming the connection user. */
398 if (!become_user(conn
, conn
->vuid
)) {
399 DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name
));
400 *perr
= ERROR_ACCESS_DENIED
;
405 /* Open the driver file (Portable Executable format) and determine the
406 * deriver the cversion. */
407 slprintf(driverpath
, sizeof(driverpath
), "%s/%s", architecture
, driverpath_in
);
409 unix_convert(driverpath
,conn
,NULL
,&bad_path
,&st
);
411 fsp
= open_file_shared(conn
, driverpath
, &st
,
412 SET_OPEN_MODE(DOS_OPEN_RDONLY
),
413 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
414 0, 0, &access_mode
, &action
);
416 DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
418 *perr
= ERROR_ACCESS_DENIED
;
422 if ((byte_count
= vfs_read_data(fsp
, buf
, DOS_HEADER_SIZE
)) < DOS_HEADER_SIZE
) {
423 DEBUG(3,("get_correct_cversion: File [%s] DOS header too short, bytes read = %d\n",
424 driverpath
, byte_count
));
425 *perr
= NT_STATUS_FILE_INVALID
;
429 /* Is this really a DOS header? */
430 if (SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
) != DOS_HEADER_MAGIC
) {
431 DEBUG(6,("get_correct_cversion: File [%s] bad DOS magic = 0x%x\n",
432 driverpath
, SVAL(buf
,DOS_HEADER_MAGIC_OFFSET
)));
433 *perr
= NT_STATUS_FILE_INVALID
;
437 /* Skip OEM header (if any) and the DOS stub to start of Windows header */
438 if (fsp
->conn
->vfs_ops
.lseek(fsp
, fsp
->fd
, SVAL(buf
,DOS_HEADER_LFANEW_OFFSET
), SEEK_SET
) == (SMB_OFF_T
)-1) {
439 DEBUG(3,("get_correct_cversion: File [%s] too short, errno = %d\n",
441 *perr
= NT_STATUS_FILE_INVALID
;
445 if ((byte_count
= vfs_read_data(fsp
, buf
, PE_HEADER_SIZE
)) < PE_HEADER_SIZE
) {
446 DEBUG(3,("get_correct_cversion: File [%s] Windows header too short, bytes read = %d\n",
447 driverpath
, byte_count
));
448 *perr
= NT_STATUS_FILE_INVALID
;
452 /* The header may be a PE (Portable Executable) or an NE (New Executable) */
453 if (IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
) == PE_HEADER_SIGNATURE
) {
454 if (SVAL(buf
,PE_HEADER_MACHINE_OFFSET
) == PE_HEADER_MACHINE_I386
) {
456 switch (SVAL(buf
,PE_HEADER_MAJOR_OS_VER_OFFSET
)) {
457 case 4: cversion
= 2; break; /* Win NT 4 */
458 case 5: cversion
= 3; break; /* Win 2000 */
460 DEBUG(6,("get_correct_cversion: PE formated file [%s] bad version = %d\n",
461 driverpath
, SVAL(buf
,PE_HEADER_MAJOR_OS_VER_OFFSET
)));
462 *perr
= NT_STATUS_FILE_INVALID
;
466 DEBUG(6,("get_correct_cversion: PE formatted file [%s] wrong machine = 0x%x\n",
467 driverpath
, SVAL(buf
,PE_HEADER_MACHINE_OFFSET
)));
468 *perr
= NT_STATUS_FILE_INVALID
;
472 } else if (SVAL(buf
,NE_HEADER_SIGNATURE_OFFSET
) == NE_HEADER_SIGNATURE
) {
473 if (CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
) == NE_HEADER_TARGOS_WIN
) {
475 switch (CVAL(buf
,NE_HEADER_MAJOR_VER_OFFSET
)) {
476 case 3: cversion
= 0; break; /* Win 3.x / Win 9x / Win ME */
477 /* case ?: cversion = 1; break;*/ /* Win NT 3.51 ... needs research JRR */
479 DEBUG(6,("get_correct_cversion: NE formated file [%s] bad version = %d\n",
480 driverpath
, CVAL(buf
,NE_HEADER_MAJOR_VER_OFFSET
)));
481 *perr
= NT_STATUS_FILE_INVALID
;
485 DEBUG(6,("get_correct_cversion: NE formatted file [%s] wrong target OS = 0x%x\n",
486 driverpath
, CVAL(buf
,NE_HEADER_TARGET_OS_OFFSET
)));
487 *perr
= NT_STATUS_FILE_INVALID
;
492 DEBUG(6,("get_correct_cversion: Unknown file format [%s], signature = 0x%x\n",
493 driverpath
, IVAL(buf
,PE_HEADER_SIGNATURE_OFFSET
)));
494 *perr
= NT_STATUS_FILE_INVALID
;
498 DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
499 driverpath
, cversion
));
501 fsp
->conn
->vfs_ops
.close(fsp
, fsp
->fd
);
503 close_cnum(conn
, user
->vuid
);
511 fsp
->conn
->vfs_ops
.close(fsp
, fsp
->fd
);
515 close_cnum(conn
, user
->vuid
);
520 /****************************************************************************
521 ****************************************************************************/
522 static uint32
clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
,
523 struct current_user
*user
)
525 fstring architecture
;
531 /* clean up the driver name.
532 * we can get .\driver.dll
533 * or worse c:\windows\system\driver.dll !
535 /* using an intermediate string to not have overlaping memcpy()'s */
536 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
537 fstrcpy(new_name
, p
+1);
538 fstrcpy(driver
->driverpath
, new_name
);
541 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
542 fstrcpy(new_name
, p
+1);
543 fstrcpy(driver
->datafile
, new_name
);
546 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
547 fstrcpy(new_name
, p
+1);
548 fstrcpy(driver
->configfile
, new_name
);
551 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
552 fstrcpy(new_name
, p
+1);
553 fstrcpy(driver
->helpfile
, new_name
);
556 if (driver
->dependentfiles
) {
557 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
558 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
559 fstrcpy(new_name
, p
+1);
560 fstrcpy(driver
->dependentfiles
[i
], new_name
);
565 get_short_archi(architecture
, driver
->environment
);
567 /* jfm:7/16/2000 the client always sends the cversion=0.
568 * The server should check which version the driver is by reading
569 * the PE header of driver->driverpath.
571 * For Windows 95/98 the version is 0 (so the value sent is correct)
572 * For Windows NT (the architecture doesn't matter)
574 * NT 3.5/3.51: cversion=1
578 if ((driver
->cversion
= get_correct_cversion( architecture
,
579 driver
->driverpath
, user
, &err
)) == -1)
582 return NT_STATUS_NO_PROBLEMO
;
585 /****************************************************************************
586 ****************************************************************************/
587 static uint32
clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
,
588 struct current_user
*user
)
590 fstring architecture
;
596 /* clean up the driver name.
597 * we can get .\driver.dll
598 * or worse c:\windows\system\driver.dll !
600 /* using an intermediate string to not have overlaping memcpy()'s */
601 if ((p
= strrchr(driver
->driverpath
,'\\')) != NULL
) {
602 fstrcpy(new_name
, p
+1);
603 fstrcpy(driver
->driverpath
, new_name
);
606 if ((p
= strrchr(driver
->datafile
,'\\')) != NULL
) {
607 fstrcpy(new_name
, p
+1);
608 fstrcpy(driver
->datafile
, new_name
);
611 if ((p
= strrchr(driver
->configfile
,'\\')) != NULL
) {
612 fstrcpy(new_name
, p
+1);
613 fstrcpy(driver
->configfile
, new_name
);
616 if ((p
= strrchr(driver
->helpfile
,'\\')) != NULL
) {
617 fstrcpy(new_name
, p
+1);
618 fstrcpy(driver
->helpfile
, new_name
);
621 if (driver
->dependentfiles
) {
622 for (i
=0; *driver
->dependentfiles
[i
]; i
++) {
623 if ((p
= strrchr(driver
->dependentfiles
[i
],'\\')) != NULL
) {
624 fstrcpy(new_name
, p
+1);
625 fstrcpy(driver
->dependentfiles
[i
], new_name
);
630 get_short_archi(architecture
, driver
->environment
);
632 /* jfm:7/16/2000 the client always sends the cversion=0.
633 * The server should check which version the driver is by reading
634 * the PE header of driver->driverpath.
636 * For Windows 95/98 the version is 0 (so the value sent is correct)
637 * For Windows NT (the architecture doesn't matter)
639 * NT 3.5/3.51: cversion=1
643 if ((driver
->version
= get_correct_cversion(architecture
,
644 driver
->driverpath
, user
, &err
)) == -1)
647 return NT_STATUS_NO_PROBLEMO
;
650 /****************************************************************************
651 ****************************************************************************/
652 uint32
clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract
,
653 uint32 level
, struct current_user
*user
)
658 NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
;
659 driver
=driver_abstract
.info_3
;
660 return clean_up_driver_struct_level_3(driver
, user
);
664 NT_PRINTER_DRIVER_INFO_LEVEL_6
*driver
;
665 driver
=driver_abstract
.info_6
;
666 return clean_up_driver_struct_level_6(driver
, user
);
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
){
696 static char ffmt_str
[17];
698 for (i
=0; i
<16; i
++) {
699 if ((c
[i
] < ' ') || (c
[i
] > '~'))
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
,
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
));
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",
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",
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",
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
) {
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.
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
;
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
));
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",
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
);
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
));
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",
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",
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));
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
));
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. */
852 /* Allocate a bit more space to speed up things */
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
));
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
) {
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",
885 byte_count
= bc
+ (byte_count
- i
);
886 if (byte_count
<VS_VERSION_INFO_SIZE
) break;
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));
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
));
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
)));
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
,
944 BOOL use_version
= True
;
949 time_t new_create_time
;
953 time_t old_create_time
;
957 files_struct
*fsp
= NULL
;
959 SMB_STRUCT_STAT stat_buf
;
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
);
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",
983 int ret
= get_file_version(fsp
, old_file
, &old_major
, &old_minor
);
984 if (ret
== -1) goto error_exit
;
987 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
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
);
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
);
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",
1014 int ret
= get_file_version(fsp
, new_file
, &new_major
, &new_minor
);
1015 if (ret
== -1) goto error_exit
;
1018 DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n",
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
);
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
));
1038 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
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
));
1049 DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file
));
1058 fsp
->conn
->vfs_ops
.close(fsp
, fsp
->fd
);
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
;
1075 connection_struct
*conn
;
1078 struct passwd
*pass
;
1085 memset(inbuf
, '\0', sizeof(inbuf
));
1086 memset(outbuf
, '\0', sizeof(outbuf
));
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
;
1094 DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level
));
1098 get_short_archi(architecture
, driver
->environment
);
1101 pass
= getpwuid(user
->uid
);
1103 DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
1104 (unsigned int)user
->uid
));
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... */
1116 conn
= make_connection("print$", user_name
, null_pw
, 0, "A:", user
->vuid
, &ecode
);
1119 DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
1120 *perr
= (uint32
)ecode
;
1125 * Save who we are - we are temporarily becoming the connection user.
1130 if (!become_user(conn
, conn
->vuid
)) {
1131 DEBUG(0,("move_driver_to_download_area: Can't become user %s\n", user_name
));
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
);
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
);
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
);
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
);
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
)) {
1243 for (j
=0; j
< i
; j
++) {
1244 if (strequal(driver
->dependentfiles
[i
], driver
->dependentfiles
[j
])) {
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
);
1261 unlink_internals(conn
, inbuf
, outbuf
, 0, new_name
);
1267 close_cnum(conn
, user
->vuid
);
1270 return ver
== -1 ? False
: True
;
1273 /****************************************************************************
1274 ****************************************************************************/
1275 static uint32
add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3
*driver
)
1278 fstring architecture
;
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
));
1324 len
+= tdb_pack(buf
+len
, buflen
-len
, "dffffffff",
1327 driver
->environment
,
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
);
1350 kbuf
.dsize
= strlen(key
)+1;
1354 ret
= tdb_store(tdb
, kbuf
, dbuf
, TDB_REPLACE
);
1357 DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key
));
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
;
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
;
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
));
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
;
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
);
1432 kbuf
.dsize
= strlen(key
)+1;
1434 dbuf
= tdb_fetch(tdb
, kbuf
);
1436 if (!dbuf
.dptr
) return get_a_printer_driver_3_default(info_ptr
, in_prt
, in_arch
);
1438 if (!dbuf
.dptr
) return 5;
1440 len
+= tdb_unpack(dbuf
.dptr
, dbuf
.dsize
, "dffffffff",
1449 driver
.defaultdatatype
);
1452 while (len
< dbuf
.dsize
) {
1453 driver
.dependentfiles
= (fstring
*)Realloc(driver
.dependentfiles
,
1454 sizeof(fstring
)*(i
+2));
1455 if (driver
.dependentfiles
== NULL
)
1458 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "f",
1459 &driver
.dependentfiles
[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
));
1479 /****************************************************************************
1480 ****************************************************************************/
1481 uint32
get_a_printer_driver_9x_compatible(pstring line
, fstring model
)
1483 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
1489 slprintf(key
, sizeof(key
), "%s%s/%d/%s", DRIVERS_PREFIX
, "WIN40", 0, model
);
1490 DEBUG(10,("driver key: [%s]\n", key
));
1493 kbuf
.dsize
= strlen(key
)+1;
1494 if (!tdb_exists(tdb
, kbuf
)) return False
;
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
);
1515 trim_string(info3
->datafile
, "\\print$\\WIN40\\0\\", 0);
1516 pstrcat(line
, info3
->datafile
);
1518 trim_string(info3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
1519 pstrcat(line
, info3
->helpfile
);
1521 trim_string(info3
->monitorname
, "\\print$\\WIN40\\0\\", 0);
1522 pstrcat(line
, info3
->monitorname
);
1524 pstrcat(line
, "RAW"); /*info3->defaultdatatype);*/
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
]);
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
)
1545 NT_PRINTER_DRIVER_INFO_LEVEL_3
*info3
;
1548 DEBUG(106,("Dumping printer driver at level [%d]\n", level
));
1554 if (driver
.info_3
== NULL
)
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
]));
1579 DEBUGADD(1,("Level not implemented\n"));
1587 /****************************************************************************
1588 ****************************************************************************/
1589 static int pack_devicemode(NT_DEVICEMODE
*nt_devmode
, char *buf
, int buflen
)
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
,
1604 nt_devmode
->driverextra
,
1605 nt_devmode
->orientation
,
1606 nt_devmode
->papersize
,
1607 nt_devmode
->paperlength
,
1608 nt_devmode
->paperwidth
,
1611 nt_devmode
->defaultsource
,
1612 nt_devmode
->printquality
,
1615 nt_devmode
->yresolution
,
1616 nt_devmode
->ttoption
,
1617 nt_devmode
->collate
,
1618 nt_devmode
->logpixels
,
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
));
1648 /****************************************************************************
1649 ****************************************************************************/
1650 static int pack_specifics(NT_PRINTER_PARAM
*param
, char *buf
, int buflen
)
1654 while (param
!= NULL
) {
1655 len
+= tdb_pack(buf
+len
, buflen
-len
, "pfdB",
1664 len
+= tdb_pack(buf
+len
, buflen
-len
, "p", param
);
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
)
1679 slprintf(key
, sizeof(key
), "%s%s",
1680 PRINTERS_PREFIX
, sharename
);
1683 kbuf
.dsize
=strlen(key
)+1;
1685 tdb_delete(tdb
, kbuf
);
1689 /****************************************************************************
1690 ****************************************************************************/
1691 static uint32
update_a_printer_2(NT_PRINTER_INFO_LEVEL_2
*info
)
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.
1728 len
+= tdb_pack(buf
+len
, buflen
-len
, "dddddddddddfffffPfffff",
1731 info
->default_priority
,
1748 info
->printprocessor
,
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
);
1762 slprintf(key
, sizeof(key
), "%s%s",
1763 PRINTERS_PREFIX
, info
->sharename
);
1766 kbuf
.dsize
= strlen(key
)+1;
1770 ret
= tdb_store(tdb
, kbuf
, dbuf
, TDB_REPLACE
);
1773 DEBUG(8, ("error updating printer to tdb on disk\n"));
1777 DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
1778 info
->sharename
, info
->drivername
, info
->portname
, len
));
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
;
1800 current
=info_2
->specific
;
1801 while (current
->next
!= NULL
) {
1802 current
=current
->next
;
1804 current
->next
=*param
;
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
;
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
);
1828 DEBUG(109,("deleted first value\n"));
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
);
1841 DEBUG(109,("deleted current value\n"));
1845 previous
=previous
->next
;
1846 current
=current
->next
;
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
;
1861 DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param
->value
));
1864 safe_free(param
->data
);
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
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"));
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
;
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"));
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"));
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
)
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
;
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
);
2011 /****************************************************************************
2012 ****************************************************************************/
2013 static int unpack_devicemode(NT_DEVICEMODE
**nt_devmode
, char *buf
, int buflen
)
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",
2029 &devmode
.specversion
,
2030 &devmode
.driverversion
,
2032 &devmode
.driverextra
,
2033 &devmode
.orientation
,
2035 &devmode
.paperlength
,
2036 &devmode
.paperwidth
,
2039 &devmode
.defaultsource
,
2040 &devmode
.printquality
,
2043 &devmode
.yresolution
,
2049 &devmode
.bitsperpel
,
2051 &devmode
.pelsheight
,
2052 &devmode
.displayflags
,
2053 &devmode
.displayfrequency
,
2057 &devmode
.dithertype
,
2060 &devmode
.panningwidth
,
2061 &devmode
.panningheight
,
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
));
2086 /****************************************************************************
2087 ****************************************************************************/
2088 static int unpack_specifics(NT_PRINTER_PARAM
**list
, char *buf
, int buflen
)
2091 NT_PRINTER_PARAM param
, *p
;
2096 len
+= tdb_unpack(buf
+len
, buflen
-len
, "p", &p
);
2099 len
+= tdb_unpack(buf
+len
, buflen
-len
, "fdB",
2105 *list
= memdup(¶m
, sizeof(param
));
2107 DEBUG(8,("specific: [%s], len: %d\n", param
.value
, param
.data_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
;
2121 NT_PRINTER_INFO_LEVEL_2 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 */
2151 info
.default_priority
= 1;
2152 info
.setuptime
= (uint32
)time(NULL
);
2154 if ((info
.devmode
= construct_nt_devicemode(info
.printername
)) == NULL
)
2157 if (!nt_printing_getsec(sharename
, &info
.secdesc_buf
))
2160 *info_ptr
= (NT_PRINTER_INFO_LEVEL_2
*)memdup(&info
, sizeof(info
));
2162 DEBUG(0,("get_a_printer_2_default: malloc fail.\n"));
2171 free_nt_devicemode(&info
.devmode
);
2172 if (info
.secdesc_buf
)
2173 free_sec_desc_buf(&info
.secdesc_buf
);
2177 /****************************************************************************
2178 ****************************************************************************/
2179 static uint32
get_a_printer_2(NT_PRINTER_INFO_LEVEL_2
**info_ptr
, fstring sharename
)
2182 NT_PRINTER_INFO_LEVEL_2 info
;
2184 TDB_DATA kbuf
, dbuf
;
2185 fstring printername
;
2189 slprintf(key
, sizeof(key
), "%s%s", PRINTERS_PREFIX
, sharename
);
2192 kbuf
.dsize
= strlen(key
)+1;
2194 dbuf
= tdb_fetch(tdb
, kbuf
);
2196 return get_a_printer_2_default(info_ptr
, sharename
);
2198 len
+= tdb_unpack(dbuf
.dptr
+len
, dbuf
.dsize
-len
, "dddddddddddfffffPfffff",
2201 &info
.default_priority
,
2218 info
.printprocessor
,
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
,
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
));
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
)
2252 NT_PRINTER_INFO_LEVEL_2
*info2
;
2254 DEBUG(106,("Dumping printer at level [%d]\n", level
));
2260 if (printer
.info_2
== NULL
)
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
));
2294 DEBUGADD(1,("Level not implemented\n"));
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)
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.
2328 /****************************************************************************
2329 Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
2330 ****************************************************************************/
2332 uint32
mod_a_printer(NT_PRINTER_INFO_LEVEL printer
, uint32 level
)
2336 dump_a_printer(printer
, level
);
2342 printer
.info_2
->c_setprinter
++;
2343 result
=update_a_printer_2(printer
.info_2
);
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
)
2363 dump_a_printer(printer
, level
);
2370 * Update the changestamp.
2371 * Note we must *not* do this in mod_a_printer().
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
);
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
)
2397 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2401 DEBUG(10,("get_a_printer: [%s] level %u\n", sharename
, (unsigned int)level
));
2407 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
2408 DEBUG(0,("get_a_printer: malloc fail.\n"));
2411 ZERO_STRUCTP(printer
);
2412 result
=get_a_printer_2(&printer
->info_2
, sharename
);
2414 dump_a_printer(*printer
, level
);
2415 *pp_printer
= printer
;
2426 DEBUG(10,("get_a_printer: [%s] level %u returning %u\n", sharename
, (unsigned int)level
, (unsigned int)result
));
2431 /****************************************************************************
2432 Deletes a NT_PRINTER_INFO_LEVEL struct.
2433 ****************************************************************************/
2435 uint32
free_a_printer(NT_PRINTER_INFO_LEVEL
**pp_printer
, uint32 level
)
2438 NT_PRINTER_INFO_LEVEL
*printer
= *pp_printer
;
2440 DEBUG(104,("freeing a printer at level [%d]\n", level
));
2442 if (printer
== NULL
)
2449 if (printer
->info_2
!= NULL
)
2451 free_nt_printer_info_level_2(&printer
->info_2
);
2470 /****************************************************************************
2471 ****************************************************************************/
2472 uint32
add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
2475 DEBUG(104,("adding a printer at level [%d]\n", level
));
2476 dump_a_printer_driver(driver
, level
);
2482 result
=add_a_printer_driver_3(driver
.info_3
);
2488 result
=add_a_printer_driver_6(driver
.info_6
);
2498 /****************************************************************************
2499 ****************************************************************************/
2500 uint32
get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL
*driver
, uint32 level
,
2501 fstring printername
, fstring architecture
, uint32 version
)
2509 result
=get_a_printer_driver_3(&driver
->info_3
, printername
, architecture
, version
);
2518 dump_a_printer_driver(*driver
, level
);
2522 /****************************************************************************
2523 ****************************************************************************/
2524 uint32
free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver
, uint32 level
)
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
);
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
);
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
;
2581 param
=printer
.info_2
->specific
;
2583 while (param
!= NULL
&& i
< param_index
) {
2591 /* exited because it exist */
2593 StrnCpy(value
, param
->value
, sizeof(fstring
)-1);
2594 *data
=(uint8
*)malloc(param
->data_len
*sizeof(uint8
));
2597 ZERO_STRUCTP(*data
);
2598 memcpy(*data
, param
->data
, param
->data_len
);
2599 *len
=param
->data_len
;
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
)
2620 if ( !strcmp(value
, param
->value
)
2622 && strlen(value
)==strlen(param
->value
))
2628 DEBUG(106, ("found one param\n"));
2631 /* exited because it exist */
2634 *data
=(uint8
*)malloc(param
->data_len
*sizeof(uint8
));
2637 memcpy(*data
, param
->data
, param
->data_len
);
2638 *len
=param
->data_len
;
2640 DEBUG(106, ("exit of get_specific_param:true\n"));
2643 DEBUG(106, ("exit of get_specific_param:false\n"));
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
;
2656 TALLOC_CTX
*mem_ctx
= NULL
;
2660 mem_ctx
= talloc_init();
2661 if (mem_ctx
== NULL
)
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
;
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
,
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
,
2722 status
= ERROR_INVALID_FUNCTION
;
2726 slprintf(key
, sizeof(key
), "SECDESC/%s", printername
);
2728 if (tdb_prs_store(tdb
, key
, &ps
)==0) {
2731 DEBUG(1,("Failed to store secdesc for %s\n", printername
));
2732 status
= ERROR_INVALID_FUNCTION
;
2735 /* Free mallocated memory */
2738 free_sec_desc_buf(&old_secdesc_ctr
);
2740 if (new_secdesc_ctr
!= secdesc_ctr
) {
2741 free_sec_desc_buf(&new_secdesc_ctr
);
2746 talloc_destroy(mem_ctx
);
2750 /****************************************************************************
2751 Construct a default security descriptor buffer for a printer.
2752 ****************************************************************************/
2754 static SEC_DESC_BUF
*construct_default_printer_sdb(void)
2758 SEC_ACL
*psa
= NULL
;
2759 SEC_DESC_BUF
*sdb
= NULL
;
2760 SEC_DESC
*psd
= NULL
;
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
);
2778 /* Backup plan - make printer owned by admins or root. This should
2779 emulate a lanman printer as security settings can't be
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
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
,
2809 NULL
, psa
, &sd_size
);
2814 DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
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
);
2827 /****************************************************************************
2828 Get a security desc for a printer.
2829 ****************************************************************************/
2831 BOOL
nt_printing_getsec(char *printername
, SEC_DESC_BUF
**secdesc_ctr
)
2834 TALLOC_CTX
*mem_ctx
= NULL
;
2837 mem_ctx
= talloc_init();
2838 if (mem_ctx
== NULL
)
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
);
2855 talloc_destroy(mem_ctx
);
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
)) {
2865 enum SID_NAME_USE name_type
;
2867 /* Change sd owner to workgroup administrator */
2869 if (winbind_lookup_name(lp_workgroup(), &owner_sid
,
2871 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
;
2872 SEC_DESC
*psd
= NULL
;
2877 sid_append_rid(&owner_sid
, DOMAIN_USER_RID_ADMIN
);
2879 psd
= make_sec_desc((*secdesc_ctr
)->sec
->revision
,
2881 (*secdesc_ctr
)->sec
->grp_sid
,
2882 (*secdesc_ctr
)->sec
->sacl
,
2883 (*secdesc_ctr
)->sec
->dacl
,
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
;
2897 nt_printing_setsec(printername
, *secdesc_ctr
);
2901 if (DEBUGLEVEL
>= 10) {
2902 SEC_ACL
*acl
= (*secdesc_ctr
)->sec
->dacl
;
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
++) {
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
));
2919 talloc_destroy(mem_ctx
);
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):
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
2972 JOB_ACCESS_ADMINISTER:
2973 print_job_delete, print_job_pause, print_job_resume,
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;
2983 extern struct current_user current_user
;
2985 /* If user is NULL then use the current_user structure */
2987 if (!user
) user
= ¤t_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
))) {
2996 /* Get printer name */
2998 pname
= PRINTERNAME(snum
);
3000 if (!pname
|| !*pname
)
3001 pname
= SERVICE(snum
);
3003 if (!pname
|| !*pname
) {
3008 /* Get printer security descriptor */
3010 nt_printing_getsec(pname
, &secdesc
);
3012 /* Check against NT4 ACE mask values. From observation these
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
;
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
3035 required_access
= PRINTER_ACE_FULL_CONTROL
;
3037 case JOB_ACCESS_ADMINISTER
:
3038 required_access
= PRINTER_ACE_MANAGE_DOCUMENTS
;
3041 DEBUG(0, ("invalid value passed to print_access_check()\n"));
3046 if ((result
= se_access_check(secdesc
->sec
, user
, required_access
,
3047 &access_granted
, &status
))) {
3051 /* Check against NT5 ACE mask values. From observation these
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
3064 switch (access_type
) {
3065 case PRINTER_ACCESS_USE
:
3066 required_access
= PRINTER_ACE_NT5_PRINT
;
3068 case PRINTER_ACCESS_ADMINISTER
:
3069 required_access
= PRINTER_ACE_NT5_FULL_CONTROL
;
3071 case JOB_ACCESS_ADMINISTER
:
3072 required_access
= PRINTER_ACE_NT5_MANAGE_DOCUMENTS
;
3076 result
= se_access_check(secdesc
->sec
, user
, required_access
,
3077 &access_granted
, &status
);
3082 DEBUG(4, ("access check was %s\n", result
? "SUCCESS" : "FAILURE"));
3084 /* Free mallocated memory */
3086 free_sec_desc_buf(&secdesc
);
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
;
3102 time_t now
= time(NULL
);
3106 if (get_a_printer(&printer
, 2, lp_servicename(snum
))!=0)
3109 if (printer
->info_2
->starttime
== 0 && printer
->info_2
->untiltime
== 0)
3113 mins
= (uint32
)t
->tm_hour
*60 + (uint32
)t
->tm_min
;
3115 if (mins
>= printer
->info_2
->starttime
&& mins
<= printer
->info_2
->untiltime
)
3118 free_a_printer(&printer
, 2);