2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
32 #define DBGC_CLASS DBGC_RPC_SRV
34 #ifndef MAX_OPEN_PRINTER_EXS
35 #define MAX_OPEN_PRINTER_EXS 50
38 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
39 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 /* Table to map the driver version */
44 static const char * drv_ver_to_os
[] = {
45 "WIN9X", /* driver version/cversion 0 */
47 "WINNT", /* driver version/cversion 2 */
48 "WIN2K", /* driver version/cversion 3 */
51 static const char *get_drv_ver_to_os(int ver
)
53 if (ver
< 0 || ver
> 3)
55 return drv_ver_to_os
[ver
];
59 const char *long_archi
;
60 const char *short_archi
;
64 static Printer_entry
*printers_list
;
66 typedef struct _counter_printer_0
{
67 struct _counter_printer_0
*next
;
68 struct _counter_printer_0
*prev
;
74 static counter_printer_0
*counter_list
;
76 static struct cli_state notify_cli
; /* print notify back-channel */
77 static uint32 smb_connections
=0;
80 /* in printing/nt_printing.c */
82 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
84 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
85 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
87 /* translate between internal status numbers and NT status numbers */
88 static int nt_printj_status(int v
)
94 return JOB_STATUS_PAUSED
;
96 return JOB_STATUS_SPOOLING
;
98 return JOB_STATUS_PRINTING
;
100 return JOB_STATUS_ERROR
;
102 return JOB_STATUS_DELETING
;
104 return JOB_STATUS_OFFLINE
;
106 return JOB_STATUS_PAPEROUT
;
108 return JOB_STATUS_PRINTED
;
110 return JOB_STATUS_DELETED
;
112 return JOB_STATUS_BLOCKED
;
113 case LPQ_USER_INTERVENTION
:
114 return JOB_STATUS_USER_INTERVENTION
;
119 static int nt_printq_status(int v
)
123 return PRINTER_STATUS_PAUSED
;
132 /****************************************************************************
133 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
134 ****************************************************************************/
136 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
141 SAFE_FREE((*pp
)->ctr
.type
);
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum
))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections
==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
167 result
= cli_spoolss_reply_close_printer(¬ify_cli
, notify_cli
.mem_ctx
, handle
);
169 if (!W_ERROR_IS_OK(result
))
170 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171 dos_errstr(result
)));
173 /* if it's the last connection, deconnect the IPC$ share */
174 if (smb_connections
==1) {
175 cli_nt_session_close(¬ify_cli
);
176 cli_ulogoff(¬ify_cli
);
177 cli_shutdown(¬ify_cli
);
178 message_deregister(MSG_PRINTER_NOTIFY2
);
180 /* Tell the connections db we're no longer interested in
181 * printer notify messages. */
183 register_message_flags( False
, FLAG_MSG_PRINT_NOTIFY
);
189 /****************************************************************************
190 Functions to free a printer entry datastruct.
191 ****************************************************************************/
193 static void free_printer_entry(void *ptr
)
195 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
197 if (Printer
->notify
.client_connected
==True
) {
200 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
202 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
203 } else if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) {
204 snum
= print_queue_snum(Printer
->sharename
);
206 srv_spoolss_replycloseprinter(snum
,
207 &Printer
->notify
.client_hnd
);
211 Printer
->notify
.flags
=0;
212 Printer
->notify
.options
=0;
213 Printer
->notify
.localmachine
[0]='\0';
214 Printer
->notify
.printerlocal
=0;
215 free_spool_notify_option(&Printer
->notify
.option
);
216 Printer
->notify
.option
=NULL
;
217 Printer
->notify
.client_connected
=False
;
219 free_nt_devicemode( &Printer
->nt_devmode
);
220 free_a_printer( &Printer
->printer_info
, 2 );
222 talloc_destroy( Printer
->ctx
);
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list
, Printer
);
230 /****************************************************************************
231 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
232 ****************************************************************************/
234 static SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
236 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
241 new_sp
= (SPOOL_NOTIFY_OPTION
*)malloc(sizeof(SPOOL_NOTIFY_OPTION
));
248 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
250 if (!new_sp
->ctr
.type
) {
259 /****************************************************************************
260 find printer index by handle
261 ****************************************************************************/
263 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
265 Printer_entry
*find_printer
= NULL
;
267 if(!find_policy_by_hnd(p
,hnd
,(void **)&find_printer
)) {
268 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
275 /****************************************************************************
276 look for a printer object cached on an open printer handle
277 ****************************************************************************/
279 WERROR
find_printer_in_print_hnd_cache( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL_2
**info2
,
280 const char *servername
, const char *printername
)
284 DEBUG(10,("find_printer_in_print_hnd_cache: printer [\\\\%s\\%s]\n",
285 servername
, printername
));
287 for ( p
=printers_list
; p
; p
=p
->next
)
289 if ( p
->printer_type
==PRINTER_HANDLE_IS_PRINTER
291 && strequal( p
->sharename
, printername
)
292 && strequal( p
->servername
, servername
) )
294 DEBUG(10,("Found printer\n"));
295 *info2
= dup_printer_2( ctx
, p
->printer_info
->info_2
);
301 return WERR_INVALID_PRINTER_NAME
;
304 /****************************************************************************
305 destroy any cached printer_info_2 structures on open handles
306 ****************************************************************************/
308 void invalidate_printer_hnd_cache( char *printername
)
312 DEBUG(10,("invalidate_printer_hnd_cache: printer [%s]\n", printername
));
314 for ( p
=printers_list
; p
; p
=p
->next
)
316 if ( p
->printer_type
==PRINTER_HANDLE_IS_PRINTER
318 && StrCaseCmp(p
->sharename
, printername
)==0)
320 DEBUG(10,("invalidating printer_info cache for handl:\n"));
321 free_a_printer( &p
->printer_info
, 2 );
322 p
->printer_info
= NULL
;
328 /****************************************************************************
329 Close printer index by handle.
330 ****************************************************************************/
332 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
334 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
337 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
341 close_policy_hnd(p
, hnd
);
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
352 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
366 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED
;
372 /* Check calling user has permission to delete printer. Note that
373 since we set the snum parameter to -1 only administrators can
374 delete the printer. This stops people with the Full Control
375 permission from deleting the printer. */
377 if (!print_access_check(NULL
, -1, PRINTER_ACCESS_ADMINISTER
)) {
378 DEBUG(3, ("printer delete denied by security descriptor\n"));
379 return WERR_ACCESS_DENIED
;
383 if (del_a_printer( Printer
->sharename
) != 0) {
384 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
388 if (*lp_deleteprinter_cmd()) {
390 char *cmd
= lp_deleteprinter_cmd();
394 pstr_sprintf(command
, "%s \"%s\"", cmd
, Printer
->sharename
);
396 DEBUG(10,("Running [%s]\n", command
));
397 ret
= smbrun(command
, NULL
);
399 return WERR_BADFID
; /* What to return here? */
401 DEBUGADD(10,("returned [%d]\n", ret
));
403 /* Send SIGHUP to process group... is there a better way? */
406 /* go ahead and re-read the services immediately */
407 reload_services( False
);
409 if ( lp_servicenumber( Printer
->sharename
) < 0 )
410 return WERR_ACCESS_DENIED
;
416 /****************************************************************************
417 Return the snum of a printer corresponding to an handle.
418 ****************************************************************************/
420 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
422 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
425 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
429 switch (Printer
->printer_type
) {
430 case PRINTER_HANDLE_IS_PRINTER
:
431 DEBUG(4,("short name:%s\n", Printer
->sharename
));
432 *number
= print_queue_snum(Printer
->sharename
);
433 return (*number
!= -1);
434 case PRINTER_HANDLE_IS_PRINTSERVER
:
441 /****************************************************************************
442 Set printer handle type.
443 Check if it's \\server or \\server\printer
444 ****************************************************************************/
446 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
448 DEBUG(3,("Setting printer type=%s\n", handlename
));
450 if ( strlen(handlename
) < 3 ) {
451 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
455 /* it's a print server */
456 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
457 DEBUGADD(4,("Printer is a print server\n"));
458 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTSERVER
;
462 DEBUGADD(4,("Printer is a printer\n"));
463 Printer
->printer_type
= PRINTER_HANDLE_IS_PRINTER
;
469 /****************************************************************************
470 Set printer handle name.
471 ****************************************************************************/
473 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
476 int n_services
=lp_numservices();
477 char *aprinter
, *printername
;
478 const char *servername
;
481 NT_PRINTER_INFO_LEVEL
*printer
;
484 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
, (unsigned long)strlen(handlename
)));
486 aprinter
= handlename
;
487 if ( *handlename
== '\\' ) {
488 servername
= handlename
+ 2;
489 if ( (aprinter
= strchr_m( handlename
+2, '\\' )) != NULL
) {
498 /* save the servername to fill in replies on this handle */
500 if ( !is_myname_or_ipaddr( servername
) )
503 fstrcpy( Printer
->servername
, servername
);
505 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
508 if ( Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTER
)
511 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
513 /* Search all sharenames first as this is easier than pulling
514 the printer_info_2 off of disk */
516 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
518 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
521 /* ------ sharename ------ */
523 fstrcpy(sname
, lp_servicename(snum
));
525 DEBUGADD(10, ("share: %s\n",sname
));
527 if ( strequal(sname
, aprinter
) ) {
532 /* do another loop to look for printernames */
534 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
536 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
) ) )
539 fstrcpy(sname
, lp_servicename(snum
));
542 result
= get_a_printer( NULL
, &printer
, 2, sname
);
543 if ( !W_ERROR_IS_OK(result
) ) {
544 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
545 sname
, dos_errstr(result
)));
549 /* printername is always returned as \\server\printername */
550 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
551 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
552 printer
->info_2
->printername
));
553 free_a_printer( &printer
, 2);
559 if ( strequal(printername
, aprinter
) ) {
563 DEBUGADD(10, ("printername: %s\n", printername
));
565 free_a_printer( &printer
, 2);
569 DEBUGADD(4,("Printer not found\n"));
573 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
575 fstrcpy(Printer
->sharename
, sname
);
580 /****************************************************************************
581 Find first available printer slot. creates a printer handle for you.
582 ****************************************************************************/
584 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
586 Printer_entry
*new_printer
;
588 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
590 if((new_printer
=(Printer_entry
*)malloc(sizeof(Printer_entry
))) == NULL
)
593 ZERO_STRUCTP(new_printer
);
595 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
596 SAFE_FREE(new_printer
);
600 /* Add to the internal list. */
601 DLIST_ADD(printers_list
, new_printer
);
603 new_printer
->notify
.option
=NULL
;
605 if ( !(new_printer
->ctx
= talloc_init("Printer Entry [%p]", hnd
)) ) {
606 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
607 close_printer_handle(p
, hnd
);
611 if (!set_printer_hnd_printertype(new_printer
, name
)) {
612 close_printer_handle(p
, hnd
);
616 if (!set_printer_hnd_name(new_printer
, name
)) {
617 close_printer_handle(p
, hnd
);
621 new_printer
->access_granted
= access_granted
;
623 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
628 /****************************************************************************
629 Allocate more memory for a BUFFER.
630 ****************************************************************************/
632 static BOOL
alloc_buffer_size(NEW_BUFFER
*buffer
, uint32 buffer_size
)
640 /* damn, I'm doing the reverse operation of prs_grow() :) */
641 if (buffer_size
< prs_data_size(ps
))
644 extra_space
= buffer_size
- prs_data_size(ps
);
647 * save the offset and move to the end of the buffer
648 * prs_grow() checks the extra_space against the offset
650 old_offset
=prs_offset(ps
);
651 prs_set_offset(ps
, prs_data_size(ps
));
653 if (!prs_grow(ps
, extra_space
))
656 prs_set_offset(ps
, old_offset
);
658 buffer
->string_at_end
=prs_data_size(ps
);
663 /***************************************************************************
664 check to see if the client motify handle is monitoring the notification
665 given by (notify_type, notify_field).
666 **************************************************************************/
668 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
674 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
677 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
681 * Flags should always be zero when the change notify
682 * is registered by the client's spooler. A user Win32 app
683 * might use the flags though instead of the NOTIFY_OPTION_INFO
692 return is_monitoring_event_flags(
693 p
->notify
.flags
, notify_type
, notify_field
);
695 for (i
= 0; i
< option
->count
; i
++) {
697 /* Check match for notify_type */
699 if (option
->ctr
.type
[i
].type
!= notify_type
)
702 /* Check match for field */
704 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
705 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
711 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
712 p
->servername
, p
->sharename
, notify_type
, notify_field
));
717 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
719 static void notify_one_value(struct spoolss_notify_msg
*msg
,
720 SPOOL_NOTIFY_INFO_DATA
*data
,
723 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
724 data
->notify_data
.value
[1] = 0;
727 static void notify_string(struct spoolss_notify_msg
*msg
,
728 SPOOL_NOTIFY_INFO_DATA
*data
,
733 /* The length of the message includes the trailing \0 */
735 init_unistr2(&unistr
, msg
->notify
.data
, UNI_STR_TERMINATE
);
737 data
->notify_data
.data
.length
= msg
->len
* 2;
738 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, msg
->len
* 2);
740 if (!data
->notify_data
.data
.string
) {
741 data
->notify_data
.data
.length
= 0;
745 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
748 static void notify_system_time(struct spoolss_notify_msg
*msg
,
749 SPOOL_NOTIFY_INFO_DATA
*data
,
755 if (msg
->len
!= sizeof(time_t)) {
756 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
761 if (!prs_init(&ps
, MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
762 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
766 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
767 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
771 if (!spoolss_io_system_time("", &ps
, 0, &systime
))
774 data
->notify_data
.data
.length
= prs_offset(&ps
);
775 data
->notify_data
.data
.string
= talloc(mem_ctx
, prs_offset(&ps
));
777 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
782 struct notify2_message_table
{
784 void (*fn
)(struct spoolss_notify_msg
*msg
,
785 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
788 static struct notify2_message_table printer_notify_table
[] = {
789 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
790 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
791 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
792 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
793 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
794 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
795 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
796 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
797 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
798 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
799 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
800 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
801 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
802 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
803 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
804 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
805 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
806 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
807 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
810 static struct notify2_message_table job_notify_table
[] = {
811 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
812 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
813 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
814 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
815 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
816 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
817 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
818 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
819 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
820 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
821 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
822 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
823 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
824 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
825 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
826 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
827 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
828 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
829 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
830 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
831 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
832 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
833 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
834 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
838 /***********************************************************************
839 Allocate talloc context for container object
840 **********************************************************************/
842 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
847 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
852 /***********************************************************************
853 release all allocated memory and zero out structure
854 **********************************************************************/
856 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
862 talloc_destroy(ctr
->ctx
);
869 /***********************************************************************
870 **********************************************************************/
872 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
880 /***********************************************************************
881 **********************************************************************/
883 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
885 if ( !ctr
|| !ctr
->msg_groups
)
888 if ( idx
>= ctr
->num_groups
)
891 return &ctr
->msg_groups
[idx
];
895 /***********************************************************************
896 How many groups of change messages do we have ?
897 **********************************************************************/
899 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
904 return ctr
->num_groups
;
907 /***********************************************************************
908 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
909 **********************************************************************/
911 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
913 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
914 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
915 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
921 /* loop over all groups looking for a matching printer name */
923 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
924 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
928 /* add a new group? */
930 if ( i
== ctr
->num_groups
) {
933 if ( !(groups
= talloc_realloc( ctr
->ctx
, ctr
->msg_groups
, sizeof(SPOOLSS_NOTIFY_MSG_GROUP
)*ctr
->num_groups
)) ) {
934 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
937 ctr
->msg_groups
= groups
;
939 /* clear the new entry and set the printer name */
941 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
942 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
945 /* add the change messages; 'i' is the correct index now regardless */
947 msg_grp
= &ctr
->msg_groups
[i
];
951 if ( !(msg_list
= talloc_realloc( ctr
->ctx
, msg_grp
->msgs
, sizeof(SPOOLSS_NOTIFY_MSG
)*msg_grp
->num_msgs
)) ) {
952 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
955 msg_grp
->msgs
= msg_list
;
957 new_slot
= msg_grp
->num_msgs
-1;
958 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
960 /* need to allocate own copy of data */
963 msg_grp
->msgs
[new_slot
].notify
.data
= talloc_memdup( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
965 return ctr
->num_groups
;
968 /***********************************************************************
969 Send a change notication message on all handles which have a call
971 **********************************************************************/
973 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
976 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
977 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
978 SPOOLSS_NOTIFY_MSG
*messages
;
979 int sending_msg_count
;
982 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
986 messages
= msg_group
->msgs
;
989 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
993 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
995 /* loop over all printers */
997 for (p
= printers_list
; p
; p
= p
->next
) {
998 SPOOL_NOTIFY_INFO_DATA
*data
;
1003 /* Is there notification on this handle? */
1005 if ( !p
->notify
.client_connected
)
1008 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
1010 /* For this printer? Print servers always receive
1013 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
1014 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
1017 DEBUG(10,("Our printer\n"));
1019 /* allocate the max entries possible */
1021 data
= talloc( mem_ctx
, msg_group
->num_msgs
*sizeof(SPOOL_NOTIFY_INFO_DATA
) );
1024 /* build the array of change notifications */
1026 sending_msg_count
= 0;
1028 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
1029 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
1031 /* Are we monitoring this event? */
1033 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1036 sending_msg_count
++;
1039 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1040 msg
->type
, msg
->field
, p
->sharename
));
1043 * if the is a printer notification handle and not a job notification
1044 * type, then set the id to 0. Other wise just use what was specified
1047 * When registering change notification on a print server handle
1048 * we always need to send back the id (snum) matching the printer
1049 * for which the change took place. For change notify registered
1050 * on a printer handle, this does not matter and the id should be 0.
1055 if ( ( p
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1061 /* Convert unix jobid to smb jobid */
1063 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1064 id
= sysjob_to_jobid(msg
->id
);
1067 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1072 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1075 case PRINTER_NOTIFY_TYPE
:
1076 if ( printer_notify_table
[msg
->field
].fn
)
1077 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1080 case JOB_NOTIFY_TYPE
:
1081 if ( job_notify_table
[msg
->field
].fn
)
1082 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1086 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1093 if ( sending_msg_count
) {
1094 cli_spoolss_rrpcn( ¬ify_cli
, mem_ctx
, &p
->notify
.client_hnd
,
1095 data_len
, data
, p
->notify
.change
, 0 );
1100 DEBUG(8,("send_notify2_changes: Exit...\n"));
1104 /***********************************************************************
1105 **********************************************************************/
1107 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1110 uint32 tv_sec
, tv_usec
;
1113 /* Unpack message */
1115 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1118 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddddd",
1120 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1123 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1124 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1126 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1127 &msg
->len
, &msg
->notify
.data
);
1129 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1130 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1132 tv
->tv_sec
= tv_sec
;
1133 tv
->tv_usec
= tv_usec
;
1136 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1137 msg
->notify
.value
[1]));
1139 dump_data(3, msg
->notify
.data
, msg
->len
);
1144 /********************************************************************
1145 Receive a notify2 message list
1146 ********************************************************************/
1148 static void receive_notify2_message_list(int msg_type
, pid_t src
, void *msg
, size_t len
)
1150 size_t msg_count
, i
;
1151 char *buf
= (char *)msg
;
1154 SPOOLSS_NOTIFY_MSG notify
;
1155 SPOOLSS_NOTIFY_MSG_CTR messages
;
1159 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1163 msg_count
= IVAL(buf
, 0);
1166 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1168 if (msg_count
== 0) {
1169 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1173 /* initialize the container */
1175 ZERO_STRUCT( messages
);
1176 notify_msg_ctr_init( &messages
);
1179 * build message groups for each printer identified
1180 * in a change_notify msg. Remember that a PCN message
1181 * includes the handle returned for the srv_spoolss_replyopenprinter()
1182 * call. Therefore messages are grouped according to printer handle.
1185 for ( i
=0; i
<msg_count
; i
++ ) {
1186 struct timeval msg_tv
;
1188 if (msg_ptr
+ 4 - buf
> len
) {
1189 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1193 msg_len
= IVAL(msg_ptr
,0);
1196 if (msg_ptr
+ msg_len
- buf
> len
) {
1197 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1201 /* unpack messages */
1203 ZERO_STRUCT( notify
);
1204 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1207 /* add to correct list in container */
1209 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1211 /* free memory that might have been allocated by notify2_unpack_msg() */
1213 if ( notify
.len
!= 0 )
1214 SAFE_FREE( notify
.notify
.data
);
1217 /* process each group of messages */
1219 num_groups
= notify_msg_ctr_numgroups( &messages
);
1220 for ( i
=0; i
<num_groups
; i
++ )
1221 send_notify2_changes( &messages
, i
);
1226 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1228 notify_msg_ctr_destroy( &messages
);
1233 /********************************************************************
1234 callback to MSG_PRINTER_CHANGED. When a printer is changed by
1235 one smbd, all of processes must clear their printer cache immediately.
1236 ********************************************************************/
1238 void receive_printer_mod_msg(int msg_type
, pid_t src
, void *buf
, size_t len
)
1240 fstring printername
;
1242 fstrcpy( printername
, buf
);
1244 DEBUG(10,("receive_printer_mod_msg: Printer change [%s]\n", printername
));
1246 invalidate_printer_hnd_cache( printername
);
1249 /********************************************************************
1250 Send a message to ourself about new driver being installed
1251 so we can upgrade the information for each printer bound to this
1253 ********************************************************************/
1255 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1257 int len
= strlen(drivername
);
1262 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1265 message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1270 /**********************************************************************
1271 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1272 over all printers, upgrading ones as necessary
1273 **********************************************************************/
1275 void do_drv_upgrade_printer(int msg_type
, pid_t src
, void *buf
, size_t len
)
1279 int n_services
= lp_numservices();
1281 len
= MIN(len
,sizeof(drivername
)-1);
1282 strncpy(drivername
, buf
, len
);
1284 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1286 /* Iterate the printer list */
1288 for (snum
=0; snum
<n_services
; snum
++)
1290 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1293 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1295 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1296 if (!W_ERROR_IS_OK(result
))
1299 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1301 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1303 /* all we care about currently is the change_id */
1305 result
= mod_a_printer(printer
, 2);
1306 if (!W_ERROR_IS_OK(result
)) {
1307 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1308 dos_errstr(result
)));
1312 free_a_printer(&printer
, 2);
1319 /********************************************************************
1320 Update the cache for all printq's with a registered client
1322 ********************************************************************/
1324 void update_monitored_printq_cache( void )
1326 Printer_entry
*printer
= printers_list
;
1329 /* loop through all printers and update the cache where
1330 client_connected == True */
1333 if ( (printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
1334 && printer
->notify
.client_connected
)
1336 snum
= print_queue_snum(printer
->sharename
);
1337 print_queue_status( snum
, NULL
, NULL
);
1340 printer
= printer
->next
;
1345 /********************************************************************
1346 Send a message to ourself about new driver being installed
1347 so we can upgrade the information for each printer bound to this
1349 ********************************************************************/
1351 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1353 int len
= strlen(drivername
);
1358 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1361 message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1366 /**********************************************************************
1367 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1368 over all printers, resetting printer data as neessary
1369 **********************************************************************/
1371 void reset_all_printerdata(int msg_type
, pid_t src
, void *buf
, size_t len
)
1375 int n_services
= lp_numservices();
1377 len
= MIN( len
, sizeof(drivername
)-1 );
1378 strncpy( drivername
, buf
, len
);
1380 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1382 /* Iterate the printer list */
1384 for ( snum
=0; snum
<n_services
; snum
++ )
1386 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1389 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1391 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1392 if ( !W_ERROR_IS_OK(result
) )
1396 * if the printer is bound to the driver,
1397 * then reset to the new driver initdata
1400 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1402 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1404 if ( !set_driver_init(printer
, 2) ) {
1405 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1406 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1409 result
= mod_a_printer( printer
, 2 );
1410 if ( !W_ERROR_IS_OK(result
) ) {
1411 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1412 get_dos_error_msg(result
)));
1416 free_a_printer( &printer
, 2 );
1425 /********************************************************************
1426 Copy routines used by convert_to_openprinterex()
1427 *******************************************************************/
1429 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1437 DEBUG (8,("dup_devmode\n"));
1439 /* bulk copy first */
1441 d
= talloc_memdup(ctx
, devmode
, sizeof(DEVICEMODE
));
1445 /* dup the pointer members separately */
1447 len
= unistrlen(devmode
->devicename
.buffer
);
1449 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1450 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1455 len
= unistrlen(devmode
->formname
.buffer
);
1457 d
->devicename
.buffer
= talloc(ctx
, len
*2);
1458 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1462 d
->private = talloc_memdup(ctx
, devmode
->private, devmode
->driverextra
);
1467 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1469 if (!new_ctr
|| !ctr
)
1472 DEBUG(8,("copy_devmode_ctr\n"));
1474 new_ctr
->size
= ctr
->size
;
1475 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1477 if(ctr
->devmode_ptr
)
1478 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1481 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1483 if (!new_def
|| !def
)
1486 DEBUG(8,("copy_printer_defaults\n"));
1488 new_def
->datatype_ptr
= def
->datatype_ptr
;
1490 if (def
->datatype_ptr
)
1491 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1493 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1495 new_def
->access_required
= def
->access_required
;
1498 /********************************************************************
1499 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1500 * SPOOL_Q_OPEN_PRINTER_EX structure
1501 ********************************************************************/
1503 static void convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1505 if (!q_u_ex
|| !q_u
)
1508 DEBUG(8,("convert_to_openprinterex\n"));
1510 q_u_ex
->printername_ptr
= q_u
->printername_ptr
;
1512 if (q_u
->printername_ptr
)
1513 copy_unistr2(&q_u_ex
->printername
, &q_u
->printername
);
1515 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1518 /********************************************************************
1519 * spoolss_open_printer
1521 * called from the spoolss dispatcher
1522 ********************************************************************/
1524 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1526 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1527 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1532 ZERO_STRUCT(q_u_ex
);
1533 ZERO_STRUCT(r_u_ex
);
1535 /* convert the OpenPrinter() call to OpenPrinterEx() */
1537 convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1539 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1541 /* convert back to OpenPrinter() */
1543 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1548 /********************************************************************
1549 * spoolss_open_printer
1551 * If the openprinterex rpc call contains a devmode,
1552 * it's a per-user one. This per-user devmode is derivated
1553 * from the global devmode. Openprinterex() contains a per-user
1554 * devmode for when you do EMF printing and spooling.
1555 * In the EMF case, the NT workstation is only doing half the job
1556 * of rendering the page. The other half is done by running the printer
1557 * driver on the server.
1558 * The EMF file doesn't contain the page description (paper size, orientation, ...).
1559 * The EMF file only contains what is to be printed on the page.
1560 * So in order for the server to know how to print, the NT client sends
1561 * a devicemode attached to the openprinterex call.
1562 * But this devicemode is short lived, it's only valid for the current print job.
1564 * If Samba would have supported EMF spooling, this devicemode would
1565 * have been attached to the handle, to sent it to the driver to correctly
1566 * rasterize the EMF file.
1568 * As Samba only supports RAW spooling, we only receive a ready-to-print file,
1569 * we just act as a pass-thru between windows and the printer.
1571 * In order to know that Samba supports only RAW spooling, NT has to call
1572 * getprinter() at level 2 (attribute field) or NT has to call startdoc()
1573 * and until NT sends a RAW job, we refuse it.
1575 * But to call getprinter() or startdoc(), you first need a valid handle,
1576 * and to get an handle you have to call openprintex(). Hence why you have
1577 * a devicemode in the openprinterex() call.
1580 * Differences between NT4 and NT 2000.
1583 * On NT4, you only have a global devicemode. This global devicemode can be changed
1584 * by the administrator (or by a user with enough privs). Everytime a user
1585 * wants to print, the devicemode is resetted to the default. In Word, everytime
1586 * you print, the printer's characteristics are always reset to the global devicemode.
1590 * In W2K, there is the notion of per-user devicemode. The first time you use
1591 * a printer, a per-user devicemode is build from the global devicemode.
1592 * If you change your per-user devicemode, it is saved in the registry, under the
1593 * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
1594 * printer preferences available.
1596 * To change the per-user devicemode: it's the "Printing Preferences ..." button
1597 * on the General Tab of the printer properties windows.
1599 * To change the global devicemode: it's the "Printing Defaults..." button
1600 * on the Advanced Tab of the printer properties window.
1603 ********************************************************************/
1605 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1607 UNISTR2
*printername
= NULL
;
1608 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1609 POLICY_HND
*handle
= &r_u
->handle
;
1613 struct current_user user
;
1614 Printer_entry
*Printer
=NULL
;
1616 if (q_u
->printername_ptr
!= 0)
1617 printername
= &q_u
->printername
;
1619 if (printername
== NULL
)
1620 return WERR_INVALID_PRINTER_NAME
;
1622 /* some sanity check because you can open a printer or a print server */
1623 /* aka: \\server\printer or \\server */
1624 unistr2_to_ascii(name
, printername
, sizeof(name
)-1);
1626 DEBUGADD(3,("checking name: %s\n",name
));
1628 if (!open_printer_hnd(p
, handle
, name
, 0))
1629 return WERR_INVALID_PRINTER_NAME
;
1631 Printer
=find_printer_index_by_hnd(p
, handle
);
1633 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1634 "handle we created for printer %s\n", name
));
1635 close_printer_handle(p
,handle
);
1636 return WERR_INVALID_PRINTER_NAME
;
1639 get_current_user(&user
, p
);
1642 * First case: the user is opening the print server:
1644 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1645 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1647 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1648 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1649 * or if the user is listed in the smb.conf printer admin parameter.
1651 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1652 * client view printer folder, but does not show the MSAPW.
1654 * Note: this test needs code to check access rights here too. Jeremy
1655 * could you look at this?
1657 * Second case: the user is opening a printer:
1658 * NT doesn't let us connect to a printer if the connecting user
1659 * doesn't have print permission.
1662 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
1664 /* Printserver handles use global struct... */
1668 /* Map standard access rights to object specific access rights */
1670 se_map_standard(&printer_default
->access_required
,
1671 &printserver_std_mapping
);
1673 /* Deny any object specific bits that don't apply to print
1674 servers (i.e printer and job specific bits) */
1676 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1678 if (printer_default
->access_required
&
1679 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1680 DEBUG(3, ("access DENIED for non-printserver bits"));
1681 close_printer_handle(p
, handle
);
1682 return WERR_ACCESS_DENIED
;
1685 /* Allow admin access */
1687 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1689 if (!lp_ms_add_printer_wizard()) {
1690 close_printer_handle(p
, handle
);
1691 return WERR_ACCESS_DENIED
;
1694 /* if the user is not root and not a printer admin, then fail */
1697 && !user_in_list(uidtoname(user
.uid
), lp_printer_admin(snum
), user
.groups
, user
.ngroups
) )
1699 close_printer_handle(p
, handle
);
1700 return WERR_ACCESS_DENIED
;
1703 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1707 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1710 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1711 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1713 /* We fall through to return WERR_OK */
1718 /* NT doesn't let us connect to a printer if the connecting user
1719 doesn't have print permission. */
1721 if (!get_printer_snum(p
, handle
, &snum
)) {
1722 close_printer_handle(p
, handle
);
1726 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1728 /* map an empty access mask to the minimum access mask */
1729 if (printer_default
->access_required
== 0x0)
1730 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1733 * If we are not serving the printer driver for this printer,
1734 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1735 * will keep NT clients happy --jerry
1738 if (lp_use_client_driver(snum
)
1739 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1741 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1744 /* check smb.conf parameters and the the sec_desc */
1746 if (!user_ok(uidtoname(user
.uid
), snum
, user
.groups
, user
.ngroups
) || !print_access_check(&user
, snum
, printer_default
->access_required
)) {
1747 DEBUG(3, ("access DENIED for printer open\n"));
1748 close_printer_handle(p
, handle
);
1749 return WERR_ACCESS_DENIED
;
1752 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1753 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1754 close_printer_handle(p
, handle
);
1755 return WERR_ACCESS_DENIED
;
1758 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1759 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1761 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1763 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1764 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1768 Printer
->access_granted
= printer_default
->access_required
;
1771 * If the client sent a devmode in the OpenPrinter() call, then
1772 * save it here in case we get a job submission on this handle
1775 if ( (Printer
->printer_type
!= PRINTER_HANDLE_IS_PRINTSERVER
)
1776 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1778 convert_devicemode( Printer
->sharename
, q_u
->printer_default
.devmode_cont
.devmode
,
1779 &Printer
->nt_devmode
);
1782 #if 0 /* JERRY -- I'm doubtful this is really effective */
1783 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1784 optimization in Windows 2000 clients --jerry */
1786 if ( (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1787 && (RA_WIN2K
== get_remote_arch()) )
1789 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1790 sys_usleep( 500000 );
1797 /****************************************************************************
1798 ****************************************************************************/
1800 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1801 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1807 ret
= uni_2_asc_printer_info_2(uni
->info_2
, &printer
->info_2
);
1816 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1817 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1823 printer
->info_3
=NULL
;
1824 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1828 printer
->info_6
=NULL
;
1829 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1839 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1840 NT_DEVICEMODE
**pp_nt_devmode
)
1842 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1845 * Ensure nt_devmode is a valid pointer
1846 * as we will be overwriting it.
1849 if (nt_devmode
== NULL
) {
1850 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1851 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1855 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1856 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1858 nt_devmode
->specversion
=devmode
->specversion
;
1859 nt_devmode
->driverversion
=devmode
->driverversion
;
1860 nt_devmode
->size
=devmode
->size
;
1861 nt_devmode
->fields
=devmode
->fields
;
1862 nt_devmode
->orientation
=devmode
->orientation
;
1863 nt_devmode
->papersize
=devmode
->papersize
;
1864 nt_devmode
->paperlength
=devmode
->paperlength
;
1865 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1866 nt_devmode
->scale
=devmode
->scale
;
1867 nt_devmode
->copies
=devmode
->copies
;
1868 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1869 nt_devmode
->printquality
=devmode
->printquality
;
1870 nt_devmode
->color
=devmode
->color
;
1871 nt_devmode
->duplex
=devmode
->duplex
;
1872 nt_devmode
->yresolution
=devmode
->yresolution
;
1873 nt_devmode
->ttoption
=devmode
->ttoption
;
1874 nt_devmode
->collate
=devmode
->collate
;
1876 nt_devmode
->logpixels
=devmode
->logpixels
;
1877 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1878 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1879 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1880 nt_devmode
->displayflags
=devmode
->displayflags
;
1881 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1882 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1883 nt_devmode
->icmintent
=devmode
->icmintent
;
1884 nt_devmode
->mediatype
=devmode
->mediatype
;
1885 nt_devmode
->dithertype
=devmode
->dithertype
;
1886 nt_devmode
->reserved1
=devmode
->reserved1
;
1887 nt_devmode
->reserved2
=devmode
->reserved2
;
1888 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1889 nt_devmode
->panningheight
=devmode
->panningheight
;
1892 * Only change private and driverextra if the incoming devmode
1893 * has a new one. JRA.
1896 if ((devmode
->driverextra
!= 0) && (devmode
->private != NULL
)) {
1897 SAFE_FREE(nt_devmode
->private);
1898 nt_devmode
->driverextra
=devmode
->driverextra
;
1899 if((nt_devmode
->private=(uint8
*)malloc(nt_devmode
->driverextra
* sizeof(uint8
))) == NULL
)
1901 memcpy(nt_devmode
->private, devmode
->private, nt_devmode
->driverextra
);
1904 *pp_nt_devmode
= nt_devmode
;
1909 /********************************************************************
1910 * _spoolss_enddocprinter_internal.
1911 ********************************************************************/
1913 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1915 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1919 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1923 if (!get_printer_snum(p
, handle
, &snum
))
1926 Printer
->document_started
=False
;
1927 print_job_end(snum
, Printer
->jobid
,True
);
1928 /* error codes unhandled so far ... */
1933 /********************************************************************
1934 * api_spoolss_closeprinter
1935 ********************************************************************/
1937 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1939 POLICY_HND
*handle
= &q_u
->handle
;
1941 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1943 if (Printer
&& Printer
->document_started
)
1944 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1946 if (!close_printer_handle(p
, handle
))
1949 /* clear the returned printer handle. Observed behavior
1950 from Win2k server. Don't think this really matters.
1951 Previous code just copied the value of the closed
1954 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1959 /********************************************************************
1960 * api_spoolss_deleteprinter
1962 ********************************************************************/
1964 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1966 POLICY_HND
*handle
= &q_u
->handle
;
1967 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1970 if (Printer
&& Printer
->document_started
)
1971 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1973 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1975 result
= delete_printer_handle(p
, handle
);
1977 update_c_setprinter(False
);
1982 /*******************************************************************
1983 * static function to lookup the version id corresponding to an
1984 * long architecture string
1985 ******************************************************************/
1987 static int get_version_id (char * arch
)
1990 struct table_node archi_table
[]= {
1992 {"Windows 4.0", "WIN40", 0 },
1993 {"Windows NT x86", "W32X86", 2 },
1994 {"Windows NT R4000", "W32MIPS", 2 },
1995 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1996 {"Windows NT PowerPC", "W32PPC", 2 },
1997 {"Windows IA64", "IA64", 3 },
1998 {"Windows x64", "x64", 3 },
2002 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
2004 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
2005 return (archi_table
[i
].version
);
2011 /********************************************************************
2012 * _spoolss_deleteprinterdriver
2013 ********************************************************************/
2015 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
2019 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2020 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2022 struct current_user user
;
2024 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2026 get_current_user(&user
, p
);
2028 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2029 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2031 /* check that we have a valid driver name first */
2033 if ((version
=get_version_id(arch
)) == -1)
2034 return WERR_INVALID_ENVIRONMENT
;
2037 ZERO_STRUCT(info_win2k
);
2039 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
2041 /* try for Win2k driver if "Windows NT x86" */
2043 if ( version
== 2 ) {
2045 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2046 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2050 /* otherwise it was a failure */
2052 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2058 if (printer_driver_in_use(info
.info_3
)) {
2059 status
= WERR_PRINTER_DRIVER_IN_USE
;
2065 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2067 /* if we get to here, we now have 2 driver info structures to remove */
2068 /* remove the Win2k driver first*/
2070 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
2071 free_a_printer_driver( info_win2k
, 3 );
2073 /* this should not have failed---if it did, report to client */
2074 if ( !W_ERROR_IS_OK(status_win2k
) )
2079 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
2081 /* if at least one of the deletes succeeded return OK */
2083 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2087 free_a_printer_driver( info
, 3 );
2092 /********************************************************************
2093 * spoolss_deleteprinterdriverex
2094 ********************************************************************/
2096 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
2100 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2101 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2103 uint32 flags
= q_u
->delete_flags
;
2105 struct current_user user
;
2107 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2109 get_current_user(&user
, p
);
2111 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2112 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2114 /* check that we have a valid driver name first */
2115 if ((version
=get_version_id(arch
)) == -1) {
2116 /* this is what NT returns */
2117 return WERR_INVALID_ENVIRONMENT
;
2120 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2121 version
= q_u
->version
;
2124 ZERO_STRUCT(info_win2k
);
2126 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2128 if ( !W_ERROR_IS_OK(status
) )
2131 * if the client asked for a specific version,
2132 * or this is something other than Windows NT x86,
2136 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2139 /* try for Win2k driver if "Windows NT x86" */
2142 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2143 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2148 if ( printer_driver_in_use(info
.info_3
) ) {
2149 status
= WERR_PRINTER_DRIVER_IN_USE
;
2154 * we have a couple of cases to consider.
2155 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2156 * then the delete should fail if **any** files overlap with
2158 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2159 * non-overlapping files
2160 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2161 * is set, the do not delete any files
2162 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2165 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2167 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2169 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2170 /* no idea of the correct error here */
2171 status
= WERR_ACCESS_DENIED
;
2176 /* also check for W32X86/3 if necessary; maybe we already have? */
2178 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2179 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2182 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2183 /* no idea of the correct error here */
2184 free_a_printer_driver( info_win2k
, 3 );
2185 status
= WERR_ACCESS_DENIED
;
2189 /* if we get to here, we now have 2 driver info structures to remove */
2190 /* remove the Win2k driver first*/
2192 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2193 free_a_printer_driver( info_win2k
, 3 );
2195 /* this should not have failed---if it did, report to client */
2197 if ( !W_ERROR_IS_OK(status_win2k
) )
2202 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2204 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2207 free_a_printer_driver( info
, 3 );
2213 /****************************************************************************
2214 Internal routine for retreiving printerdata
2215 ***************************************************************************/
2217 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2218 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2219 uint32
*needed
, uint32 in_size
)
2221 REGISTRY_VALUE
*val
;
2224 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2225 return WERR_BADFILE
;
2227 *type
= regval_type( val
);
2229 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2231 size
= regval_size( val
);
2233 /* copy the min(in_size, len) */
2236 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2238 /* special case for 0 length values */
2240 if ( (*data
= (uint8
*)talloc_memdup(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2244 if ( (*data
= (uint8
*)talloc_zero(ctx
, in_size
)) == NULL
)
2253 DEBUG(5,("get_printer_dataex: copy done\n"));
2258 /****************************************************************************
2259 Internal routine for removing printerdata
2260 ***************************************************************************/
2262 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2264 return delete_printer_data( printer
->info_2
, key
, value
);
2267 /****************************************************************************
2268 Internal routine for storing printerdata
2269 ***************************************************************************/
2271 static WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2272 uint32 type
, uint8
*data
, int real_len
)
2274 delete_printer_data( printer
->info_2
, key
, value
);
2276 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2279 /********************************************************************
2280 GetPrinterData on a printer server Handle.
2281 ********************************************************************/
2283 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2287 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2289 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2291 if((*data
= (uint8
*)talloc_zero(ctx
, 4*sizeof(uint8
) )) == NULL
)
2297 if (!StrCaseCmp(value
, "BeepEnabled")) {
2299 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2301 SIVAL(*data
, 0, 0x00);
2306 if (!StrCaseCmp(value
, "EventLog")) {
2308 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2310 /* formally was 0x1b */
2311 SIVAL(*data
, 0, 0x0);
2316 if (!StrCaseCmp(value
, "NetPopup")) {
2318 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2320 SIVAL(*data
, 0, 0x00);
2325 if (!StrCaseCmp(value
, "MajorVersion")) {
2327 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2330 /* Windows NT 4.0 seems to not allow uploading of drivers
2331 to a server that reports 0x3 as the MajorVersion.
2332 need to investigate more how Win2k gets around this .
2335 if ( RA_WINNT
== get_remote_arch() )
2344 if (!StrCaseCmp(value
, "MinorVersion")) {
2346 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2354 * uint32 size = 0x114
2356 * uint32 minor = [0|1]
2357 * uint32 build = [2195|2600]
2358 * extra unicode string = e.g. "Service Pack 3"
2360 if (!StrCaseCmp(value
, "OSVersion")) {
2364 if((*data
= (uint8
*)talloc(ctx
, (*needed
)*sizeof(uint8
) )) == NULL
)
2366 ZERO_STRUCTP( *data
);
2368 SIVAL(*data
, 0, *needed
); /* size */
2369 SIVAL(*data
, 4, 5); /* Windows 2000 == 5.0 */
2371 SIVAL(*data
, 12, 2195); /* build */
2373 /* leave extra string empty */
2379 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2380 const char *string
="C:\\PRINTERS";
2382 *needed
= 2*(strlen(string
)+1);
2383 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2385 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2387 /* it's done by hand ready to go on the wire */
2388 for (i
=0; i
<strlen(string
); i
++) {
2389 (*data
)[2*i
]=string
[i
];
2390 (*data
)[2*i
+1]='\0';
2395 if (!StrCaseCmp(value
, "Architecture")) {
2396 const char *string
="Windows NT x86";
2398 *needed
= 2*(strlen(string
)+1);
2399 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2401 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2402 for (i
=0; i
<strlen(string
); i
++) {
2403 (*data
)[2*i
]=string
[i
];
2404 (*data
)[2*i
+1]='\0';
2409 if (!StrCaseCmp(value
, "DsPresent")) {
2411 if((*data
= (uint8
*)talloc(ctx
, 4*sizeof(uint8
) )) == NULL
)
2413 SIVAL(*data
, 0, 0x01);
2418 if (!StrCaseCmp(value
, "DNSMachineName")) {
2421 if (!get_mydnsfullname(hostname
))
2422 return WERR_BADFILE
;
2424 *needed
= 2*(strlen(hostname
)+1);
2425 if((*data
= (uint8
*)talloc(ctx
, ((*needed
> in_size
) ? *needed
:in_size
) *sizeof(uint8
))) == NULL
)
2427 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2428 for (i
=0; i
<strlen(hostname
); i
++) {
2429 (*data
)[2*i
]=hostname
[i
];
2430 (*data
)[2*i
+1]='\0';
2436 return WERR_BADFILE
;
2439 /********************************************************************
2440 * spoolss_getprinterdata
2441 ********************************************************************/
2443 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2445 POLICY_HND
*handle
= &q_u
->handle
;
2446 UNISTR2
*valuename
= &q_u
->valuename
;
2447 uint32 in_size
= q_u
->size
;
2448 uint32
*type
= &r_u
->type
;
2449 uint32
*out_size
= &r_u
->size
;
2450 uint8
**data
= &r_u
->data
;
2451 uint32
*needed
= &r_u
->needed
;
2454 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2455 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2459 * Reminder: when it's a string, the length is in BYTES
2460 * even if UNICODE is negociated.
2465 *out_size
= in_size
;
2467 /* in case of problem, return some default values */
2472 DEBUG(4,("_spoolss_getprinterdata\n"));
2475 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2476 status
= WERR_BADFID
;
2480 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2482 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2483 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2486 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2487 status
= WERR_BADFID
;
2491 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2492 if ( !W_ERROR_IS_OK(status
) )
2495 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2497 if ( strequal(value
, "ChangeId") ) {
2499 *needed
= sizeof(uint32
);
2500 if ( (*data
= (uint8
*)talloc(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2501 status
= WERR_NOMEM
;
2504 SIVAL( *data
, 0, printer
->info_2
->changeid
);
2508 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2511 if (*needed
> *out_size
)
2512 status
= WERR_MORE_DATA
;
2515 if ( !W_ERROR_IS_OK(status
) )
2517 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2519 /* reply this param doesn't exist */
2522 if((*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
2524 free_a_printer( &printer
, 2 );
2533 /* cleanup & exit */
2536 free_a_printer( &printer
, 2 );
2541 /*********************************************************
2542 Connect to the client machine.
2543 **********************************************************/
2545 static BOOL
spoolss_connect_to_client(struct cli_state
*the_cli
,
2546 struct in_addr
*client_ip
, const char *remote_machine
)
2548 ZERO_STRUCTP(the_cli
);
2550 if(cli_initialise(the_cli
) == NULL
) {
2551 DEBUG(0,("spoolss_connect_to_client: unable to initialize client connection.\n"));
2555 if ( is_zero_ip(*client_ip
) ) {
2556 if(!resolve_name( remote_machine
, &the_cli
->dest_ip
, 0x20)) {
2557 DEBUG(0,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2558 cli_shutdown(the_cli
);
2562 if (ismyip(the_cli
->dest_ip
)) {
2563 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2564 cli_shutdown(the_cli
);
2569 the_cli
->dest_ip
.s_addr
= client_ip
->s_addr
;
2570 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2571 inet_ntoa(*client_ip
) ));
2574 if (!cli_connect(the_cli
, remote_machine
, &the_cli
->dest_ip
)) {
2575 DEBUG(0,("spoolss_connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2576 cli_shutdown(the_cli
);
2580 if (!attempt_netbios_session_request(the_cli
, global_myname(), remote_machine
, &the_cli
->dest_ip
)) {
2581 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the NetBIOS session request.\n",
2583 cli_shutdown(the_cli
);
2587 the_cli
->protocol
= PROTOCOL_NT1
;
2588 cli_setup_signing_state(the_cli
, lp_client_signing());
2590 if (!cli_negprot(the_cli
)) {
2591 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2592 cli_shutdown(the_cli
);
2596 if (the_cli
->protocol
!= PROTOCOL_NT1
) {
2597 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2598 cli_shutdown(the_cli
);
2603 * Do an anonymous session setup.
2606 if (!cli_session_setup(the_cli
, "", "", 0, "", 0, "")) {
2607 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2608 cli_shutdown(the_cli
);
2612 if (!(the_cli
->sec_mode
& 1)) {
2613 DEBUG(0,("spoolss_connect_to_client: machine %s isn't in user level security mode\n", remote_machine
));
2614 cli_shutdown(the_cli
);
2618 if (!cli_send_tconX(the_cli
, "IPC$", "IPC", "", 1)) {
2619 DEBUG(0,("spoolss_connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
) ));
2620 cli_shutdown(the_cli
);
2625 * Ok - we have an anonymous connection to the IPC$ share.
2626 * Now start the NT Domain stuff :-).
2629 if(cli_nt_session_open(the_cli
, PI_SPOOLSS
) == False
) {
2630 DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine
, cli_errstr(the_cli
)));
2631 cli_nt_session_close(the_cli
);
2632 cli_ulogoff(the_cli
);
2633 cli_shutdown(the_cli
);
2640 /***************************************************************************
2641 Connect to the client.
2642 ****************************************************************************/
2644 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2645 uint32 localprinter
, uint32 type
,
2646 POLICY_HND
*handle
, struct in_addr
*client_ip
)
2651 * If it's the first connection, contact the client
2652 * and connect to the IPC$ share anonymously
2654 if (smb_connections
==0) {
2655 fstring unix_printer
;
2657 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2659 ZERO_STRUCT(notify_cli
);
2661 if(!spoolss_connect_to_client(¬ify_cli
, client_ip
, unix_printer
))
2664 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2665 /* Tell the connections db we're now interested in printer
2666 * notify messages. */
2667 register_message_flags( True
, FLAG_MSG_PRINT_NOTIFY
);
2671 * Tell the specific printing tdb we want messages for this printer
2672 * by registering our PID.
2675 if (!print_notify_register_pid(snum
))
2676 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2680 result
= cli_spoolss_reply_open_printer(¬ify_cli
, notify_cli
.mem_ctx
, printer
, localprinter
,
2683 if (!W_ERROR_IS_OK(result
))
2684 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2685 dos_errstr(result
)));
2687 return (W_ERROR_IS_OK(result
));
2690 /********************************************************************
2692 * ReplyFindFirstPrinterChangeNotifyEx
2694 * before replying OK: status=0 a rpc call is made to the workstation
2695 * asking ReplyOpenPrinter
2697 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2698 * called from api_spoolss_rffpcnex
2699 ********************************************************************/
2701 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2703 POLICY_HND
*handle
= &q_u
->handle
;
2704 uint32 flags
= q_u
->flags
;
2705 uint32 options
= q_u
->options
;
2706 UNISTR2
*localmachine
= &q_u
->localmachine
;
2707 uint32 printerlocal
= q_u
->printerlocal
;
2709 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2710 struct in_addr client_ip
;
2712 /* store the notify value in the printer struct */
2714 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2717 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2721 Printer
->notify
.flags
=flags
;
2722 Printer
->notify
.options
=options
;
2723 Printer
->notify
.printerlocal
=printerlocal
;
2725 if (Printer
->notify
.option
)
2726 free_spool_notify_option(&Printer
->notify
.option
);
2728 Printer
->notify
.option
=dup_spool_notify_option(option
);
2730 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2731 sizeof(Printer
->notify
.localmachine
)-1);
2733 /* Connect to the client machine and send a ReplyOpenPrinter */
2735 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
2737 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
2738 !get_printer_snum(p
, handle
, &snum
) )
2741 client_ip
.s_addr
= inet_addr(p
->conn
->client_address
);
2743 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2744 Printer
->notify
.printerlocal
, 1,
2745 &Printer
->notify
.client_hnd
, &client_ip
))
2746 return WERR_SERVER_UNAVAILABLE
;
2748 Printer
->notify
.client_connected
=True
;
2753 #if 0 /* JERRY -- disabled; not used for now */
2755 /*******************************************************************
2756 * fill a notify_info_data with the servername
2757 ********************************************************************/
2759 void spoolss_notify_server_name(int snum
,
2760 SPOOL_NOTIFY_INFO_DATA
*data
,
2761 print_queue_struct
*queue
,
2762 NT_PRINTER_INFO_LEVEL
*printer
,
2763 TALLOC_CTX
*mem_ctx
)
2765 pstring temp_name
, temp
;
2768 fstrcpy( temp_name
, "\\\\%L" );
2769 standard_sub_basic( "", temp_name
, sizeof(temp_name
)-1 );
2772 len
= rpcstr_push(temp
, temp_name
, sizeof(temp
)-2, STR_TERMINATE
);
2774 data
->notify_data
.data
.length
= len
;
2775 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2777 if (!data
->notify_data
.data
.string
) {
2778 data
->notify_data
.data
.length
= 0;
2782 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2788 /*******************************************************************
2789 * fill a notify_info_data with the printername (not including the servername).
2790 ********************************************************************/
2792 void spoolss_notify_printer_name(int snum
,
2793 SPOOL_NOTIFY_INFO_DATA
*data
,
2794 print_queue_struct
*queue
,
2795 NT_PRINTER_INFO_LEVEL
*printer
,
2796 TALLOC_CTX
*mem_ctx
)
2801 /* the notify name should not contain the \\server\ part */
2802 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2805 p
= printer
->info_2
->printername
;
2810 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2812 data
->notify_data
.data
.length
= len
;
2813 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2815 if (!data
->notify_data
.data
.string
) {
2816 data
->notify_data
.data
.length
= 0;
2820 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2823 /*******************************************************************
2824 * fill a notify_info_data with the servicename
2825 ********************************************************************/
2827 void spoolss_notify_share_name(int snum
,
2828 SPOOL_NOTIFY_INFO_DATA
*data
,
2829 print_queue_struct
*queue
,
2830 NT_PRINTER_INFO_LEVEL
*printer
,
2831 TALLOC_CTX
*mem_ctx
)
2836 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2838 data
->notify_data
.data
.length
= len
;
2839 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2841 if (!data
->notify_data
.data
.string
) {
2842 data
->notify_data
.data
.length
= 0;
2846 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2849 /*******************************************************************
2850 * fill a notify_info_data with the port name
2851 ********************************************************************/
2853 void spoolss_notify_port_name(int snum
,
2854 SPOOL_NOTIFY_INFO_DATA
*data
,
2855 print_queue_struct
*queue
,
2856 NT_PRINTER_INFO_LEVEL
*printer
,
2857 TALLOC_CTX
*mem_ctx
)
2862 /* even if it's strange, that's consistant in all the code */
2864 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2866 data
->notify_data
.data
.length
= len
;
2867 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2869 if (!data
->notify_data
.data
.string
) {
2870 data
->notify_data
.data
.length
= 0;
2874 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2877 /*******************************************************************
2878 * fill a notify_info_data with the printername
2879 * but it doesn't exist, have to see what to do
2880 ********************************************************************/
2882 void spoolss_notify_driver_name(int snum
,
2883 SPOOL_NOTIFY_INFO_DATA
*data
,
2884 print_queue_struct
*queue
,
2885 NT_PRINTER_INFO_LEVEL
*printer
,
2886 TALLOC_CTX
*mem_ctx
)
2891 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2893 data
->notify_data
.data
.length
= len
;
2894 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2896 if (!data
->notify_data
.data
.string
) {
2897 data
->notify_data
.data
.length
= 0;
2901 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2904 /*******************************************************************
2905 * fill a notify_info_data with the comment
2906 ********************************************************************/
2908 void spoolss_notify_comment(int snum
,
2909 SPOOL_NOTIFY_INFO_DATA
*data
,
2910 print_queue_struct
*queue
,
2911 NT_PRINTER_INFO_LEVEL
*printer
,
2912 TALLOC_CTX
*mem_ctx
)
2917 if (*printer
->info_2
->comment
== '\0')
2918 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2920 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2922 data
->notify_data
.data
.length
= len
;
2923 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2925 if (!data
->notify_data
.data
.string
) {
2926 data
->notify_data
.data
.length
= 0;
2930 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2933 /*******************************************************************
2934 * fill a notify_info_data with the comment
2935 * location = "Room 1, floor 2, building 3"
2936 ********************************************************************/
2938 void spoolss_notify_location(int snum
,
2939 SPOOL_NOTIFY_INFO_DATA
*data
,
2940 print_queue_struct
*queue
,
2941 NT_PRINTER_INFO_LEVEL
*printer
,
2942 TALLOC_CTX
*mem_ctx
)
2947 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2949 data
->notify_data
.data
.length
= len
;
2950 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2952 if (!data
->notify_data
.data
.string
) {
2953 data
->notify_data
.data
.length
= 0;
2957 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2960 /*******************************************************************
2961 * fill a notify_info_data with the device mode
2962 * jfm:xxxx don't to it for know but that's a real problem !!!
2963 ********************************************************************/
2965 static void spoolss_notify_devmode(int snum
,
2966 SPOOL_NOTIFY_INFO_DATA
*data
,
2967 print_queue_struct
*queue
,
2968 NT_PRINTER_INFO_LEVEL
*printer
,
2969 TALLOC_CTX
*mem_ctx
)
2973 /*******************************************************************
2974 * fill a notify_info_data with the separator file name
2975 ********************************************************************/
2977 void spoolss_notify_sepfile(int snum
,
2978 SPOOL_NOTIFY_INFO_DATA
*data
,
2979 print_queue_struct
*queue
,
2980 NT_PRINTER_INFO_LEVEL
*printer
,
2981 TALLOC_CTX
*mem_ctx
)
2986 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2988 data
->notify_data
.data
.length
= len
;
2989 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
2991 if (!data
->notify_data
.data
.string
) {
2992 data
->notify_data
.data
.length
= 0;
2996 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2999 /*******************************************************************
3000 * fill a notify_info_data with the print processor
3001 * jfm:xxxx return always winprint to indicate we don't do anything to it
3002 ********************************************************************/
3004 void spoolss_notify_print_processor(int snum
,
3005 SPOOL_NOTIFY_INFO_DATA
*data
,
3006 print_queue_struct
*queue
,
3007 NT_PRINTER_INFO_LEVEL
*printer
,
3008 TALLOC_CTX
*mem_ctx
)
3013 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
3015 data
->notify_data
.data
.length
= len
;
3016 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3018 if (!data
->notify_data
.data
.string
) {
3019 data
->notify_data
.data
.length
= 0;
3023 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3026 /*******************************************************************
3027 * fill a notify_info_data with the print processor options
3028 * jfm:xxxx send an empty string
3029 ********************************************************************/
3031 void spoolss_notify_parameters(int snum
,
3032 SPOOL_NOTIFY_INFO_DATA
*data
,
3033 print_queue_struct
*queue
,
3034 NT_PRINTER_INFO_LEVEL
*printer
,
3035 TALLOC_CTX
*mem_ctx
)
3040 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
3042 data
->notify_data
.data
.length
= len
;
3043 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3045 if (!data
->notify_data
.data
.string
) {
3046 data
->notify_data
.data
.length
= 0;
3050 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3053 /*******************************************************************
3054 * fill a notify_info_data with the data type
3055 * jfm:xxxx always send RAW as data type
3056 ********************************************************************/
3058 void spoolss_notify_datatype(int snum
,
3059 SPOOL_NOTIFY_INFO_DATA
*data
,
3060 print_queue_struct
*queue
,
3061 NT_PRINTER_INFO_LEVEL
*printer
,
3062 TALLOC_CTX
*mem_ctx
)
3067 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
3069 data
->notify_data
.data
.length
= len
;
3070 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3072 if (!data
->notify_data
.data
.string
) {
3073 data
->notify_data
.data
.length
= 0;
3077 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3080 /*******************************************************************
3081 * fill a notify_info_data with the security descriptor
3082 * jfm:xxxx send an null pointer to say no security desc
3083 * have to implement security before !
3084 ********************************************************************/
3086 static void spoolss_notify_security_desc(int snum
,
3087 SPOOL_NOTIFY_INFO_DATA
*data
,
3088 print_queue_struct
*queue
,
3089 NT_PRINTER_INFO_LEVEL
*printer
,
3090 TALLOC_CTX
*mem_ctx
)
3092 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
3093 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
3096 /*******************************************************************
3097 * fill a notify_info_data with the attributes
3098 * jfm:xxxx a samba printer is always shared
3099 ********************************************************************/
3101 void spoolss_notify_attributes(int snum
,
3102 SPOOL_NOTIFY_INFO_DATA
*data
,
3103 print_queue_struct
*queue
,
3104 NT_PRINTER_INFO_LEVEL
*printer
,
3105 TALLOC_CTX
*mem_ctx
)
3107 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
3108 data
->notify_data
.value
[1] = 0;
3111 /*******************************************************************
3112 * fill a notify_info_data with the priority
3113 ********************************************************************/
3115 static void spoolss_notify_priority(int snum
,
3116 SPOOL_NOTIFY_INFO_DATA
*data
,
3117 print_queue_struct
*queue
,
3118 NT_PRINTER_INFO_LEVEL
*printer
,
3119 TALLOC_CTX
*mem_ctx
)
3121 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
3122 data
->notify_data
.value
[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with the default priority
3127 ********************************************************************/
3129 static void spoolss_notify_default_priority(int snum
,
3130 SPOOL_NOTIFY_INFO_DATA
*data
,
3131 print_queue_struct
*queue
,
3132 NT_PRINTER_INFO_LEVEL
*printer
,
3133 TALLOC_CTX
*mem_ctx
)
3135 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
3136 data
->notify_data
.value
[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the start time
3141 ********************************************************************/
3143 static void spoolss_notify_start_time(int snum
,
3144 SPOOL_NOTIFY_INFO_DATA
*data
,
3145 print_queue_struct
*queue
,
3146 NT_PRINTER_INFO_LEVEL
*printer
,
3147 TALLOC_CTX
*mem_ctx
)
3149 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
3150 data
->notify_data
.value
[1] = 0;
3153 /*******************************************************************
3154 * fill a notify_info_data with the until time
3155 ********************************************************************/
3157 static void spoolss_notify_until_time(int snum
,
3158 SPOOL_NOTIFY_INFO_DATA
*data
,
3159 print_queue_struct
*queue
,
3160 NT_PRINTER_INFO_LEVEL
*printer
,
3161 TALLOC_CTX
*mem_ctx
)
3163 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3164 data
->notify_data
.value
[1] = 0;
3167 /*******************************************************************
3168 * fill a notify_info_data with the status
3169 ********************************************************************/
3171 static void spoolss_notify_status(int snum
,
3172 SPOOL_NOTIFY_INFO_DATA
*data
,
3173 print_queue_struct
*queue
,
3174 NT_PRINTER_INFO_LEVEL
*printer
,
3175 TALLOC_CTX
*mem_ctx
)
3177 print_status_struct status
;
3179 print_queue_length(snum
, &status
);
3180 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3181 data
->notify_data
.value
[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with the number of jobs queued
3186 ********************************************************************/
3188 void spoolss_notify_cjobs(int snum
,
3189 SPOOL_NOTIFY_INFO_DATA
*data
,
3190 print_queue_struct
*queue
,
3191 NT_PRINTER_INFO_LEVEL
*printer
,
3192 TALLOC_CTX
*mem_ctx
)
3194 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3195 data
->notify_data
.value
[1] = 0;
3198 /*******************************************************************
3199 * fill a notify_info_data with the average ppm
3200 ********************************************************************/
3202 static void spoolss_notify_average_ppm(int snum
,
3203 SPOOL_NOTIFY_INFO_DATA
*data
,
3204 print_queue_struct
*queue
,
3205 NT_PRINTER_INFO_LEVEL
*printer
,
3206 TALLOC_CTX
*mem_ctx
)
3208 /* always respond 8 pages per minutes */
3209 /* a little hard ! */
3210 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3211 data
->notify_data
.value
[1] = 0;
3214 /*******************************************************************
3215 * fill a notify_info_data with username
3216 ********************************************************************/
3218 static void spoolss_notify_username(int snum
,
3219 SPOOL_NOTIFY_INFO_DATA
*data
,
3220 print_queue_struct
*queue
,
3221 NT_PRINTER_INFO_LEVEL
*printer
,
3222 TALLOC_CTX
*mem_ctx
)
3227 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3229 data
->notify_data
.data
.length
= len
;
3230 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3232 if (!data
->notify_data
.data
.string
) {
3233 data
->notify_data
.data
.length
= 0;
3237 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3240 /*******************************************************************
3241 * fill a notify_info_data with job status
3242 ********************************************************************/
3244 static void spoolss_notify_job_status(int snum
,
3245 SPOOL_NOTIFY_INFO_DATA
*data
,
3246 print_queue_struct
*queue
,
3247 NT_PRINTER_INFO_LEVEL
*printer
,
3248 TALLOC_CTX
*mem_ctx
)
3250 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3251 data
->notify_data
.value
[1] = 0;
3254 /*******************************************************************
3255 * fill a notify_info_data with job name
3256 ********************************************************************/
3258 static void spoolss_notify_job_name(int snum
,
3259 SPOOL_NOTIFY_INFO_DATA
*data
,
3260 print_queue_struct
*queue
,
3261 NT_PRINTER_INFO_LEVEL
*printer
,
3262 TALLOC_CTX
*mem_ctx
)
3267 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3269 data
->notify_data
.data
.length
= len
;
3270 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3272 if (!data
->notify_data
.data
.string
) {
3273 data
->notify_data
.data
.length
= 0;
3277 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3280 /*******************************************************************
3281 * fill a notify_info_data with job status
3282 ********************************************************************/
3284 static void spoolss_notify_job_status_string(int snum
,
3285 SPOOL_NOTIFY_INFO_DATA
*data
,
3286 print_queue_struct
*queue
,
3287 NT_PRINTER_INFO_LEVEL
*printer
,
3288 TALLOC_CTX
*mem_ctx
)
3291 * Now we're returning job status codes we just return a "" here. JRA.
3298 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3301 switch (queue
->status
) {
3306 p
= ""; /* NT provides the paused string */
3315 #endif /* NO LONGER NEEDED. */
3317 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3319 data
->notify_data
.data
.length
= len
;
3320 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3322 if (!data
->notify_data
.data
.string
) {
3323 data
->notify_data
.data
.length
= 0;
3327 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3330 /*******************************************************************
3331 * fill a notify_info_data with job time
3332 ********************************************************************/
3334 static void spoolss_notify_job_time(int snum
,
3335 SPOOL_NOTIFY_INFO_DATA
*data
,
3336 print_queue_struct
*queue
,
3337 NT_PRINTER_INFO_LEVEL
*printer
,
3338 TALLOC_CTX
*mem_ctx
)
3340 data
->notify_data
.value
[0]=0x0;
3341 data
->notify_data
.value
[1]=0;
3344 /*******************************************************************
3345 * fill a notify_info_data with job size
3346 ********************************************************************/
3348 static void spoolss_notify_job_size(int snum
,
3349 SPOOL_NOTIFY_INFO_DATA
*data
,
3350 print_queue_struct
*queue
,
3351 NT_PRINTER_INFO_LEVEL
*printer
,
3352 TALLOC_CTX
*mem_ctx
)
3354 data
->notify_data
.value
[0]=queue
->size
;
3355 data
->notify_data
.value
[1]=0;
3358 /*******************************************************************
3359 * fill a notify_info_data with page info
3360 ********************************************************************/
3361 static void spoolss_notify_total_pages(int snum
,
3362 SPOOL_NOTIFY_INFO_DATA
*data
,
3363 print_queue_struct
*queue
,
3364 NT_PRINTER_INFO_LEVEL
*printer
,
3365 TALLOC_CTX
*mem_ctx
)
3367 data
->notify_data
.value
[0]=queue
->page_count
;
3368 data
->notify_data
.value
[1]=0;
3371 /*******************************************************************
3372 * fill a notify_info_data with pages printed info.
3373 ********************************************************************/
3374 static void spoolss_notify_pages_printed(int snum
,
3375 SPOOL_NOTIFY_INFO_DATA
*data
,
3376 print_queue_struct
*queue
,
3377 NT_PRINTER_INFO_LEVEL
*printer
,
3378 TALLOC_CTX
*mem_ctx
)
3380 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3381 data
->notify_data
.value
[1]=0;
3384 /*******************************************************************
3385 Fill a notify_info_data with job position.
3386 ********************************************************************/
3388 static void spoolss_notify_job_position(int snum
,
3389 SPOOL_NOTIFY_INFO_DATA
*data
,
3390 print_queue_struct
*queue
,
3391 NT_PRINTER_INFO_LEVEL
*printer
,
3392 TALLOC_CTX
*mem_ctx
)
3394 data
->notify_data
.value
[0]=queue
->job
;
3395 data
->notify_data
.value
[1]=0;
3398 /*******************************************************************
3399 Fill a notify_info_data with submitted time.
3400 ********************************************************************/
3402 static void spoolss_notify_submitted_time(int snum
,
3403 SPOOL_NOTIFY_INFO_DATA
*data
,
3404 print_queue_struct
*queue
,
3405 NT_PRINTER_INFO_LEVEL
*printer
,
3406 TALLOC_CTX
*mem_ctx
)
3413 t
=gmtime(&queue
->time
);
3415 len
= sizeof(SYSTEMTIME
);
3417 data
->notify_data
.data
.length
= len
;
3418 data
->notify_data
.data
.string
= (uint16
*)talloc(mem_ctx
, len
);
3420 if (!data
->notify_data
.data
.string
) {
3421 data
->notify_data
.data
.length
= 0;
3425 make_systemtime(&st
, t
);
3428 * Systemtime must be linearized as a set of UINT16's.
3429 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3432 p
= (char *)data
->notify_data
.data
.string
;
3433 SSVAL(p
, 0, st
.year
);
3434 SSVAL(p
, 2, st
.month
);
3435 SSVAL(p
, 4, st
.dayofweek
);
3436 SSVAL(p
, 6, st
.day
);
3437 SSVAL(p
, 8, st
.hour
);
3438 SSVAL(p
, 10, st
.minute
);
3439 SSVAL(p
, 12, st
.second
);
3440 SSVAL(p
, 14, st
.milliseconds
);
3443 struct s_notify_info_data_table
3449 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3450 print_queue_struct
*queue
,
3451 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3454 /* A table describing the various print notification constants and
3455 whether the notification data is a pointer to a variable sized
3456 buffer, a one value uint32 or a two value uint32. */
3458 static const struct s_notify_info_data_table notify_info_data_table
[] =
3460 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, NULL
},
3461 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3462 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3463 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3464 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3465 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3466 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3467 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3468 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3469 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3470 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3471 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3472 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3473 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3474 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3475 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3476 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3477 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3478 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3479 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3480 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3481 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3482 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3483 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3484 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3485 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3486 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3487 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, NULL
},
3488 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3489 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3490 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3491 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3492 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3493 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3494 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3495 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3496 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3497 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3498 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3499 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3500 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3501 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3502 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3503 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3504 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3505 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3506 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3507 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3508 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3509 { PRINT_TABLE_END
, 0x0, NULL
, 0x0, NULL
},
3512 /*******************************************************************
3513 Return the size of info_data structure.
3514 ********************************************************************/
3516 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3520 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++)
3522 if ( (notify_info_data_table
[i
].type
== type
)
3523 && (notify_info_data_table
[i
].field
== field
) )
3525 switch(notify_info_data_table
[i
].size
)
3527 case NOTIFY_ONE_VALUE
:
3528 case NOTIFY_TWO_VALUE
:
3533 /* The only pointer notify data I have seen on
3534 the wire is the submitted time and this has
3535 the notify size set to 4. -tpot */
3537 case NOTIFY_POINTER
:
3540 case NOTIFY_SECDESC
:
3546 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3551 /*******************************************************************
3552 Return the type of notify_info_data.
3553 ********************************************************************/
3555 static int type_of_notify_info_data(uint16 type
, uint16 field
)
3559 for (i
= 0; i
< sizeof(notify_info_data_table
); i
++) {
3560 if (notify_info_data_table
[i
].type
== type
&&
3561 notify_info_data_table
[i
].field
== field
)
3562 return notify_info_data_table
[i
].size
;
3568 /****************************************************************************
3569 ****************************************************************************/
3571 static int search_notify(uint16 type
, uint16 field
, int *value
)
3575 for (i
= 0; notify_info_data_table
[i
].type
!= PRINT_TABLE_END
; i
++) {
3576 if (notify_info_data_table
[i
].type
== type
&&
3577 notify_info_data_table
[i
].field
== field
&&
3578 notify_info_data_table
[i
].fn
!= NULL
) {
3587 /****************************************************************************
3588 ****************************************************************************/
3590 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3592 info_data
->type
= type
;
3593 info_data
->field
= field
;
3594 info_data
->reserved
= 0;
3596 info_data
->size
= size_of_notify_info_data(type
, field
);
3597 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3604 /*******************************************************************
3606 * fill a notify_info struct with info asked
3608 ********************************************************************/
3610 static BOOL
construct_notify_printer_info(Printer_entry
*print_hnd
, SPOOL_NOTIFY_INFO
*info
, int
3611 snum
, SPOOL_NOTIFY_OPTION_TYPE
3612 *option_type
, uint32 id
,
3613 TALLOC_CTX
*mem_ctx
)
3619 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3620 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3621 print_queue_struct
*queue
=NULL
;
3623 type
=option_type
->type
;
3625 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3626 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3627 option_type
->count
, lp_servicename(snum
)));
3629 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3632 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3633 field
= option_type
->fields
[field_num
];
3635 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3637 if (!search_notify(type
, field
, &j
) )
3640 if((tid
=(SPOOL_NOTIFY_INFO_DATA
*)Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3641 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3646 current_data
= &info
->data
[info
->count
];
3648 construct_info_data(current_data
, type
, field
, id
);
3650 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3651 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3653 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3659 free_a_printer(&printer
, 2);
3663 /*******************************************************************
3665 * fill a notify_info struct with info asked
3667 ********************************************************************/
3669 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3670 SPOOL_NOTIFY_INFO
*info
,
3671 NT_PRINTER_INFO_LEVEL
*printer
,
3672 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3673 *option_type
, uint32 id
,
3674 TALLOC_CTX
*mem_ctx
)
3680 SPOOL_NOTIFY_INFO_DATA
*current_data
, *tid
;
3682 DEBUG(4,("construct_notify_jobs_info\n"));
3684 type
= option_type
->type
;
3686 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3687 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3688 option_type
->count
));
3690 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3691 field
= option_type
->fields
[field_num
];
3693 if (!search_notify(type
, field
, &j
) )
3696 if((tid
=Realloc(info
->data
, (info
->count
+1)*sizeof(SPOOL_NOTIFY_INFO_DATA
))) == NULL
) {
3697 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3700 else info
->data
= tid
;
3702 current_data
=&(info
->data
[info
->count
]);
3704 construct_info_data(current_data
, type
, field
, id
);
3705 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3714 * JFM: The enumeration is not that simple, it's even non obvious.
3716 * let's take an example: I want to monitor the PRINTER SERVER for
3717 * the printer's name and the number of jobs currently queued.
3718 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3719 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3721 * I have 3 printers on the back of my server.
3723 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3726 * 1 printer 1 name 1
3727 * 2 printer 1 cjob 1
3728 * 3 printer 2 name 2
3729 * 4 printer 2 cjob 2
3730 * 5 printer 3 name 3
3731 * 6 printer 3 name 3
3733 * that's the print server case, the printer case is even worse.
3736 /*******************************************************************
3738 * enumerate all printers on the printserver
3739 * fill a notify_info struct with info asked
3741 ********************************************************************/
3743 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3744 SPOOL_NOTIFY_INFO
*info
,
3745 TALLOC_CTX
*mem_ctx
)
3748 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3749 int n_services
=lp_numservices();
3751 SPOOL_NOTIFY_OPTION
*option
;
3752 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3754 DEBUG(4,("printserver_notify_info\n"));
3759 option
=Printer
->notify
.option
;
3764 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3765 sending a ffpcn() request first */
3770 for (i
=0; i
<option
->count
; i
++) {
3771 option_type
=&(option
->ctr
.type
[i
]);
3773 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3776 for (snum
=0; snum
<n_services
; snum
++)
3778 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3779 construct_notify_printer_info ( Printer
, info
, snum
, option_type
, snum
, mem_ctx
);
3785 * Debugging information, don't delete.
3788 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3789 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3790 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3792 for (i
=0; i
<info
->count
; i
++) {
3793 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3794 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3795 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3802 /*******************************************************************
3804 * fill a notify_info struct with info asked
3806 ********************************************************************/
3808 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3809 TALLOC_CTX
*mem_ctx
)
3812 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3815 SPOOL_NOTIFY_OPTION
*option
;
3816 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3818 print_queue_struct
*queue
=NULL
;
3819 print_status_struct status
;
3821 DEBUG(4,("printer_notify_info\n"));
3826 option
=Printer
->notify
.option
;
3832 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3833 sending a ffpcn() request first */
3838 get_printer_snum(p
, hnd
, &snum
);
3840 for (i
=0; i
<option
->count
; i
++) {
3841 option_type
=&option
->ctr
.type
[i
];
3843 switch ( option_type
->type
) {
3844 case PRINTER_NOTIFY_TYPE
:
3845 if(construct_notify_printer_info(Printer
, info
, snum
,
3851 case JOB_NOTIFY_TYPE
: {
3852 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3854 count
= print_queue_status(snum
, &queue
, &status
);
3856 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3859 for (j
=0; j
<count
; j
++) {
3860 construct_notify_jobs_info(&queue
[j
], info
,
3867 free_a_printer(&printer
, 2);
3877 * Debugging information, don't delete.
3880 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3881 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3882 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3884 for (i=0; i<info->count; i++) {
3885 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3886 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3887 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3893 /********************************************************************
3895 ********************************************************************/
3897 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3899 POLICY_HND
*handle
= &q_u
->handle
;
3900 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3902 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3903 WERROR result
= WERR_BADFID
;
3905 /* we always have a NOTIFY_INFO struct */
3909 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3910 OUR_HANDLE(handle
)));
3914 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3917 * We are now using the change value, and
3918 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3919 * I don't have a global notification system, I'm sending back all the
3920 * informations even when _NOTHING_ has changed.
3923 /* We need to keep track of the change value to send back in
3924 RRPCN replies otherwise our updates are ignored. */
3926 Printer
->notify
.fnpcn
= True
;
3928 if (Printer
->notify
.client_connected
) {
3929 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3930 Printer
->notify
.change
= q_u
->change
;
3933 /* just ignore the SPOOL_NOTIFY_OPTION */
3935 switch (Printer
->printer_type
) {
3936 case PRINTER_HANDLE_IS_PRINTSERVER
:
3937 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3940 case PRINTER_HANDLE_IS_PRINTER
:
3941 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3945 Printer
->notify
.fnpcn
= False
;
3951 /********************************************************************
3952 * construct_printer_info_0
3953 * fill a printer_info_0 struct
3954 ********************************************************************/
3956 static BOOL
construct_printer_info_0(Printer_entry
*print_hnd
, PRINTER_INFO_0
*printer
, int snum
)
3960 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3961 counter_printer_0
*session_counter
;
3962 uint32 global_counter
;
3965 print_status_struct status
;
3967 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3970 count
= print_queue_length(snum
, &status
);
3972 /* check if we already have a counter for this printer */
3973 for(session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3974 if (session_counter
->snum
== snum
)
3978 /* it's the first time, add it to the list */
3979 if (session_counter
==NULL
) {
3980 if((session_counter
=(counter_printer_0
*)malloc(sizeof(counter_printer_0
))) == NULL
) {
3981 free_a_printer(&ntprinter
, 2);
3984 ZERO_STRUCTP(session_counter
);
3985 session_counter
->snum
=snum
;
3986 session_counter
->counter
=0;
3987 DLIST_ADD(counter_list
, session_counter
);
3991 session_counter
->counter
++;
3994 * the global_counter should be stored in a TDB as it's common to all the clients
3995 * and should be zeroed on samba startup
3997 global_counter
=session_counter
->counter
;
3999 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
4001 init_unistr(&printer
->printername
, chaine
);
4003 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_server_name(print_hnd
));
4004 init_unistr(&printer
->servername
, chaine
);
4006 printer
->cjobs
= count
;
4007 printer
->total_jobs
= 0;
4008 printer
->total_bytes
= 0;
4010 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
4011 t
=gmtime(&setuptime
);
4013 printer
->year
= t
->tm_year
+1900;
4014 printer
->month
= t
->tm_mon
+1;
4015 printer
->dayofweek
= t
->tm_wday
;
4016 printer
->day
= t
->tm_mday
;
4017 printer
->hour
= t
->tm_hour
;
4018 printer
->minute
= t
->tm_min
;
4019 printer
->second
= t
->tm_sec
;
4020 printer
->milliseconds
= 0;
4022 printer
->global_counter
= global_counter
;
4023 printer
->total_pages
= 0;
4025 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4026 printer
->major_version
= 0x0005; /* NT 5 */
4027 printer
->build_version
= 0x0893; /* build 2195 */
4029 printer
->unknown7
= 0x1;
4030 printer
->unknown8
= 0x0;
4031 printer
->unknown9
= 0x0;
4032 printer
->session_counter
= session_counter
->counter
;
4033 printer
->unknown11
= 0x0;
4034 printer
->printer_errors
= 0x0; /* number of print failure */
4035 printer
->unknown13
= 0x0;
4036 printer
->unknown14
= 0x1;
4037 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
4038 printer
->unknown16
= 0x0;
4039 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
4040 printer
->unknown18
= 0x0;
4041 printer
->status
= nt_printq_status(status
.status
);
4042 printer
->unknown20
= 0x0;
4043 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4044 printer
->unknown22
= 0x0;
4045 printer
->unknown23
= 0x6; /* 6 ???*/
4046 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
4047 printer
->unknown25
= 0;
4048 printer
->unknown26
= 0;
4049 printer
->unknown27
= 0;
4050 printer
->unknown28
= 0;
4051 printer
->unknown29
= 0;
4053 free_a_printer(&ntprinter
,2);
4057 /********************************************************************
4058 * construct_printer_info_1
4059 * fill a printer_info_1 struct
4060 ********************************************************************/
4061 static BOOL
construct_printer_info_1(Printer_entry
*print_hnd
, uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
4065 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4067 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4070 printer
->flags
=flags
;
4072 if (*ntprinter
->info_2
->comment
== '\0') {
4073 init_unistr(&printer
->comment
, lp_comment(snum
));
4074 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4075 ntprinter
->info_2
->drivername
, lp_comment(snum
));
4078 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4079 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4080 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
4083 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
4085 init_unistr(&printer
->description
, chaine
);
4086 init_unistr(&printer
->name
, chaine2
);
4088 free_a_printer(&ntprinter
,2);
4093 /****************************************************************************
4094 Free a DEVMODE struct.
4095 ****************************************************************************/
4097 static void free_dev_mode(DEVICEMODE
*dev
)
4102 SAFE_FREE(dev
->private);
4107 /****************************************************************************
4108 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4109 should be valid upon entry
4110 ****************************************************************************/
4112 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
4114 if ( !devmode
|| !ntdevmode
)
4117 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
4119 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
4121 devmode
->specversion
= ntdevmode
->specversion
;
4122 devmode
->driverversion
= ntdevmode
->driverversion
;
4123 devmode
->size
= ntdevmode
->size
;
4124 devmode
->driverextra
= ntdevmode
->driverextra
;
4125 devmode
->fields
= ntdevmode
->fields
;
4127 devmode
->orientation
= ntdevmode
->orientation
;
4128 devmode
->papersize
= ntdevmode
->papersize
;
4129 devmode
->paperlength
= ntdevmode
->paperlength
;
4130 devmode
->paperwidth
= ntdevmode
->paperwidth
;
4131 devmode
->scale
= ntdevmode
->scale
;
4132 devmode
->copies
= ntdevmode
->copies
;
4133 devmode
->defaultsource
= ntdevmode
->defaultsource
;
4134 devmode
->printquality
= ntdevmode
->printquality
;
4135 devmode
->color
= ntdevmode
->color
;
4136 devmode
->duplex
= ntdevmode
->duplex
;
4137 devmode
->yresolution
= ntdevmode
->yresolution
;
4138 devmode
->ttoption
= ntdevmode
->ttoption
;
4139 devmode
->collate
= ntdevmode
->collate
;
4140 devmode
->icmmethod
= ntdevmode
->icmmethod
;
4141 devmode
->icmintent
= ntdevmode
->icmintent
;
4142 devmode
->mediatype
= ntdevmode
->mediatype
;
4143 devmode
->dithertype
= ntdevmode
->dithertype
;
4145 if (ntdevmode
->private != NULL
) {
4146 if ((devmode
->private=(uint8
*)memdup(ntdevmode
->private, ntdevmode
->driverextra
)) == NULL
)
4153 /****************************************************************************
4154 Create a DEVMODE struct. Returns malloced memory.
4155 ****************************************************************************/
4157 DEVICEMODE
*construct_dev_mode(int snum
)
4159 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4160 DEVICEMODE
*devmode
= NULL
;
4162 DEBUG(7,("construct_dev_mode\n"));
4164 DEBUGADD(8,("getting printer characteristics\n"));
4166 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
4169 if ( !printer
->info_2
->devmode
) {
4170 DEBUG(5, ("BONG! There was no device mode!\n"));
4174 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) == NULL
) {
4175 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4179 ZERO_STRUCTP(devmode
);
4181 DEBUGADD(8,("loading DEVICEMODE\n"));
4183 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4184 free_dev_mode( devmode
);
4189 free_a_printer(&printer
,2);
4194 /********************************************************************
4195 * construct_printer_info_2
4196 * fill a printer_info_2 struct
4197 ********************************************************************/
4199 static BOOL
construct_printer_info_2(Printer_entry
*print_hnd
, PRINTER_INFO_2
*printer
, int snum
)
4202 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4204 print_status_struct status
;
4206 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4209 count
= print_queue_length(snum
, &status
);
4211 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4212 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4213 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4214 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4215 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4217 if (*ntprinter
->info_2
->comment
== '\0')
4218 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4220 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4222 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4223 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4224 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4225 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4226 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4228 printer
->attributes
= ntprinter
->info_2
->attributes
;
4230 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4231 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4232 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4233 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4234 printer
->status
= nt_printq_status(status
.status
); /* status */
4235 printer
->cjobs
= count
; /* jobs */
4236 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4238 if((printer
->devmode
= construct_dev_mode(snum
)) == NULL
) {
4239 DEBUG(8, ("Returning NULL Devicemode!\n"));
4242 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4243 /* steal the printer info sec_desc structure. [badly done]. */
4244 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4245 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen memory. */
4246 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen memory. */
4247 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen memory. */
4250 printer
->secdesc
= NULL
;
4253 free_a_printer(&ntprinter
, 2);
4257 /********************************************************************
4258 * construct_printer_info_3
4259 * fill a printer_info_3 struct
4260 ********************************************************************/
4262 static BOOL
construct_printer_info_3(Printer_entry
*print_hnd
, PRINTER_INFO_3
**pp_printer
, int snum
)
4264 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4265 PRINTER_INFO_3
*printer
= NULL
;
4267 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4271 if ((printer
= (PRINTER_INFO_3
*)malloc(sizeof(PRINTER_INFO_3
))) == NULL
) {
4272 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4276 ZERO_STRUCTP(printer
);
4278 printer
->flags
= 4; /* These are the components of the SD we are returning. */
4279 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4280 /* steal the printer info sec_desc structure. [badly done]. */
4281 printer
->secdesc
= ntprinter
->info_2
->secdesc_buf
->sec
;
4285 * Set the flags for the components we are returning.
4288 if (printer
->secdesc
->owner_sid
)
4289 printer
->flags
|= OWNER_SECURITY_INFORMATION
;
4291 if (printer
->secdesc
->grp_sid
)
4292 printer
->flags
|= GROUP_SECURITY_INFORMATION
;
4294 if (printer
->secdesc
->dacl
)
4295 printer
->flags
|= DACL_SECURITY_INFORMATION
;
4297 if (printer
->secdesc
->sacl
)
4298 printer
->flags
|= SACL_SECURITY_INFORMATION
;
4301 ntprinter
->info_2
->secdesc_buf
->sec
= NULL
; /* Stolen the malloced memory. */
4302 ntprinter
->info_2
->secdesc_buf
->len
= 0; /* Stolen the malloced memory. */
4303 ntprinter
->info_2
->secdesc_buf
->max_len
= 0; /* Stolen the malloced memory. */
4306 free_a_printer(&ntprinter
, 2);
4308 *pp_printer
= printer
;
4312 /********************************************************************
4313 * construct_printer_info_4
4314 * fill a printer_info_4 struct
4315 ********************************************************************/
4317 static BOOL
construct_printer_info_4(Printer_entry
*print_hnd
, PRINTER_INFO_4
*printer
, int snum
)
4319 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4321 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4324 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4325 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4326 printer
->attributes
= ntprinter
->info_2
->attributes
;
4328 free_a_printer(&ntprinter
, 2);
4332 /********************************************************************
4333 * construct_printer_info_5
4334 * fill a printer_info_5 struct
4335 ********************************************************************/
4337 static BOOL
construct_printer_info_5(Printer_entry
*print_hnd
, PRINTER_INFO_5
*printer
, int snum
)
4339 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4341 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4344 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4345 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4346 printer
->attributes
= ntprinter
->info_2
->attributes
;
4348 /* these two are not used by NT+ according to MSDN */
4350 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4351 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4353 free_a_printer(&ntprinter
, 2);
4358 /********************************************************************
4359 * construct_printer_info_7
4360 * fill a printer_info_7 struct
4361 ********************************************************************/
4363 static BOOL
construct_printer_info_7(Printer_entry
*print_hnd
, PRINTER_INFO_7
*printer
, int snum
)
4365 char *guid_str
= NULL
;
4368 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4369 asprintf(&guid_str
, "{%s}", smb_uuid_string_static(guid
));
4370 strupper_m(guid_str
);
4371 init_unistr(&printer
->guid
, guid_str
);
4372 printer
->action
= SPOOL_DS_PUBLISH
;
4374 init_unistr(&printer
->guid
, "");
4375 printer
->action
= SPOOL_DS_UNPUBLISH
;
4381 /********************************************************************
4382 Spoolss_enumprinters.
4383 ********************************************************************/
4385 static WERROR
enum_all_printers_info_1(uint32 flags
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4389 int n_services
=lp_numservices();
4390 PRINTER_INFO_1
*tp
, *printers
=NULL
;
4391 PRINTER_INFO_1 current_prt
;
4393 DEBUG(4,("enum_all_printers_info_1\n"));
4395 for (snum
=0; snum
<n_services
; snum
++) {
4396 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4397 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4399 if (construct_printer_info_1(NULL
, flags
, ¤t_prt
, snum
)) {
4400 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_1
))) == NULL
) {
4401 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4402 SAFE_FREE(printers
);
4407 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4409 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4415 /* check the required size. */
4416 for (i
=0; i
<*returned
; i
++)
4417 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4419 if (!alloc_buffer_size(buffer
, *needed
))
4420 return WERR_INSUFFICIENT_BUFFER
;
4422 /* fill the buffer with the structures */
4423 for (i
=0; i
<*returned
; i
++)
4424 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4427 SAFE_FREE(printers
);
4429 if (*needed
> offered
) {
4431 return WERR_INSUFFICIENT_BUFFER
;
4437 /********************************************************************
4438 enum_all_printers_info_1_local.
4439 *********************************************************************/
4441 static WERROR
enum_all_printers_info_1_local(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4443 DEBUG(4,("enum_all_printers_info_1_local\n"));
4445 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4448 /********************************************************************
4449 enum_all_printers_info_1_name.
4450 *********************************************************************/
4452 static WERROR
enum_all_printers_info_1_name(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4456 DEBUG(4,("enum_all_printers_info_1_name\n"));
4458 if ((name
[0] == '\\') && (name
[1] == '\\'))
4461 if (is_myname_or_ipaddr(s
)) {
4462 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4465 return WERR_INVALID_NAME
;
4468 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4469 /********************************************************************
4470 enum_all_printers_info_1_remote.
4471 *********************************************************************/
4473 static WERROR
enum_all_printers_info_1_remote(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4475 PRINTER_INFO_1
*printer
;
4476 fstring printername
;
4479 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4481 /* JFM: currently it's more a place holder than anything else.
4482 * In the spooler world there is a notion of server registration.
4483 * the print servers are registered on the PDC (in the same domain)
4485 * We should have a TDB here. The registration is done thru an
4486 * undocumented RPC call.
4489 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4494 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", name
);
4495 slprintf(desc
, sizeof(desc
)-1,"%s", name
);
4496 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4498 init_unistr(&printer
->description
, desc
);
4499 init_unistr(&printer
->name
, printername
);
4500 init_unistr(&printer
->comment
, comment
);
4501 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4503 /* check the required size. */
4504 *needed
+= spoolss_size_printer_info_1(printer
);
4506 if (!alloc_buffer_size(buffer
, *needed
)) {
4508 return WERR_INSUFFICIENT_BUFFER
;
4511 /* fill the buffer with the structures */
4512 smb_io_printer_info_1("", buffer
, printer
, 0);
4517 if (*needed
> offered
) {
4519 return WERR_INSUFFICIENT_BUFFER
;
4527 /********************************************************************
4528 enum_all_printers_info_1_network.
4529 *********************************************************************/
4531 static WERROR
enum_all_printers_info_1_network(fstring name
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4535 DEBUG(4,("enum_all_printers_info_1_network\n"));
4537 /* If we respond to a enum_printers level 1 on our name with flags
4538 set to PRINTER_ENUM_REMOTE with a list of printers then these
4539 printers incorrectly appear in the APW browse list.
4540 Specifically the printers for the server appear at the workgroup
4541 level where all the other servers in the domain are
4542 listed. Windows responds to this call with a
4543 WERR_CAN_NOT_COMPLETE so we should do the same. */
4545 if (name
[0] == '\\' && name
[1] == '\\')
4548 if (is_myname_or_ipaddr(s
))
4549 return WERR_CAN_NOT_COMPLETE
;
4551 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4554 /********************************************************************
4555 * api_spoolss_enumprinters
4557 * called from api_spoolss_enumprinters (see this to understand)
4558 ********************************************************************/
4560 static WERROR
enum_all_printers_info_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4564 int n_services
=lp_numservices();
4565 PRINTER_INFO_2
*tp
, *printers
=NULL
;
4566 PRINTER_INFO_2 current_prt
;
4568 for (snum
=0; snum
<n_services
; snum
++) {
4569 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4570 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4572 if (construct_printer_info_2(NULL
, ¤t_prt
, snum
)) {
4573 if((tp
=Realloc(printers
, (*returned
+1)*sizeof(PRINTER_INFO_2
))) == NULL
) {
4574 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4575 SAFE_FREE(printers
);
4580 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
));
4581 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4587 /* check the required size. */
4588 for (i
=0; i
<*returned
; i
++)
4589 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4591 if (!alloc_buffer_size(buffer
, *needed
)) {
4592 for (i
=0; i
<*returned
; i
++) {
4593 free_devmode(printers
[i
].devmode
);
4595 SAFE_FREE(printers
);
4596 return WERR_INSUFFICIENT_BUFFER
;
4599 /* fill the buffer with the structures */
4600 for (i
=0; i
<*returned
; i
++)
4601 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4604 for (i
=0; i
<*returned
; i
++) {
4605 free_devmode(printers
[i
].devmode
);
4607 SAFE_FREE(printers
);
4609 if (*needed
> offered
) {
4611 return WERR_INSUFFICIENT_BUFFER
;
4617 /********************************************************************
4618 * handle enumeration of printers at level 1
4619 ********************************************************************/
4621 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4622 NEW_BUFFER
*buffer
, uint32 offered
,
4623 uint32
*needed
, uint32
*returned
)
4625 /* Not all the flags are equals */
4627 if (flags
& PRINTER_ENUM_LOCAL
)
4628 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4630 if (flags
& PRINTER_ENUM_NAME
)
4631 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4633 #if 0 /* JERRY - disabled for now */
4634 if (flags
& PRINTER_ENUM_REMOTE
)
4635 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4638 if (flags
& PRINTER_ENUM_NETWORK
)
4639 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4641 return WERR_OK
; /* NT4sp5 does that */
4644 /********************************************************************
4645 * handle enumeration of printers at level 2
4646 ********************************************************************/
4648 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4649 NEW_BUFFER
*buffer
, uint32 offered
,
4650 uint32
*needed
, uint32
*returned
)
4652 char *s
= servername
;
4654 if (flags
& PRINTER_ENUM_LOCAL
) {
4655 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4658 if (flags
& PRINTER_ENUM_NAME
) {
4659 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4661 if (is_myname_or_ipaddr(s
))
4662 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4664 return WERR_INVALID_NAME
;
4667 if (flags
& PRINTER_ENUM_REMOTE
)
4668 return WERR_UNKNOWN_LEVEL
;
4673 /********************************************************************
4674 * handle enumeration of printers at level 5
4675 ********************************************************************/
4677 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4678 NEW_BUFFER
*buffer
, uint32 offered
,
4679 uint32
*needed
, uint32
*returned
)
4681 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4685 /********************************************************************
4686 * api_spoolss_enumprinters
4688 * called from api_spoolss_enumprinters (see this to understand)
4689 ********************************************************************/
4691 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4693 uint32 flags
= q_u
->flags
;
4694 UNISTR2
*servername
= &q_u
->servername
;
4695 uint32 level
= q_u
->level
;
4696 NEW_BUFFER
*buffer
= NULL
;
4697 uint32 offered
= q_u
->offered
;
4698 uint32
*needed
= &r_u
->needed
;
4699 uint32
*returned
= &r_u
->returned
;
4703 /* that's an [in out] buffer */
4704 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4705 buffer
= r_u
->buffer
;
4707 DEBUG(4,("_spoolss_enumprinters\n"));
4714 * flags==PRINTER_ENUM_NAME
4715 * if name=="" then enumerates all printers
4716 * if name!="" then enumerate the printer
4717 * flags==PRINTER_ENUM_REMOTE
4718 * name is NULL, enumerate printers
4719 * Level 2: name!="" enumerates printers, name can't be NULL
4720 * Level 3: doesn't exist
4721 * Level 4: does a local registry lookup
4722 * Level 5: same as Level 2
4725 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4730 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4732 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4734 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4739 return WERR_UNKNOWN_LEVEL
;
4742 /****************************************************************************
4743 ****************************************************************************/
4745 static WERROR
getprinter_level_0(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4747 PRINTER_INFO_0
*printer
=NULL
;
4749 if((printer
=(PRINTER_INFO_0
*)malloc(sizeof(PRINTER_INFO_0
))) == NULL
)
4752 construct_printer_info_0(print_hnd
, printer
, snum
);
4754 /* check the required size. */
4755 *needed
+= spoolss_size_printer_info_0(printer
);
4757 if (!alloc_buffer_size(buffer
, *needed
)) {
4759 return WERR_INSUFFICIENT_BUFFER
;
4762 /* fill the buffer with the structures */
4763 smb_io_printer_info_0("", buffer
, printer
, 0);
4768 if (*needed
> offered
) {
4769 return WERR_INSUFFICIENT_BUFFER
;
4775 /****************************************************************************
4776 ****************************************************************************/
4778 static WERROR
getprinter_level_1(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4780 PRINTER_INFO_1
*printer
=NULL
;
4782 if((printer
=(PRINTER_INFO_1
*)malloc(sizeof(PRINTER_INFO_1
))) == NULL
)
4785 construct_printer_info_1(print_hnd
, PRINTER_ENUM_ICON8
, printer
, snum
);
4787 /* check the required size. */
4788 *needed
+= spoolss_size_printer_info_1(printer
);
4790 if (!alloc_buffer_size(buffer
, *needed
)) {
4792 return WERR_INSUFFICIENT_BUFFER
;
4795 /* fill the buffer with the structures */
4796 smb_io_printer_info_1("", buffer
, printer
, 0);
4801 if (*needed
> offered
) {
4802 return WERR_INSUFFICIENT_BUFFER
;
4808 /****************************************************************************
4809 ****************************************************************************/
4811 static WERROR
getprinter_level_2(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4813 PRINTER_INFO_2
*printer
=NULL
;
4815 if((printer
=(PRINTER_INFO_2
*)malloc(sizeof(PRINTER_INFO_2
)))==NULL
)
4818 construct_printer_info_2(print_hnd
, printer
, snum
);
4820 /* check the required size. */
4821 *needed
+= spoolss_size_printer_info_2(printer
);
4823 if (!alloc_buffer_size(buffer
, *needed
)) {
4824 free_printer_info_2(printer
);
4825 return WERR_INSUFFICIENT_BUFFER
;
4828 /* fill the buffer with the structures */
4829 if (!smb_io_printer_info_2("", buffer
, printer
, 0)) {
4830 free_printer_info_2(printer
);
4835 free_printer_info_2(printer
);
4837 if (*needed
> offered
) {
4838 return WERR_INSUFFICIENT_BUFFER
;
4844 /****************************************************************************
4845 ****************************************************************************/
4847 static WERROR
getprinter_level_3(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4849 PRINTER_INFO_3
*printer
=NULL
;
4851 if (!construct_printer_info_3(print_hnd
, &printer
, snum
))
4854 /* check the required size. */
4855 *needed
+= spoolss_size_printer_info_3(printer
);
4857 if (!alloc_buffer_size(buffer
, *needed
)) {
4858 free_printer_info_3(printer
);
4859 return WERR_INSUFFICIENT_BUFFER
;
4862 /* fill the buffer with the structures */
4863 smb_io_printer_info_3("", buffer
, printer
, 0);
4866 free_printer_info_3(printer
);
4868 if (*needed
> offered
) {
4869 return WERR_INSUFFICIENT_BUFFER
;
4875 /****************************************************************************
4876 ****************************************************************************/
4878 static WERROR
getprinter_level_4(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4880 PRINTER_INFO_4
*printer
=NULL
;
4882 if((printer
=(PRINTER_INFO_4
*)malloc(sizeof(PRINTER_INFO_4
)))==NULL
)
4885 if (!construct_printer_info_4(print_hnd
, printer
, snum
))
4888 /* check the required size. */
4889 *needed
+= spoolss_size_printer_info_4(printer
);
4891 if (!alloc_buffer_size(buffer
, *needed
)) {
4892 free_printer_info_4(printer
);
4893 return WERR_INSUFFICIENT_BUFFER
;
4896 /* fill the buffer with the structures */
4897 smb_io_printer_info_4("", buffer
, printer
, 0);
4900 free_printer_info_4(printer
);
4902 if (*needed
> offered
) {
4903 return WERR_INSUFFICIENT_BUFFER
;
4909 /****************************************************************************
4910 ****************************************************************************/
4912 static WERROR
getprinter_level_5(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4914 PRINTER_INFO_5
*printer
=NULL
;
4916 if((printer
=(PRINTER_INFO_5
*)malloc(sizeof(PRINTER_INFO_5
)))==NULL
)
4919 if (!construct_printer_info_5(print_hnd
, printer
, snum
))
4922 /* check the required size. */
4923 *needed
+= spoolss_size_printer_info_5(printer
);
4925 if (!alloc_buffer_size(buffer
, *needed
)) {
4926 free_printer_info_5(printer
);
4927 return WERR_INSUFFICIENT_BUFFER
;
4930 /* fill the buffer with the structures */
4931 smb_io_printer_info_5("", buffer
, printer
, 0);
4934 free_printer_info_5(printer
);
4936 if (*needed
> offered
) {
4937 return WERR_INSUFFICIENT_BUFFER
;
4943 static WERROR
getprinter_level_7(Printer_entry
*print_hnd
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4945 PRINTER_INFO_7
*printer
=NULL
;
4947 if((printer
=(PRINTER_INFO_7
*)malloc(sizeof(PRINTER_INFO_7
)))==NULL
)
4950 if (!construct_printer_info_7(print_hnd
, printer
, snum
))
4953 /* check the required size. */
4954 *needed
+= spoolss_size_printer_info_7(printer
);
4956 if (!alloc_buffer_size(buffer
, *needed
)) {
4957 free_printer_info_7(printer
);
4958 return WERR_INSUFFICIENT_BUFFER
;
4961 /* fill the buffer with the structures */
4962 smb_io_printer_info_7("", buffer
, printer
, 0);
4965 free_printer_info_7(printer
);
4967 if (*needed
> offered
) {
4968 return WERR_INSUFFICIENT_BUFFER
;
4974 /****************************************************************************
4975 ****************************************************************************/
4977 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4979 POLICY_HND
*handle
= &q_u
->handle
;
4980 uint32 level
= q_u
->level
;
4981 NEW_BUFFER
*buffer
= NULL
;
4982 uint32 offered
= q_u
->offered
;
4983 uint32
*needed
= &r_u
->needed
;
4984 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
4988 /* that's an [in out] buffer */
4989 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
4990 buffer
= r_u
->buffer
;
4994 if (!get_printer_snum(p
, handle
, &snum
))
4999 return getprinter_level_0(Printer
, snum
, buffer
, offered
, needed
);
5001 return getprinter_level_1(Printer
, snum
, buffer
, offered
, needed
);
5003 return getprinter_level_2(Printer
, snum
, buffer
, offered
, needed
);
5005 return getprinter_level_3(Printer
, snum
, buffer
, offered
, needed
);
5007 return getprinter_level_4(Printer
, snum
, buffer
, offered
, needed
);
5009 return getprinter_level_5(Printer
, snum
, buffer
, offered
, needed
);
5011 return getprinter_level_7(Printer
, snum
, buffer
, offered
, needed
);
5013 return WERR_UNKNOWN_LEVEL
;
5016 /********************************************************************
5017 * fill a DRIVER_INFO_1 struct
5018 ********************************************************************/
5020 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
5022 init_unistr( &info
->name
, driver
.info_3
->name
);
5025 /********************************************************************
5026 * construct_printer_driver_info_1
5027 ********************************************************************/
5029 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5031 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5032 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5034 ZERO_STRUCT(driver
);
5036 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5037 return WERR_INVALID_PRINTER_NAME
;
5039 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
5040 return WERR_UNKNOWN_PRINTER_DRIVER
;
5042 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
5044 free_a_printer(&printer
,2);
5049 /********************************************************************
5050 * construct_printer_driver_info_2
5051 * fill a printer_info_2 struct
5052 ********************************************************************/
5054 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5058 info
->version
=driver
.info_3
->cversion
;
5060 init_unistr( &info
->name
, driver
.info_3
->name
);
5061 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5064 if (strlen(driver
.info_3
->driverpath
)) {
5065 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5066 init_unistr( &info
->driverpath
, temp
);
5068 init_unistr( &info
->driverpath
, "" );
5070 if (strlen(driver
.info_3
->datafile
)) {
5071 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5072 init_unistr( &info
->datafile
, temp
);
5074 init_unistr( &info
->datafile
, "" );
5076 if (strlen(driver
.info_3
->configfile
)) {
5077 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5078 init_unistr( &info
->configfile
, temp
);
5080 init_unistr( &info
->configfile
, "" );
5083 /********************************************************************
5084 * construct_printer_driver_info_2
5085 * fill a printer_info_2 struct
5086 ********************************************************************/
5088 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5090 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5091 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5093 ZERO_STRUCT(printer
);
5094 ZERO_STRUCT(driver
);
5096 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5097 return WERR_INVALID_PRINTER_NAME
;
5099 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
)))
5100 return WERR_UNKNOWN_PRINTER_DRIVER
;
5102 fill_printer_driver_info_2(info
, driver
, servername
);
5104 free_a_printer(&printer
,2);
5109 /********************************************************************
5110 * copy a strings array and convert to UNICODE
5112 * convert an array of ascii string to a UNICODE string
5113 ********************************************************************/
5115 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
5123 DEBUG(6,("init_unistr_array\n"));
5134 v
= ""; /* hack to handle null lists */
5137 /* hack to allow this to be used in places other than when generating
5138 the list of dependent files */
5141 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
5145 DEBUGADD(6,("%d:%s:%lu\n", i
, line
, (unsigned long)strlen(line
)));
5147 /* add one extra unit16 for the second terminating NULL */
5149 if ( (tuary
=Realloc(*uni_array
, (j
+1+strlen(line
)+2)*sizeof(uint16
))) == NULL
) {
5150 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5158 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
5163 /* special case for ""; we need to add both NULL's here */
5165 (*uni_array
)[j
++]=0x0000;
5166 (*uni_array
)[j
]=0x0000;
5169 DEBUGADD(6,("last one:done\n"));
5171 /* return size of array in uint16's */
5176 /********************************************************************
5177 * construct_printer_info_3
5178 * fill a printer_info_3 struct
5179 ********************************************************************/
5181 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5187 info
->version
=driver
.info_3
->cversion
;
5189 init_unistr( &info
->name
, driver
.info_3
->name
);
5190 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5192 if (strlen(driver
.info_3
->driverpath
)) {
5193 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5194 init_unistr( &info
->driverpath
, temp
);
5196 init_unistr( &info
->driverpath
, "" );
5198 if (strlen(driver
.info_3
->datafile
)) {
5199 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5200 init_unistr( &info
->datafile
, temp
);
5202 init_unistr( &info
->datafile
, "" );
5204 if (strlen(driver
.info_3
->configfile
)) {
5205 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5206 init_unistr( &info
->configfile
, temp
);
5208 init_unistr( &info
->configfile
, "" );
5210 if (strlen(driver
.info_3
->helpfile
)) {
5211 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5212 init_unistr( &info
->helpfile
, temp
);
5214 init_unistr( &info
->helpfile
, "" );
5216 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5217 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5219 info
->dependentfiles
=NULL
;
5220 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5223 /********************************************************************
5224 * construct_printer_info_3
5225 * fill a printer_info_3 struct
5226 ********************************************************************/
5228 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5230 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5231 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5233 ZERO_STRUCT(driver
);
5235 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5236 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5237 if (!W_ERROR_IS_OK(status
))
5238 return WERR_INVALID_PRINTER_NAME
;
5240 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5241 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5246 * I put this code in during testing. Helpful when commenting out the
5247 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5248 * as win2k always queries the driver using an infor level of 6.
5249 * I've left it in (but ifdef'd out) because I'll probably
5250 * use it in experimentation again in the future. --jerry 22/01/2002
5253 if (!W_ERROR_IS_OK(status
)) {
5255 * Is this a W2k client ?
5258 /* Yes - try again with a WinNT driver. */
5260 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5261 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5265 if (!W_ERROR_IS_OK(status
)) {
5266 free_a_printer(&printer
,2);
5267 return WERR_UNKNOWN_PRINTER_DRIVER
;
5275 fill_printer_driver_info_3(info
, driver
, servername
);
5277 free_a_printer(&printer
,2);
5282 /********************************************************************
5283 * construct_printer_info_6
5284 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5285 ********************************************************************/
5287 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5293 memset(&nullstr
, '\0', sizeof(fstring
));
5295 info
->version
=driver
.info_3
->cversion
;
5297 init_unistr( &info
->name
, driver
.info_3
->name
);
5298 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5300 if (strlen(driver
.info_3
->driverpath
)) {
5301 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5302 init_unistr( &info
->driverpath
, temp
);
5304 init_unistr( &info
->driverpath
, "" );
5306 if (strlen(driver
.info_3
->datafile
)) {
5307 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5308 init_unistr( &info
->datafile
, temp
);
5310 init_unistr( &info
->datafile
, "" );
5312 if (strlen(driver
.info_3
->configfile
)) {
5313 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5314 init_unistr( &info
->configfile
, temp
);
5316 init_unistr( &info
->configfile
, "" );
5318 if (strlen(driver
.info_3
->helpfile
)) {
5319 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5320 init_unistr( &info
->helpfile
, temp
);
5322 init_unistr( &info
->helpfile
, "" );
5324 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5325 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5327 info
->dependentfiles
= NULL
;
5328 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5330 info
->previousdrivernames
=NULL
;
5331 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5333 info
->driver_date
.low
=0;
5334 info
->driver_date
.high
=0;
5337 info
->driver_version_low
=0;
5338 info
->driver_version_high
=0;
5340 init_unistr( &info
->mfgname
, "");
5341 init_unistr( &info
->oem_url
, "");
5342 init_unistr( &info
->hardware_id
, "");
5343 init_unistr( &info
->provider
, "");
5346 /********************************************************************
5347 * construct_printer_info_6
5348 * fill a printer_info_6 struct
5349 ********************************************************************/
5351 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5352 fstring servername
, fstring architecture
, uint32 version
)
5354 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5355 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5358 ZERO_STRUCT(driver
);
5360 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5362 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5364 if (!W_ERROR_IS_OK(status
))
5365 return WERR_INVALID_PRINTER_NAME
;
5367 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5369 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5371 if (!W_ERROR_IS_OK(status
))
5374 * Is this a W2k client ?
5378 free_a_printer(&printer
,2);
5379 return WERR_UNKNOWN_PRINTER_DRIVER
;
5382 /* Yes - try again with a WinNT driver. */
5384 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5385 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5386 if (!W_ERROR_IS_OK(status
)) {
5387 free_a_printer(&printer
,2);
5388 return WERR_UNKNOWN_PRINTER_DRIVER
;
5392 fill_printer_driver_info_6(info
, driver
, servername
);
5394 free_a_printer(&printer
,2);
5395 free_a_printer_driver(driver
, 3);
5400 /****************************************************************************
5401 ****************************************************************************/
5403 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5405 SAFE_FREE(info
->dependentfiles
);
5408 /****************************************************************************
5409 ****************************************************************************/
5411 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5413 SAFE_FREE(info
->dependentfiles
);
5417 /****************************************************************************
5418 ****************************************************************************/
5420 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5422 DRIVER_INFO_1
*info
=NULL
;
5425 if((info
=(DRIVER_INFO_1
*)malloc(sizeof(DRIVER_INFO_1
))) == NULL
)
5428 status
=construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5429 if (!W_ERROR_IS_OK(status
)) {
5434 /* check the required size. */
5435 *needed
+= spoolss_size_printer_driver_info_1(info
);
5437 if (!alloc_buffer_size(buffer
, *needed
)) {
5439 return WERR_INSUFFICIENT_BUFFER
;
5442 /* fill the buffer with the structures */
5443 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5448 if (*needed
> offered
)
5449 return WERR_INSUFFICIENT_BUFFER
;
5454 /****************************************************************************
5455 ****************************************************************************/
5457 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5459 DRIVER_INFO_2
*info
=NULL
;
5462 if((info
=(DRIVER_INFO_2
*)malloc(sizeof(DRIVER_INFO_2
))) == NULL
)
5465 status
=construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5466 if (!W_ERROR_IS_OK(status
)) {
5471 /* check the required size. */
5472 *needed
+= spoolss_size_printer_driver_info_2(info
);
5474 if (!alloc_buffer_size(buffer
, *needed
)) {
5476 return WERR_INSUFFICIENT_BUFFER
;
5479 /* fill the buffer with the structures */
5480 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5485 if (*needed
> offered
)
5486 return WERR_INSUFFICIENT_BUFFER
;
5491 /****************************************************************************
5492 ****************************************************************************/
5494 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5501 status
=construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5502 if (!W_ERROR_IS_OK(status
)) {
5506 /* check the required size. */
5507 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5509 if (!alloc_buffer_size(buffer
, *needed
)) {
5510 free_printer_driver_info_3(&info
);
5511 return WERR_INSUFFICIENT_BUFFER
;
5514 /* fill the buffer with the structures */
5515 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5517 free_printer_driver_info_3(&info
);
5519 if (*needed
> offered
)
5520 return WERR_INSUFFICIENT_BUFFER
;
5525 /****************************************************************************
5526 ****************************************************************************/
5528 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5535 status
=construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5536 if (!W_ERROR_IS_OK(status
)) {
5540 /* check the required size. */
5541 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5543 if (!alloc_buffer_size(buffer
, *needed
)) {
5544 free_printer_driver_info_6(&info
);
5545 return WERR_INSUFFICIENT_BUFFER
;
5548 /* fill the buffer with the structures */
5549 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5551 free_printer_driver_info_6(&info
);
5553 if (*needed
> offered
)
5554 return WERR_INSUFFICIENT_BUFFER
;
5559 /****************************************************************************
5560 ****************************************************************************/
5562 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5564 POLICY_HND
*handle
= &q_u
->handle
;
5565 UNISTR2
*uni_arch
= &q_u
->architecture
;
5566 uint32 level
= q_u
->level
;
5567 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5568 NEW_BUFFER
*buffer
= NULL
;
5569 uint32 offered
= q_u
->offered
;
5570 uint32
*needed
= &r_u
->needed
;
5571 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5572 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5573 Printer_entry
*printer
;
5576 fstring architecture
;
5579 /* that's an [in out] buffer */
5580 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
5581 buffer
= r_u
->buffer
;
5583 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5585 if ( !(printer
= find_printer_index_by_hnd( p
, handle
)) ) {
5586 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5587 return WERR_INVALID_PRINTER_NAME
;
5591 *servermajorversion
= 0;
5592 *serverminorversion
= 0;
5594 fstrcpy(servername
, get_server_name( printer
));
5595 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5597 if (!get_printer_snum(p
, handle
, &snum
))
5602 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5604 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5606 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5608 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5611 /* apparently this call is the equivalent of
5612 EnumPrinterDataEx() for the DsDriver key */
5617 return WERR_UNKNOWN_LEVEL
;
5620 /****************************************************************************
5621 ****************************************************************************/
5623 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5625 POLICY_HND
*handle
= &q_u
->handle
;
5627 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5630 DEBUG(3,("Error in startpageprinter printer handle\n"));
5634 Printer
->page_started
=True
;
5638 /****************************************************************************
5639 ****************************************************************************/
5641 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5643 POLICY_HND
*handle
= &q_u
->handle
;
5646 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5649 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5653 if (!get_printer_snum(p
, handle
, &snum
))
5656 Printer
->page_started
=False
;
5657 print_job_endpage(snum
, Printer
->jobid
);
5662 /********************************************************************
5663 * api_spoolss_getprinter
5664 * called from the spoolss dispatcher
5666 ********************************************************************/
5668 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5670 POLICY_HND
*handle
= &q_u
->handle
;
5671 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5672 uint32
*jobid
= &r_u
->jobid
;
5674 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5678 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5679 struct current_user user
;
5682 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5686 get_current_user(&user
, p
);
5689 * a nice thing with NT is it doesn't listen to what you tell it.
5690 * when asked to send _only_ RAW datas, it tries to send datas
5693 * So I add checks like in NT Server ...
5696 if (info_1
->p_datatype
!= 0) {
5697 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5698 if (strcmp(datatype
, "RAW") != 0) {
5700 return WERR_INVALID_DATATYPE
;
5704 /* get the share number of the printer */
5705 if (!get_printer_snum(p
, handle
, &snum
)) {
5709 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5711 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5713 /* An error occured in print_job_start() so return an appropriate
5716 if (Printer
->jobid
== -1) {
5717 return map_werror_from_unix(errno
);
5720 Printer
->document_started
=True
;
5721 (*jobid
) = Printer
->jobid
;
5726 /********************************************************************
5727 * api_spoolss_getprinter
5728 * called from the spoolss dispatcher
5730 ********************************************************************/
5732 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5734 POLICY_HND
*handle
= &q_u
->handle
;
5736 return _spoolss_enddocprinter_internal(p
, handle
);
5739 /****************************************************************************
5740 ****************************************************************************/
5742 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5744 POLICY_HND
*handle
= &q_u
->handle
;
5745 uint32 buffer_size
= q_u
->buffer_size
;
5746 uint8
*buffer
= q_u
->buffer
;
5747 uint32
*buffer_written
= &q_u
->buffer_size2
;
5749 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5752 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5753 r_u
->buffer_written
= q_u
->buffer_size2
;
5757 if (!get_printer_snum(p
, handle
, &snum
))
5760 (*buffer_written
) = print_job_write(snum
, Printer
->jobid
, (char *)buffer
, buffer_size
);
5761 if (*buffer_written
== -1) {
5762 r_u
->buffer_written
= 0;
5763 if (errno
== ENOSPC
)
5764 return WERR_NO_SPOOL_SPACE
;
5766 return WERR_ACCESS_DENIED
;
5769 r_u
->buffer_written
= q_u
->buffer_size2
;
5774 /********************************************************************
5775 * api_spoolss_getprinter
5776 * called from the spoolss dispatcher
5778 ********************************************************************/
5780 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5783 struct current_user user
;
5785 WERROR errcode
= WERR_BADFUNC
;
5786 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5788 get_current_user(&user
, p
);
5791 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5795 if (!get_printer_snum(p
, handle
, &snum
))
5799 case PRINTER_CONTROL_PAUSE
:
5800 if (print_queue_pause(&user
, snum
, &errcode
)) {
5804 case PRINTER_CONTROL_RESUME
:
5805 case PRINTER_CONTROL_UNPAUSE
:
5806 if (print_queue_resume(&user
, snum
, &errcode
)) {
5810 case PRINTER_CONTROL_PURGE
:
5811 if (print_queue_purge(&user
, snum
, &errcode
)) {
5816 return WERR_UNKNOWN_LEVEL
;
5822 /********************************************************************
5823 * api_spoolss_abortprinter
5824 * From MSDN: "Deletes printer's spool file if printer is configured
5826 ********************************************************************/
5828 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5830 POLICY_HND
*handle
= &q_u
->handle
;
5831 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5833 struct current_user user
;
5834 WERROR errcode
= WERR_OK
;
5837 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5841 if (!get_printer_snum(p
, handle
, &snum
))
5844 get_current_user( &user
, p
);
5846 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5851 /********************************************************************
5852 * called by spoolss_api_setprinter
5853 * when updating a printer description
5854 ********************************************************************/
5856 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5857 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5858 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5860 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5861 struct current_user user
;
5865 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5867 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5868 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5869 OUR_HANDLE(handle
)));
5871 result
= WERR_BADFID
;
5875 /* NT seems to like setting the security descriptor even though
5876 nothing may have actually changed. */
5878 nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
);
5880 if (DEBUGLEVEL
>= 10) {
5884 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5885 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5886 PRINTERNAME(snum
), the_acl
->num_aces
));
5888 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5891 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5893 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5894 the_acl
->ace
[i
].info
.mask
));
5897 the_acl
= secdesc_ctr
->sec
->dacl
;
5900 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5901 PRINTERNAME(snum
), the_acl
->num_aces
));
5903 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5906 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5908 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5909 the_acl
->ace
[i
].info
.mask
));
5912 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5916 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5918 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5923 /* Work out which user is performing the operation */
5925 get_current_user(&user
, p
);
5927 /* Check the user has permissions to change the security
5928 descriptor. By experimentation with two NT machines, the user
5929 requires Full Access to the printer to change security
5932 if (!print_access_check(&user
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
5933 result
= WERR_ACCESS_DENIED
;
5937 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5944 /********************************************************************
5945 Canonicalize printer info from a client
5947 ATTN: It does not matter what we set the servername to hear
5948 since we do the necessary work in get_a_printer() to set it to
5949 the correct value based on what the client sent in the
5950 _spoolss_open_printer_ex().
5951 ********************************************************************/
5953 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5955 fstring printername
;
5958 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5959 "portname=%s drivername=%s comment=%s location=%s\n",
5960 info
->servername
, info
->printername
, info
->sharename
,
5961 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5963 /* we force some elements to "correct" values */
5964 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5965 fstrcpy(info
->sharename
, lp_servicename(snum
));
5967 /* make sure printername is in \\server\printername format */
5969 fstrcpy( printername
, info
->printername
);
5971 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5972 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5976 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5977 global_myname(), p
);
5979 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5980 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5987 /****************************************************************************
5988 ****************************************************************************/
5990 static BOOL
add_printer_hook(NT_PRINTER_INFO_LEVEL
*printer
)
5992 extern userdom_struct current_user_info
;
5993 char *cmd
= lp_addprinter_cmd();
5999 fstring remote_machine
= "%m";
6001 standard_sub_basic(current_user_info
.smb_name
, remote_machine
,sizeof(remote_machine
));
6003 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6004 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
6005 printer
->info_2
->portname
, printer
->info_2
->drivername
,
6006 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
6008 DEBUG(10,("Running [%s]\n", command
));
6009 ret
= smbrun(command
, &fd
);
6010 DEBUGADD(10,("returned [%d]\n", ret
));
6019 /* Get lines and convert them back to dos-codepage */
6020 qlines
= fd_lines_load(fd
, &numlines
);
6021 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6025 /* Set the portname to what the script says the portname should be. */
6026 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
6027 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6029 /* Send SIGHUP to process group... is there a better way? */
6032 /* reload our services immediately */
6033 reload_services( False
);
6036 file_lines_free(qlines
);
6040 /********************************************************************
6041 * Called by spoolss_api_setprinter
6042 * when updating a printer description.
6043 ********************************************************************/
6045 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
6046 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6047 DEVICEMODE
*devmode
)
6050 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6051 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6056 DEBUG(8,("update_printer\n"));
6061 result
= WERR_BADFID
;
6065 if (!get_printer_snum(p
, handle
, &snum
)) {
6066 result
= WERR_BADFID
;
6070 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6071 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6072 result
= WERR_BADFID
;
6076 DEBUGADD(8,("Converting info_2 struct\n"));
6079 * convert_printer_info converts the incoming
6080 * info from the client and overwrites the info
6081 * just read from the tdb in the pointer 'printer'.
6084 if (!convert_printer_info(info
, printer
, level
)) {
6085 result
= WERR_NOMEM
;
6090 /* we have a valid devmode
6091 convert it and link it*/
6093 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6094 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6095 &printer
->info_2
->devmode
)) {
6096 result
= WERR_NOMEM
;
6101 /* Do sanity check on the requested changes for Samba */
6103 if (!check_printer_ok(printer
->info_2
, snum
)) {
6104 result
= WERR_INVALID_PARAM
;
6108 /* FIXME!!! If the driver has changed we really should verify that
6109 it is installed before doing much else --jerry */
6111 /* Check calling user has permission to update printer description */
6113 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6114 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6115 result
= WERR_ACCESS_DENIED
;
6119 /* Call addprinter hook */
6120 /* Check changes to see if this is really needed */
6122 if ( *lp_addprinter_cmd()
6123 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6124 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6125 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6126 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6128 if ( !add_printer_hook(printer
) ) {
6129 result
= WERR_ACCESS_DENIED
;
6134 * make sure we actually reload the services after
6135 * this as smb.conf could have a new section in it
6136 * .... shouldn't .... but could
6138 reload_services(False
);
6142 * When a *new* driver is bound to a printer, the drivername is used to
6143 * lookup previously saved driver initialization info, which is then
6144 * bound to the printer, simulating what happens in the Windows arch.
6146 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6148 if (!set_driver_init(printer
, 2))
6150 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6151 printer
->info_2
->drivername
));
6154 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6155 printer
->info_2
->drivername
));
6157 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6161 * flag which changes actually occured. This is a small subset of
6162 * all the possible changes. We also have to update things in the
6166 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6167 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6168 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6169 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6171 notify_printer_comment(snum
, printer
->info_2
->comment
);
6174 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6175 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6176 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6177 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6179 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6182 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6185 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6188 pname
= printer
->info_2
->printername
;
6191 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6192 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6193 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6195 notify_printer_printername( snum
, pname
);
6198 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6199 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6200 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6201 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6203 notify_printer_port(snum
, printer
->info_2
->portname
);
6206 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6207 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6208 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6209 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6211 notify_printer_location(snum
, printer
->info_2
->location
);
6214 /* here we need to update some more DsSpooler keys */
6215 /* uNCName, serverName, shortServerName */
6217 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6218 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6219 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6220 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6221 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6223 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6224 global_myname(), printer
->info_2
->sharename
);
6225 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6226 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6227 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6229 /* Update printer info */
6230 result
= mod_a_printer(printer
, 2);
6233 free_a_printer(&printer
, 2);
6234 free_a_printer(&old_printer
, 2);
6240 /****************************************************************************
6241 ****************************************************************************/
6242 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6243 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6246 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6248 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6250 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6255 if (!get_printer_snum(p
, handle
, &snum
))
6258 nt_printer_publish(Printer
, snum
, info7
->action
);
6262 return WERR_UNKNOWN_LEVEL
;
6265 /****************************************************************************
6266 ****************************************************************************/
6268 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6270 POLICY_HND
*handle
= &q_u
->handle
;
6271 uint32 level
= q_u
->level
;
6272 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6273 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6274 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6275 uint32 command
= q_u
->command
;
6278 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6281 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6285 /* check the level */
6288 return control_printer(handle
, command
, p
);
6290 result
= update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6291 if (!W_ERROR_IS_OK(result
))
6294 result
= update_printer_sec(handle
, level
, info
, p
, secdesc_ctr
);
6297 return update_printer_sec(handle
, level
, info
, p
,
6300 return publish_or_unpublish_printer(p
, handle
, info
);
6302 return WERR_UNKNOWN_LEVEL
;
6306 /****************************************************************************
6307 ****************************************************************************/
6309 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6311 POLICY_HND
*handle
= &q_u
->handle
;
6312 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6315 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6319 if (Printer
->notify
.client_connected
==True
) {
6322 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
)
6324 else if ( (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
) &&
6325 !get_printer_snum(p
, handle
, &snum
) )
6328 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6331 Printer
->notify
.flags
=0;
6332 Printer
->notify
.options
=0;
6333 Printer
->notify
.localmachine
[0]='\0';
6334 Printer
->notify
.printerlocal
=0;
6335 if (Printer
->notify
.option
)
6336 free_spool_notify_option(&Printer
->notify
.option
);
6337 Printer
->notify
.client_connected
=False
;
6342 /****************************************************************************
6343 ****************************************************************************/
6345 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6347 /* that's an [in out] buffer (despite appearences to the contrary) */
6348 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6351 return WERR_INVALID_PARAM
; /* this is what a NT server
6352 returns for AddJob. AddJob
6353 must fail on non-local
6357 /****************************************************************************
6358 ****************************************************************************/
6360 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
6361 int position
, int snum
,
6362 NT_PRINTER_INFO_LEVEL
*ntprinter
)
6366 t
=gmtime(&queue
->time
);
6368 job_info
->jobid
=queue
->job
;
6369 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6370 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6371 init_unistr(&job_info
->username
, queue
->fs_user
);
6372 init_unistr(&job_info
->document
, queue
->fs_file
);
6373 init_unistr(&job_info
->datatype
, "RAW");
6374 init_unistr(&job_info
->text_status
, "");
6375 job_info
->status
=nt_printj_status(queue
->status
);
6376 job_info
->priority
=queue
->priority
;
6377 job_info
->position
=position
;
6378 job_info
->totalpages
=queue
->page_count
;
6379 job_info
->pagesprinted
=0;
6381 make_systemtime(&job_info
->submitted
, t
);
6384 /****************************************************************************
6385 ****************************************************************************/
6387 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
6388 int position
, int snum
,
6389 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6390 DEVICEMODE
*devmode
)
6394 t
=gmtime(&queue
->time
);
6396 job_info
->jobid
=queue
->job
;
6398 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6400 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6401 init_unistr(&job_info
->username
, queue
->fs_user
);
6402 init_unistr(&job_info
->document
, queue
->fs_file
);
6403 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6404 init_unistr(&job_info
->datatype
, "RAW");
6405 init_unistr(&job_info
->printprocessor
, "winprint");
6406 init_unistr(&job_info
->parameters
, "");
6407 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6408 init_unistr(&job_info
->text_status
, "");
6410 /* and here the security descriptor */
6412 job_info
->status
=nt_printj_status(queue
->status
);
6413 job_info
->priority
=queue
->priority
;
6414 job_info
->position
=position
;
6415 job_info
->starttime
=0;
6416 job_info
->untiltime
=0;
6417 job_info
->totalpages
=queue
->page_count
;
6418 job_info
->size
=queue
->size
;
6419 make_systemtime(&(job_info
->submitted
), t
);
6420 job_info
->timeelapsed
=0;
6421 job_info
->pagesprinted
=0;
6423 job_info
->devmode
= devmode
;
6428 /****************************************************************************
6429 Enumjobs at level 1.
6430 ****************************************************************************/
6432 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
6433 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6434 NEW_BUFFER
*buffer
, uint32 offered
,
6435 uint32
*needed
, uint32
*returned
)
6440 info
=(JOB_INFO_1
*)malloc(*returned
*sizeof(JOB_INFO_1
));
6447 for (i
=0; i
<*returned
; i
++)
6448 fill_job_info_1( &info
[i
], &queue
[i
], i
, snum
, ntprinter
);
6452 /* check the required size. */
6453 for (i
=0; i
<*returned
; i
++)
6454 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6456 if (!alloc_buffer_size(buffer
, *needed
)) {
6458 return WERR_INSUFFICIENT_BUFFER
;
6461 /* fill the buffer with the structures */
6462 for (i
=0; i
<*returned
; i
++)
6463 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6468 if (*needed
> offered
) {
6470 return WERR_INSUFFICIENT_BUFFER
;
6476 /****************************************************************************
6477 Enumjobs at level 2.
6478 ****************************************************************************/
6480 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
6481 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6482 NEW_BUFFER
*buffer
, uint32 offered
,
6483 uint32
*needed
, uint32
*returned
)
6485 JOB_INFO_2
*info
= NULL
;
6488 DEVICEMODE
*devmode
= NULL
;
6490 info
=(JOB_INFO_2
*)malloc(*returned
*sizeof(JOB_INFO_2
));
6493 result
= WERR_NOMEM
;
6497 /* this should not be a failure condition if the devmode is NULL */
6499 devmode
= construct_dev_mode(snum
);
6501 for (i
=0; i
<*returned
; i
++)
6502 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
,
6505 free_a_printer(&ntprinter
, 2);
6508 /* check the required size. */
6509 for (i
=0; i
<*returned
; i
++)
6510 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6512 if (*needed
> offered
) {
6514 result
= WERR_INSUFFICIENT_BUFFER
;
6518 if (!alloc_buffer_size(buffer
, *needed
)) {
6520 result
= WERR_INSUFFICIENT_BUFFER
;
6524 /* fill the buffer with the structures */
6525 for (i
=0; i
<*returned
; i
++)
6526 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6531 free_a_printer(&ntprinter
, 2);
6532 free_devmode(devmode
);
6540 /****************************************************************************
6542 ****************************************************************************/
6544 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6546 POLICY_HND
*handle
= &q_u
->handle
;
6547 uint32 level
= q_u
->level
;
6548 NEW_BUFFER
*buffer
= NULL
;
6549 uint32 offered
= q_u
->offered
;
6550 uint32
*needed
= &r_u
->needed
;
6551 uint32
*returned
= &r_u
->returned
;
6553 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6555 print_status_struct prt_status
;
6556 print_queue_struct
*queue
=NULL
;
6558 /* that's an [in out] buffer */
6559 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6560 buffer
= r_u
->buffer
;
6562 DEBUG(4,("_spoolss_enumjobs\n"));
6567 /* lookup the printer snum and tdb entry */
6569 if (!get_printer_snum(p
, handle
, &snum
))
6572 wret
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6573 if ( !W_ERROR_IS_OK(wret
) )
6576 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6577 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6579 if (*returned
== 0) {
6586 wret
= enumjobs_level1(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6589 wret
= enumjobs_level2(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6594 wret
= WERR_UNKNOWN_LEVEL
;
6597 free_a_printer( &ntprinter
, 2 );
6601 /****************************************************************************
6602 ****************************************************************************/
6604 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6609 /****************************************************************************
6610 ****************************************************************************/
6612 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6614 POLICY_HND
*handle
= &q_u
->handle
;
6615 uint32 jobid
= q_u
->jobid
;
6616 uint32 command
= q_u
->command
;
6618 struct current_user user
;
6620 WERROR errcode
= WERR_BADFUNC
;
6622 if (!get_printer_snum(p
, handle
, &snum
)) {
6626 if (!print_job_exists(lp_const_servicename(snum
), jobid
)) {
6627 return WERR_INVALID_PRINTER_NAME
;
6630 get_current_user(&user
, p
);
6633 case JOB_CONTROL_CANCEL
:
6634 case JOB_CONTROL_DELETE
:
6635 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6639 case JOB_CONTROL_PAUSE
:
6640 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6644 case JOB_CONTROL_RESTART
:
6645 case JOB_CONTROL_RESUME
:
6646 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6651 return WERR_UNKNOWN_LEVEL
;
6657 /****************************************************************************
6658 Enumerates all printer drivers at level 1.
6659 ****************************************************************************/
6661 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6666 fstring
*list
= NULL
;
6668 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6669 DRIVER_INFO_1
*tdi1
, *driver_info_1
=NULL
;
6673 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6675 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6676 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6682 if((tdi1
=(DRIVER_INFO_1
*)Realloc(driver_info_1
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_1
))) == NULL
) {
6683 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6684 SAFE_FREE(driver_info_1
);
6688 else driver_info_1
= tdi1
;
6691 for (i
=0; i
<ndrivers
; i
++) {
6693 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6694 ZERO_STRUCT(driver
);
6695 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6696 architecture
, version
);
6697 if (!W_ERROR_IS_OK(status
)) {
6701 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6702 free_a_printer_driver(driver
, 3);
6705 *returned
+=ndrivers
;
6709 /* check the required size. */
6710 for (i
=0; i
<*returned
; i
++) {
6711 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6712 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6715 if (!alloc_buffer_size(buffer
, *needed
)) {
6716 SAFE_FREE(driver_info_1
);
6717 return WERR_INSUFFICIENT_BUFFER
;
6720 /* fill the buffer with the driver structures */
6721 for (i
=0; i
<*returned
; i
++) {
6722 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6723 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6726 SAFE_FREE(driver_info_1
);
6728 if (*needed
> offered
) {
6730 return WERR_INSUFFICIENT_BUFFER
;
6736 /****************************************************************************
6737 Enumerates all printer drivers at level 2.
6738 ****************************************************************************/
6740 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6745 fstring
*list
= NULL
;
6747 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6748 DRIVER_INFO_2
*tdi2
, *driver_info_2
=NULL
;
6752 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6754 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6755 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6761 if((tdi2
=(DRIVER_INFO_2
*)Realloc(driver_info_2
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_2
))) == NULL
) {
6762 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6763 SAFE_FREE(driver_info_2
);
6767 else driver_info_2
= tdi2
;
6770 for (i
=0; i
<ndrivers
; i
++) {
6773 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6774 ZERO_STRUCT(driver
);
6775 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6776 architecture
, version
);
6777 if (!W_ERROR_IS_OK(status
)) {
6781 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6782 free_a_printer_driver(driver
, 3);
6785 *returned
+=ndrivers
;
6789 /* check the required size. */
6790 for (i
=0; i
<*returned
; i
++) {
6791 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6792 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6795 if (!alloc_buffer_size(buffer
, *needed
)) {
6796 SAFE_FREE(driver_info_2
);
6797 return WERR_INSUFFICIENT_BUFFER
;
6800 /* fill the buffer with the form structures */
6801 for (i
=0; i
<*returned
; i
++) {
6802 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6803 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6806 SAFE_FREE(driver_info_2
);
6808 if (*needed
> offered
) {
6810 return WERR_INSUFFICIENT_BUFFER
;
6816 /****************************************************************************
6817 Enumerates all printer drivers at level 3.
6818 ****************************************************************************/
6820 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6825 fstring
*list
= NULL
;
6827 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6828 DRIVER_INFO_3
*tdi3
, *driver_info_3
=NULL
;
6832 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6834 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6835 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6841 if((tdi3
=(DRIVER_INFO_3
*)Realloc(driver_info_3
, (*returned
+ndrivers
) * sizeof(DRIVER_INFO_3
))) == NULL
) {
6842 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6843 SAFE_FREE(driver_info_3
);
6847 else driver_info_3
= tdi3
;
6850 for (i
=0; i
<ndrivers
; i
++) {
6853 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6854 ZERO_STRUCT(driver
);
6855 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6856 architecture
, version
);
6857 if (!W_ERROR_IS_OK(status
)) {
6861 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6862 free_a_printer_driver(driver
, 3);
6865 *returned
+=ndrivers
;
6869 /* check the required size. */
6870 for (i
=0; i
<*returned
; i
++) {
6871 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6872 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6875 if (!alloc_buffer_size(buffer
, *needed
)) {
6876 SAFE_FREE(driver_info_3
);
6877 return WERR_INSUFFICIENT_BUFFER
;
6880 /* fill the buffer with the driver structures */
6881 for (i
=0; i
<*returned
; i
++) {
6882 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6883 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6886 for (i
=0; i
<*returned
; i
++)
6887 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6889 SAFE_FREE(driver_info_3
);
6891 if (*needed
> offered
) {
6893 return WERR_INSUFFICIENT_BUFFER
;
6899 /****************************************************************************
6900 Enumerates all printer drivers.
6901 ****************************************************************************/
6903 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6905 uint32 level
= q_u
->level
;
6906 NEW_BUFFER
*buffer
= NULL
;
6907 uint32 offered
= q_u
->offered
;
6908 uint32
*needed
= &r_u
->needed
;
6909 uint32
*returned
= &r_u
->returned
;
6911 fstring
*list
= NULL
;
6913 fstring architecture
;
6915 /* that's an [in out] buffer */
6916 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6917 buffer
= r_u
->buffer
;
6919 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6923 unistr2_to_ascii(architecture
, &q_u
->environment
, sizeof(architecture
)-1);
6924 unistr2_to_ascii(servername
, &q_u
->name
, sizeof(servername
)-1);
6926 if ( !is_myname_or_ipaddr( servername
) )
6927 return WERR_UNKNOWN_PRINTER_DRIVER
;
6931 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6933 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6935 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6939 return WERR_UNKNOWN_LEVEL
;
6943 /****************************************************************************
6944 ****************************************************************************/
6946 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
6948 form
->flag
=list
->flag
;
6949 init_unistr(&form
->name
, list
->name
);
6950 form
->width
=list
->width
;
6951 form
->length
=list
->length
;
6952 form
->left
=list
->left
;
6953 form
->top
=list
->top
;
6954 form
->right
=list
->right
;
6955 form
->bottom
=list
->bottom
;
6958 /****************************************************************************
6959 ****************************************************************************/
6961 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
6963 uint32 level
= q_u
->level
;
6964 NEW_BUFFER
*buffer
= NULL
;
6965 uint32 offered
= q_u
->offered
;
6966 uint32
*needed
= &r_u
->needed
;
6967 uint32
*numofforms
= &r_u
->numofforms
;
6968 uint32 numbuiltinforms
;
6970 nt_forms_struct
*list
=NULL
;
6971 nt_forms_struct
*builtinlist
=NULL
;
6976 /* that's an [in out] buffer */
6977 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
6978 buffer
= r_u
->buffer
;
6980 DEBUG(4,("_spoolss_enumforms\n"));
6981 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
6982 DEBUGADD(5,("Info level [%d]\n", level
));
6984 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
6985 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
6986 *numofforms
= get_ntforms(&list
);
6987 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
6988 *numofforms
+= numbuiltinforms
;
6990 if (*numofforms
== 0) return WERR_NO_MORE_ITEMS
;
6994 if ((forms_1
=(FORM_1
*)malloc(*numofforms
* sizeof(FORM_1
))) == NULL
) {
6999 /* construct the list of form structures */
7000 for (i
=0; i
<numbuiltinforms
; i
++) {
7001 DEBUGADD(6,("Filling form number [%d]\n",i
));
7002 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
7005 SAFE_FREE(builtinlist
);
7007 for (; i
<*numofforms
; i
++) {
7008 DEBUGADD(6,("Filling form number [%d]\n",i
));
7009 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
7014 /* check the required size. */
7015 for (i
=0; i
<numbuiltinforms
; i
++) {
7016 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7017 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7019 for (; i
<*numofforms
; i
++) {
7020 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7021 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7024 *needed
=buffer_size
;
7026 if (!alloc_buffer_size(buffer
, buffer_size
)){
7028 return WERR_INSUFFICIENT_BUFFER
;
7031 /* fill the buffer with the form structures */
7032 for (i
=0; i
<numbuiltinforms
; i
++) {
7033 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7034 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7036 for (; i
<*numofforms
; i
++) {
7037 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7038 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7043 if (*needed
> offered
) {
7045 return WERR_INSUFFICIENT_BUFFER
;
7052 SAFE_FREE(builtinlist
);
7053 return WERR_UNKNOWN_LEVEL
;
7058 /****************************************************************************
7059 ****************************************************************************/
7061 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
7063 uint32 level
= q_u
->level
;
7064 UNISTR2
*uni_formname
= &q_u
->formname
;
7065 NEW_BUFFER
*buffer
= NULL
;
7066 uint32 offered
= q_u
->offered
;
7067 uint32
*needed
= &r_u
->needed
;
7069 nt_forms_struct
*list
=NULL
;
7070 nt_forms_struct builtin_form
;
7075 int numofforms
=0, i
=0;
7077 /* that's an [in out] buffer */
7078 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7079 buffer
= r_u
->buffer
;
7081 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
7083 DEBUG(4,("_spoolss_getform\n"));
7084 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7085 DEBUGADD(5,("Info level [%d]\n", level
));
7087 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
7088 if (!foundBuiltin
) {
7089 numofforms
= get_ntforms(&list
);
7090 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
7092 if (numofforms
== 0)
7099 fill_form_1(&form_1
, &builtin_form
);
7102 /* Check if the requested name is in the list of form structures */
7103 for (i
=0; i
<numofforms
; i
++) {
7105 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
7107 if (strequal(form_name
, list
[i
].name
)) {
7108 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
7109 fill_form_1(&form_1
, &list
[i
]);
7115 if (i
== numofforms
) {
7119 /* check the required size. */
7121 *needed
=spoolss_size_form_1(&form_1
);
7123 if (!alloc_buffer_size(buffer
, buffer_size
)){
7124 return WERR_INSUFFICIENT_BUFFER
;
7127 if (*needed
> offered
) {
7128 return WERR_INSUFFICIENT_BUFFER
;
7131 /* fill the buffer with the form structures */
7132 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
7133 smb_io_form_1("", buffer
, &form_1
, 0);
7139 return WERR_UNKNOWN_LEVEL
;
7143 /****************************************************************************
7144 ****************************************************************************/
7146 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
7148 init_unistr(&port
->port_name
, name
);
7151 /****************************************************************************
7152 ****************************************************************************/
7154 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
7156 init_unistr(&port
->port_name
, name
);
7157 init_unistr(&port
->monitor_name
, "Local Monitor");
7158 init_unistr(&port
->description
, "Local Port");
7159 port
->port_type
=PORT_TYPE_WRITE
;
7163 /****************************************************************************
7165 ****************************************************************************/
7167 static WERROR
enumports_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7169 PORT_INFO_1
*ports
=NULL
;
7172 if (*lp_enumports_cmd()) {
7173 char *cmd
= lp_enumports_cmd();
7180 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
7182 DEBUG(10,("Running [%s]\n", command
));
7183 ret
= smbrun(command
, &fd
);
7184 DEBUG(10,("Returned [%d]\n", ret
));
7188 /* Is this the best error to return here? */
7189 return WERR_ACCESS_DENIED
;
7193 qlines
= fd_lines_load(fd
, &numlines
);
7194 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7198 if((ports
=(PORT_INFO_1
*)malloc( numlines
* sizeof(PORT_INFO_1
) )) == NULL
) {
7199 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7200 dos_errstr(WERR_NOMEM
)));
7201 file_lines_free(qlines
);
7205 for (i
=0; i
<numlines
; i
++) {
7206 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7207 fill_port_1(&ports
[i
], qlines
[i
]);
7210 file_lines_free(qlines
);
7213 *returned
= numlines
;
7216 *returned
= 1; /* Sole Samba port returned. */
7218 if((ports
=(PORT_INFO_1
*)malloc( sizeof(PORT_INFO_1
) )) == NULL
)
7221 DEBUG(10,("enumports_level_1: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7223 fill_port_1(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7226 /* check the required size. */
7227 for (i
=0; i
<*returned
; i
++) {
7228 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7229 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7232 if (!alloc_buffer_size(buffer
, *needed
)) {
7234 return WERR_INSUFFICIENT_BUFFER
;
7237 /* fill the buffer with the ports structures */
7238 for (i
=0; i
<*returned
; i
++) {
7239 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7240 smb_io_port_1("", buffer
, &ports
[i
], 0);
7245 if (*needed
> offered
) {
7247 return WERR_INSUFFICIENT_BUFFER
;
7253 /****************************************************************************
7255 ****************************************************************************/
7257 static WERROR
enumports_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7259 PORT_INFO_2
*ports
=NULL
;
7262 if (*lp_enumports_cmd()) {
7263 char *cmd
= lp_enumports_cmd();
7272 if (*lp_pathname(lp_servicenumber(PRINTERS_NAME
)))
7273 path
= lp_pathname(lp_servicenumber(PRINTERS_NAME
));
7275 path
= lp_lockdir();
7277 slprintf(tmp_file
, sizeof(tmp_file
)-1, "%s/smbcmd.%u.", path
, (unsigned int)sys_getpid());
7278 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 2);
7281 DEBUG(10,("Running [%s > %s]\n", command
,tmp_file
));
7282 ret
= smbrun(command
, &fd
);
7283 DEBUGADD(10,("returned [%d]\n", ret
));
7287 /* Is this the best error to return here? */
7288 return WERR_ACCESS_DENIED
;
7292 qlines
= fd_lines_load(fd
, &numlines
);
7293 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7297 if((ports
=(PORT_INFO_2
*)malloc( numlines
* sizeof(PORT_INFO_2
) )) == NULL
) {
7298 file_lines_free(qlines
);
7302 for (i
=0; i
<numlines
; i
++) {
7303 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7304 fill_port_2(&(ports
[i
]), qlines
[i
]);
7307 file_lines_free(qlines
);
7310 *returned
= numlines
;
7316 if((ports
=(PORT_INFO_2
*)malloc( sizeof(PORT_INFO_2
) )) == NULL
)
7319 DEBUG(10,("enumports_level_2: port name %s\n", SAMBA_PRINTER_PORT_NAME
));
7321 fill_port_2(&ports
[0], SAMBA_PRINTER_PORT_NAME
);
7324 /* check the required size. */
7325 for (i
=0; i
<*returned
; i
++) {
7326 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7327 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7330 if (!alloc_buffer_size(buffer
, *needed
)) {
7332 return WERR_INSUFFICIENT_BUFFER
;
7335 /* fill the buffer with the ports structures */
7336 for (i
=0; i
<*returned
; i
++) {
7337 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7338 smb_io_port_2("", buffer
, &ports
[i
], 0);
7343 if (*needed
> offered
) {
7345 return WERR_INSUFFICIENT_BUFFER
;
7351 /****************************************************************************
7353 ****************************************************************************/
7355 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7357 uint32 level
= q_u
->level
;
7358 NEW_BUFFER
*buffer
= NULL
;
7359 uint32 offered
= q_u
->offered
;
7360 uint32
*needed
= &r_u
->needed
;
7361 uint32
*returned
= &r_u
->returned
;
7363 /* that's an [in out] buffer */
7364 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7365 buffer
= r_u
->buffer
;
7367 DEBUG(4,("_spoolss_enumports\n"));
7374 return enumports_level_1(buffer
, offered
, needed
, returned
);
7376 return enumports_level_2(buffer
, offered
, needed
, returned
);
7378 return WERR_UNKNOWN_LEVEL
;
7382 /****************************************************************************
7383 ****************************************************************************/
7385 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7386 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7387 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7388 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7391 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7394 WERROR err
= WERR_OK
;
7396 if ((printer
= (NT_PRINTER_INFO_LEVEL
*)malloc(sizeof(NT_PRINTER_INFO_LEVEL
))) == NULL
) {
7397 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7401 ZERO_STRUCTP(printer
);
7403 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7404 if (!convert_printer_info(info
, printer
, 2)) {
7405 free_a_printer(&printer
, 2);
7409 /* check to see if the printer already exists */
7411 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7412 DEBUG(5, ("_spoolss_addprinterex: Attempted to add a printer named [%s] when one already existed!\n",
7413 printer
->info_2
->sharename
));
7414 free_a_printer(&printer
, 2);
7415 return WERR_PRINTER_ALREADY_EXISTS
;
7418 /* FIXME!!! smbd should check to see if the driver is installed before
7419 trying to add a printer like this --jerry */
7421 if (*lp_addprinter_cmd() ) {
7422 if ( !add_printer_hook(printer
) ) {
7423 free_a_printer(&printer
,2);
7424 return WERR_ACCESS_DENIED
;
7428 /* use our primary netbios name since get_a_printer() will convert
7429 it to what the client expects on a case by case basis */
7431 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7432 printer
->info_2
->sharename
);
7435 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7436 free_a_printer(&printer
,2);
7437 return WERR_ACCESS_DENIED
;
7440 /* you must be a printer admin to add a new printer */
7441 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7442 free_a_printer(&printer
,2);
7443 return WERR_ACCESS_DENIED
;
7447 * Do sanity check on the requested changes for Samba.
7450 if (!check_printer_ok(printer
->info_2
, snum
)) {
7451 free_a_printer(&printer
,2);
7452 return WERR_INVALID_PARAM
;
7456 * When a printer is created, the drivername bound to the printer is used
7457 * to lookup previously saved driver initialization info, which is then
7458 * bound to the new printer, simulating what happens in the Windows arch.
7463 set_driver_init(printer
, 2);
7467 /* A valid devmode was included, convert and link it
7469 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7471 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7472 &printer
->info_2
->devmode
))
7476 /* write the ASCII on disk */
7477 err
= mod_a_printer(printer
, 2);
7478 if (!W_ERROR_IS_OK(err
)) {
7479 free_a_printer(&printer
,2);
7483 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7484 /* Handle open failed - remove addition. */
7485 del_a_printer(printer
->info_2
->sharename
);
7486 free_a_printer(&printer
,2);
7487 return WERR_ACCESS_DENIED
;
7490 update_c_setprinter(False
);
7491 free_a_printer(&printer
,2);
7496 /****************************************************************************
7497 ****************************************************************************/
7499 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7501 UNISTR2
*uni_srv_name
= &q_u
->server_name
;
7502 uint32 level
= q_u
->level
;
7503 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7504 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7505 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7506 uint32 user_switch
= q_u
->user_switch
;
7507 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7508 POLICY_HND
*handle
= &r_u
->handle
;
7512 /* we don't handle yet */
7513 /* but I know what to do ... */
7514 return WERR_UNKNOWN_LEVEL
;
7516 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7518 user_switch
, user
, handle
);
7520 return WERR_UNKNOWN_LEVEL
;
7524 /****************************************************************************
7525 ****************************************************************************/
7527 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7529 uint32 level
= q_u
->level
;
7530 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7531 WERROR err
= WERR_OK
;
7532 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7533 struct current_user user
;
7534 fstring driver_name
;
7537 ZERO_STRUCT(driver
);
7539 get_current_user(&user
, p
);
7541 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7546 DEBUG(5,("Cleaning driver's information\n"));
7547 err
= clean_up_driver_struct(driver
, level
, &user
);
7548 if (!W_ERROR_IS_OK(err
))
7551 DEBUG(5,("Moving driver to final destination\n"));
7552 if(!move_driver_to_download_area(driver
, level
, &user
, &err
)) {
7553 if (W_ERROR_IS_OK(err
))
7554 err
= WERR_ACCESS_DENIED
;
7558 if (add_a_printer_driver(driver
, level
)!=0) {
7559 err
= WERR_ACCESS_DENIED
;
7563 /* BEGIN_ADMIN_LOG */
7566 fstrcpy(driver_name
, driver
.info_3
->name
? driver
.info_3
->name
: "");
7567 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7568 driver_name
, get_drv_ver_to_os(driver
.info_3
->cversion
),uidtoname(user
.uid
));
7571 fstrcpy(driver_name
, driver
.info_6
->name
? driver
.info_6
->name
: "");
7572 sys_adminlog(LOG_INFO
,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
7573 driver_name
, get_drv_ver_to_os(driver
.info_6
->version
),uidtoname(user
.uid
));
7579 * I think this is where he DrvUpgradePrinter() hook would be
7580 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7581 * server. Right now, we just need to send ourselves a message
7582 * to update each printer bound to this driver. --jerry
7585 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7586 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7591 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7592 * decide if the driver init data should be deleted. The rules are:
7593 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7594 * 2) delete init data only if there is no 2k/Xp driver
7595 * 3) always delete init data
7596 * The generalized rule is always use init data from the highest order driver.
7597 * It is necessary to follow the driver install by an initialization step to
7598 * finish off this process.
7601 version
= driver
.info_3
->cversion
;
7602 else if (level
== 6)
7603 version
= driver
.info_6
->version
;
7608 * 9x printer driver - never delete init data
7611 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7616 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7617 * there is no 2k/Xp driver init data for this driver name.
7621 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7623 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7625 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7627 if (!del_driver_init(driver_name
))
7628 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7631 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7633 free_a_printer_driver(driver1
,3);
7634 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7641 * 2k or Xp printer driver - always delete init data
7644 if (!del_driver_init(driver_name
))
7645 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7649 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7655 free_a_printer_driver(driver
, level
);
7659 /********************************************************************
7660 * spoolss_addprinterdriverex
7661 ********************************************************************/
7663 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7665 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7666 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7669 * we only support the semantics of AddPrinterDriver()
7670 * i.e. only copy files that are newer than existing ones
7673 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7674 return WERR_ACCESS_DENIED
;
7676 ZERO_STRUCT(q_u_local
);
7677 ZERO_STRUCT(r_u_local
);
7679 /* just pass the information off to _spoolss_addprinterdriver() */
7680 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7681 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7682 q_u_local
.level
= q_u
->level
;
7683 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7685 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7688 /****************************************************************************
7689 ****************************************************************************/
7691 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7693 init_unistr(&info
->name
, name
);
7696 /****************************************************************************
7697 ****************************************************************************/
7699 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7705 const char *short_archi
;
7706 DRIVER_DIRECTORY_1
*info
=NULL
;
7708 unistr2_to_ascii(servername
, name
, sizeof(servername
)-1);
7709 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7711 /* check for beginning double '\'s and that the server
7714 pservername
= servername
;
7715 if ( *pservername
== '\\' && strlen(servername
)>2 ) {
7719 if ( !is_myname_or_ipaddr( pservername
) )
7720 return WERR_INVALID_PARAM
;
7722 if (!(short_archi
= get_short_archi(long_archi
)))
7723 return WERR_INVALID_ENVIRONMENT
;
7725 if((info
=(DRIVER_DIRECTORY_1
*)malloc(sizeof(DRIVER_DIRECTORY_1
))) == NULL
)
7728 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", pservername
, short_archi
);
7730 DEBUG(4,("printer driver directory: [%s]\n", path
));
7732 fill_driverdir_1(info
, path
);
7734 *needed
+= spoolss_size_driverdir_info_1(info
);
7736 if (!alloc_buffer_size(buffer
, *needed
)) {
7738 return WERR_INSUFFICIENT_BUFFER
;
7741 smb_io_driverdir_1("", buffer
, info
, 0);
7745 if (*needed
> offered
)
7746 return WERR_INSUFFICIENT_BUFFER
;
7751 /****************************************************************************
7752 ****************************************************************************/
7754 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7756 UNISTR2
*name
= &q_u
->name
;
7757 UNISTR2
*uni_environment
= &q_u
->environment
;
7758 uint32 level
= q_u
->level
;
7759 NEW_BUFFER
*buffer
= NULL
;
7760 uint32 offered
= q_u
->offered
;
7761 uint32
*needed
= &r_u
->needed
;
7763 /* that's an [in out] buffer */
7764 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
7765 buffer
= r_u
->buffer
;
7767 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7773 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7775 return WERR_UNKNOWN_LEVEL
;
7779 /****************************************************************************
7780 ****************************************************************************/
7782 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7784 POLICY_HND
*handle
= &q_u
->handle
;
7785 uint32 idx
= q_u
->index
;
7786 uint32 in_value_len
= q_u
->valuesize
;
7787 uint32 in_data_len
= q_u
->datasize
;
7788 uint32
*out_max_value_len
= &r_u
->valuesize
;
7789 uint16
**out_value
= &r_u
->value
;
7790 uint32
*out_value_len
= &r_u
->realvaluesize
;
7791 uint32
*out_type
= &r_u
->type
;
7792 uint32
*out_max_data_len
= &r_u
->datasize
;
7793 uint8
**data_out
= &r_u
->data
;
7794 uint32
*out_data_len
= &r_u
->realdatasize
;
7796 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7798 uint32 biggest_valuesize
;
7799 uint32 biggest_datasize
;
7801 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7804 REGISTRY_VALUE
*val
= NULL
;
7805 NT_PRINTER_DATA
*p_data
;
7806 int i
, key_index
, num_values
;
7809 ZERO_STRUCT( printer
);
7813 *out_max_data_len
= 0;
7817 DEBUG(5,("spoolss_enumprinterdata\n"));
7820 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7824 if (!get_printer_snum(p
,handle
, &snum
))
7827 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7828 if (!W_ERROR_IS_OK(result
))
7831 p_data
= &printer
->info_2
->data
;
7832 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7837 * The NT machine wants to know the biggest size of value and data
7839 * cf: MSDN EnumPrinterData remark section
7842 if ( !in_value_len
&& !in_data_len
&& (key_index
!= -1) )
7844 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7846 biggest_valuesize
= 0;
7847 biggest_datasize
= 0;
7849 num_values
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
7851 for ( i
=0; i
<num_values
; i
++ )
7853 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
7855 name_length
= strlen(val
->valuename
);
7856 if ( strlen(val
->valuename
) > biggest_valuesize
)
7857 biggest_valuesize
= name_length
;
7859 if ( val
->size
> biggest_datasize
)
7860 biggest_datasize
= val
->size
;
7862 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7866 /* the value is an UNICODE string but real_value_size is the length
7867 in bytes including the trailing 0 */
7869 *out_value_len
= 2 * (1+biggest_valuesize
);
7870 *out_data_len
= biggest_datasize
;
7872 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7878 * the value len is wrong in NT sp3
7879 * that's the number of bytes not the number of unicode chars
7882 if ( key_index
!= -1 )
7883 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, idx
);
7888 /* out_value should default to "" or else NT4 has
7889 problems unmarshalling the response */
7891 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7893 if((*out_value
=(uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7895 result
= WERR_NOMEM
;
7899 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7901 /* the data is counted in bytes */
7903 *out_max_data_len
= in_data_len
;
7904 *out_data_len
= in_data_len
;
7906 /* only allocate when given a non-zero data_len */
7908 if ( in_data_len
&& ((*data_out
=(uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
7910 result
= WERR_NOMEM
;
7914 result
= WERR_NO_MORE_ITEMS
;
7920 * - counted in bytes in the request
7921 * - counted in UNICODE chars in the max reply
7922 * - counted in bytes in the real size
7924 * take a pause *before* coding not *during* coding
7928 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7929 if ( (*out_value
= (uint16
*)talloc_zero(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7931 result
= WERR_NOMEM
;
7935 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), in_value_len
, 0);
7939 *out_type
= regval_type( val
);
7941 /* data - counted in bytes */
7943 *out_max_data_len
= in_data_len
;
7944 if ( (*data_out
= (uint8
*)talloc_zero(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
7946 result
= WERR_NOMEM
;
7949 data_len
= (size_t)regval_size(val
);
7950 memcpy( *data_out
, regval_data_p(val
), data_len
);
7951 *out_data_len
= data_len
;
7955 free_a_printer(&printer
, 2);
7959 /****************************************************************************
7960 ****************************************************************************/
7962 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
7964 POLICY_HND
*handle
= &q_u
->handle
;
7965 UNISTR2
*value
= &q_u
->value
;
7966 uint32 type
= q_u
->type
;
7967 uint8
*data
= q_u
->data
;
7968 uint32 real_len
= q_u
->real_len
;
7970 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7972 WERROR status
= WERR_OK
;
7973 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
7976 DEBUG(5,("spoolss_setprinterdata\n"));
7979 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7983 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
7984 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
7985 return WERR_INVALID_PARAM
;
7988 if (!get_printer_snum(p
,handle
, &snum
))
7992 * Access check : NT returns "access denied" if you make a
7993 * SetPrinterData call without the necessary privildge.
7994 * we were originally returning OK if nothing changed
7995 * which made Win2k issue **a lot** of SetPrinterData
7996 * when connecting to a printer --jerry
7999 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8001 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8002 status
= WERR_ACCESS_DENIED
;
8006 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8007 if (!W_ERROR_IS_OK(status
))
8010 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8013 * When client side code sets a magic printer data key, detect it and save
8014 * the current printer data and the magic key's data (its the DEVMODE) for
8015 * future printer/driver initializations.
8017 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
8019 /* Set devmode and printer initialization info */
8020 status
= save_driver_init( printer
, 2, data
, real_len
);
8022 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
8026 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
8027 type
, data
, real_len
);
8028 if ( W_ERROR_IS_OK(status
) )
8029 status
= mod_a_printer(printer
, 2);
8033 free_a_printer(&printer
, 2);
8038 /****************************************************************************
8039 ****************************************************************************/
8041 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
8043 POLICY_HND
*handle
= &q_u
->handle
;
8044 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8047 DEBUG(5,("_spoolss_resetprinter\n"));
8050 * All we do is to check to see if the handle and queue is valid.
8051 * This call really doesn't mean anything to us because we only
8052 * support RAW printing. --jerry
8056 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8060 if (!get_printer_snum(p
,handle
, &snum
))
8064 /* blindly return success */
8069 /****************************************************************************
8070 ****************************************************************************/
8072 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
8074 POLICY_HND
*handle
= &q_u
->handle
;
8075 UNISTR2
*value
= &q_u
->valuename
;
8077 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8079 WERROR status
= WERR_OK
;
8080 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8083 DEBUG(5,("spoolss_deleteprinterdata\n"));
8086 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8090 if (!get_printer_snum(p
, handle
, &snum
))
8093 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8094 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8095 return WERR_ACCESS_DENIED
;
8098 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8099 if (!W_ERROR_IS_OK(status
))
8102 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8104 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
8106 if ( W_ERROR_IS_OK(status
) )
8107 mod_a_printer( printer
, 2 );
8109 free_a_printer(&printer
, 2);
8114 /****************************************************************************
8115 ****************************************************************************/
8117 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
8119 POLICY_HND
*handle
= &q_u
->handle
;
8120 FORM
*form
= &q_u
->form
;
8121 nt_forms_struct tmpForm
;
8123 WERROR status
= WERR_OK
;
8124 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8127 nt_forms_struct
*list
=NULL
;
8128 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8130 DEBUG(5,("spoolss_addform\n"));
8133 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8138 /* forms can be added on printer of on the print server handle */
8140 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8142 if (!get_printer_snum(p
,handle
, &snum
))
8145 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8146 if (!W_ERROR_IS_OK(status
))
8150 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8151 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8152 status
= WERR_ACCESS_DENIED
;
8156 /* can't add if builtin */
8158 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8159 status
= WERR_ALREADY_EXISTS
;
8163 count
= get_ntforms(&list
);
8165 if(!add_a_form(&list
, form
, &count
)) {
8166 status
= WERR_NOMEM
;
8170 write_ntforms(&list
, count
);
8173 * ChangeID must always be set if this is a printer
8176 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8177 status
= mod_a_printer(printer
, 2);
8181 free_a_printer(&printer
, 2);
8187 /****************************************************************************
8188 ****************************************************************************/
8190 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
8192 POLICY_HND
*handle
= &q_u
->handle
;
8193 UNISTR2
*form_name
= &q_u
->name
;
8194 nt_forms_struct tmpForm
;
8196 nt_forms_struct
*list
=NULL
;
8197 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8199 WERROR status
= WERR_OK
;
8200 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8202 DEBUG(5,("spoolss_deleteform\n"));
8205 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8209 /* forms can be deleted on printer of on the print server handle */
8211 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8213 if (!get_printer_snum(p
,handle
, &snum
))
8216 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8217 if (!W_ERROR_IS_OK(status
))
8221 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8222 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8223 status
= WERR_ACCESS_DENIED
;
8227 /* can't delete if builtin */
8229 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
8230 status
= WERR_INVALID_PARAM
;
8234 count
= get_ntforms(&list
);
8236 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8240 * ChangeID must always be set if this is a printer
8243 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8244 status
= mod_a_printer(printer
, 2);
8248 free_a_printer(&printer
, 2);
8254 /****************************************************************************
8255 ****************************************************************************/
8257 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8259 POLICY_HND
*handle
= &q_u
->handle
;
8260 FORM
*form
= &q_u
->form
;
8261 nt_forms_struct tmpForm
;
8263 WERROR status
= WERR_OK
;
8264 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8267 nt_forms_struct
*list
=NULL
;
8268 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8270 DEBUG(5,("spoolss_setform\n"));
8273 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8277 /* forms can be modified on printer of on the print server handle */
8279 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8281 if (!get_printer_snum(p
,handle
, &snum
))
8284 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8285 if (!W_ERROR_IS_OK(status
))
8289 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8290 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8291 status
= WERR_ACCESS_DENIED
;
8295 /* can't set if builtin */
8296 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8297 status
= WERR_INVALID_PARAM
;
8301 count
= get_ntforms(&list
);
8302 update_a_form(&list
, form
, count
);
8303 write_ntforms(&list
, count
);
8306 * ChangeID must always be set if this is a printer
8309 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTER
)
8310 status
= mod_a_printer(printer
, 2);
8315 free_a_printer(&printer
, 2);
8321 /****************************************************************************
8322 enumprintprocessors level 1.
8323 ****************************************************************************/
8325 static WERROR
enumprintprocessors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8327 PRINTPROCESSOR_1
*info_1
=NULL
;
8329 if((info_1
= (PRINTPROCESSOR_1
*)malloc(sizeof(PRINTPROCESSOR_1
))) == NULL
)
8334 init_unistr(&info_1
->name
, "winprint");
8336 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8338 if (!alloc_buffer_size(buffer
, *needed
))
8339 return WERR_INSUFFICIENT_BUFFER
;
8341 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8345 if (*needed
> offered
) {
8347 return WERR_INSUFFICIENT_BUFFER
;
8353 /****************************************************************************
8354 ****************************************************************************/
8356 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8358 uint32 level
= q_u
->level
;
8359 NEW_BUFFER
*buffer
= NULL
;
8360 uint32 offered
= q_u
->offered
;
8361 uint32
*needed
= &r_u
->needed
;
8362 uint32
*returned
= &r_u
->returned
;
8364 /* that's an [in out] buffer */
8365 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8366 buffer
= r_u
->buffer
;
8368 DEBUG(5,("spoolss_enumprintprocessors\n"));
8371 * Enumerate the print processors ...
8373 * Just reply with "winprint", to keep NT happy
8374 * and I can use my nice printer checker.
8382 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8384 return WERR_UNKNOWN_LEVEL
;
8388 /****************************************************************************
8389 enumprintprocdatatypes level 1.
8390 ****************************************************************************/
8392 static WERROR
enumprintprocdatatypes_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8394 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8396 if((info_1
= (PRINTPROCDATATYPE_1
*)malloc(sizeof(PRINTPROCDATATYPE_1
))) == NULL
)
8401 init_unistr(&info_1
->name
, "RAW");
8403 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8405 if (!alloc_buffer_size(buffer
, *needed
))
8406 return WERR_INSUFFICIENT_BUFFER
;
8408 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8412 if (*needed
> offered
) {
8414 return WERR_INSUFFICIENT_BUFFER
;
8420 /****************************************************************************
8421 ****************************************************************************/
8423 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8425 uint32 level
= q_u
->level
;
8426 NEW_BUFFER
*buffer
= NULL
;
8427 uint32 offered
= q_u
->offered
;
8428 uint32
*needed
= &r_u
->needed
;
8429 uint32
*returned
= &r_u
->returned
;
8431 /* that's an [in out] buffer */
8432 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8433 buffer
= r_u
->buffer
;
8435 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8442 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8444 return WERR_UNKNOWN_LEVEL
;
8448 /****************************************************************************
8449 enumprintmonitors level 1.
8450 ****************************************************************************/
8452 static WERROR
enumprintmonitors_level_1(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8454 PRINTMONITOR_1
*info_1
=NULL
;
8456 if((info_1
= (PRINTMONITOR_1
*)malloc(sizeof(PRINTMONITOR_1
))) == NULL
)
8461 init_unistr(&info_1
->name
, "Local Port");
8463 *needed
+= spoolss_size_printmonitor_info_1(info_1
);
8465 if (!alloc_buffer_size(buffer
, *needed
))
8466 return WERR_INSUFFICIENT_BUFFER
;
8468 smb_io_printmonitor_info_1("", buffer
, info_1
, 0);
8472 if (*needed
> offered
) {
8474 return WERR_INSUFFICIENT_BUFFER
;
8480 /****************************************************************************
8481 enumprintmonitors level 2.
8482 ****************************************************************************/
8484 static WERROR
enumprintmonitors_level_2(NEW_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8486 PRINTMONITOR_2
*info_2
=NULL
;
8488 if((info_2
= (PRINTMONITOR_2
*)malloc(sizeof(PRINTMONITOR_2
))) == NULL
)
8493 init_unistr(&info_2
->name
, "Local Port");
8494 init_unistr(&info_2
->environment
, "Windows NT X86");
8495 init_unistr(&info_2
->dll_name
, "localmon.dll");
8497 *needed
+= spoolss_size_printmonitor_info_2(info_2
);
8499 if (!alloc_buffer_size(buffer
, *needed
))
8500 return WERR_INSUFFICIENT_BUFFER
;
8502 smb_io_printmonitor_info_2("", buffer
, info_2
, 0);
8506 if (*needed
> offered
) {
8508 return WERR_INSUFFICIENT_BUFFER
;
8514 /****************************************************************************
8515 ****************************************************************************/
8517 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8519 uint32 level
= q_u
->level
;
8520 NEW_BUFFER
*buffer
= NULL
;
8521 uint32 offered
= q_u
->offered
;
8522 uint32
*needed
= &r_u
->needed
;
8523 uint32
*returned
= &r_u
->returned
;
8525 /* that's an [in out] buffer */
8526 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8527 buffer
= r_u
->buffer
;
8529 DEBUG(5,("spoolss_enumprintmonitors\n"));
8532 * Enumerate the print monitors ...
8534 * Just reply with "Local Port", to keep NT happy
8535 * and I can use my nice printer checker.
8543 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8545 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8547 return WERR_UNKNOWN_LEVEL
;
8551 /****************************************************************************
8552 ****************************************************************************/
8554 static WERROR
getjob_level_1(print_queue_struct
**queue
, int count
, int snum
,
8555 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8556 uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
,
8561 JOB_INFO_1
*info_1
=NULL
;
8563 info_1
=(JOB_INFO_1
*)malloc(sizeof(JOB_INFO_1
));
8565 if (info_1
== NULL
) {
8569 for (i
=0; i
<count
&& found
==False
; i
++) {
8570 if ((*queue
)[i
].job
==(int)jobid
)
8576 /* NT treats not found as bad param... yet another bad choice */
8577 return WERR_INVALID_PARAM
;
8580 fill_job_info_1( info_1
, &((*queue
)[i
-1]), i
, snum
, ntprinter
);
8582 *needed
+= spoolss_size_job_info_1(info_1
);
8584 if (!alloc_buffer_size(buffer
, *needed
)) {
8586 return WERR_INSUFFICIENT_BUFFER
;
8589 smb_io_job_info_1("", buffer
, info_1
, 0);
8593 if (*needed
> offered
)
8594 return WERR_INSUFFICIENT_BUFFER
;
8599 /****************************************************************************
8600 ****************************************************************************/
8602 static WERROR
getjob_level_2(print_queue_struct
**queue
, int count
, int snum
,
8603 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8604 uint32 jobid
, NEW_BUFFER
*buffer
, uint32 offered
,
8611 DEVICEMODE
*devmode
= NULL
;
8612 NT_DEVICEMODE
*nt_devmode
= NULL
;
8614 info_2
=(JOB_INFO_2
*)malloc(sizeof(JOB_INFO_2
));
8616 ZERO_STRUCTP(info_2
);
8618 if (info_2
== NULL
) {
8623 for ( i
=0; i
<count
&& found
==False
; i
++ )
8625 if ((*queue
)[i
].job
== (int)jobid
)
8631 /* NT treats not found as bad param... yet another bad
8633 ret
= WERR_INVALID_PARAM
;
8638 * if the print job does not have a DEVMODE associated with it,
8639 * just use the one for the printer. A NULL devicemode is not
8640 * a failure condition
8643 if ( !(nt_devmode
=print_job_devmode( lp_const_servicename(snum
), jobid
)) )
8644 devmode
= construct_dev_mode(snum
);
8646 if ((devmode
= (DEVICEMODE
*)malloc(sizeof(DEVICEMODE
))) != NULL
) {
8647 ZERO_STRUCTP( devmode
);
8648 convert_nt_devicemode( devmode
, nt_devmode
);
8652 fill_job_info_2(info_2
, &((*queue
)[i
-1]), i
, snum
, ntprinter
, devmode
);
8654 *needed
+= spoolss_size_job_info_2(info_2
);
8656 if (!alloc_buffer_size(buffer
, *needed
)) {
8657 ret
= WERR_INSUFFICIENT_BUFFER
;
8661 smb_io_job_info_2("", buffer
, info_2
, 0);
8663 if (*needed
> offered
) {
8664 ret
= WERR_INSUFFICIENT_BUFFER
;
8671 /* Cleanup allocated memory */
8673 free_job_info_2(info_2
); /* Also frees devmode */
8675 free_a_printer(&ntprinter
, 2);
8680 /****************************************************************************
8681 ****************************************************************************/
8683 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8685 POLICY_HND
*handle
= &q_u
->handle
;
8686 uint32 jobid
= q_u
->jobid
;
8687 uint32 level
= q_u
->level
;
8688 NEW_BUFFER
*buffer
= NULL
;
8689 uint32 offered
= q_u
->offered
;
8690 uint32
*needed
= &r_u
->needed
;
8691 WERROR wstatus
= WERR_OK
;
8692 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8695 print_queue_struct
*queue
= NULL
;
8696 print_status_struct prt_status
;
8698 /* that's an [in out] buffer */
8699 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
8700 buffer
= r_u
->buffer
;
8702 DEBUG(5,("spoolss_getjob\n"));
8706 if (!get_printer_snum(p
, handle
, &snum
))
8709 wstatus
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8710 if ( !W_ERROR_IS_OK(wstatus
) )
8713 count
= print_queue_status(snum
, &queue
, &prt_status
);
8715 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8716 count
, prt_status
.status
, prt_status
.message
));
8720 wstatus
= getjob_level_1(&queue
, count
, snum
, ntprinter
, jobid
,
8721 buffer
, offered
, needed
);
8724 wstatus
= getjob_level_2(&queue
, count
, snum
, ntprinter
, jobid
,
8725 buffer
, offered
, needed
);
8728 wstatus
= WERR_UNKNOWN_LEVEL
;
8733 free_a_printer( &ntprinter
, 2 );
8738 /********************************************************************
8739 spoolss_getprinterdataex
8741 From MSDN documentation of GetPrinterDataEx: pass request
8742 to GetPrinterData if key is "PrinterDriverData".
8743 ********************************************************************/
8745 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8747 POLICY_HND
*handle
= &q_u
->handle
;
8748 uint32 in_size
= q_u
->size
;
8749 uint32
*type
= &r_u
->type
;
8750 uint32
*out_size
= &r_u
->size
;
8751 uint8
**data
= &r_u
->data
;
8752 uint32
*needed
= &r_u
->needed
;
8753 fstring keyname
, valuename
;
8755 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8757 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8759 WERROR status
= WERR_OK
;
8761 DEBUG(4,("_spoolss_getprinterdataex\n"));
8763 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8764 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8766 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8767 keyname
, valuename
));
8769 /* in case of problem, return some default values */
8773 *out_size
= in_size
;
8776 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8777 status
= WERR_BADFID
;
8781 /* Is the handle to a printer or to the server? */
8783 if (Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8784 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8785 status
= WERR_INVALID_PARAM
;
8789 if ( !get_printer_snum(p
,handle
, &snum
) )
8792 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8793 if ( !W_ERROR_IS_OK(status
) )
8796 /* check to see if the keyname is valid */
8797 if ( !strlen(keyname
) ) {
8798 status
= WERR_INVALID_PARAM
;
8802 if ( lookup_printerkey( &printer
->info_2
->data
, keyname
) == -1 ) {
8803 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8804 free_a_printer( &printer
, 2 );
8805 status
= WERR_BADFILE
;
8809 /* When given a new keyname, we should just create it */
8811 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8813 if (*needed
> *out_size
)
8814 status
= WERR_MORE_DATA
;
8817 if ( !W_ERROR_IS_OK(status
) )
8819 DEBUG(5, ("error: allocating %d\n", *out_size
));
8821 /* reply this param doesn't exist */
8825 if( (*data
=(uint8
*)talloc_zero(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8826 status
= WERR_NOMEM
;
8836 free_a_printer( &printer
, 2 );
8841 /********************************************************************
8842 * spoolss_setprinterdataex
8843 ********************************************************************/
8845 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
8847 POLICY_HND
*handle
= &q_u
->handle
;
8848 uint32 type
= q_u
->type
;
8849 uint8
*data
= q_u
->data
;
8850 uint32 real_len
= q_u
->real_len
;
8852 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8854 WERROR status
= WERR_OK
;
8855 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8860 DEBUG(4,("_spoolss_setprinterdataex\n"));
8862 /* From MSDN documentation of SetPrinterDataEx: pass request to
8863 SetPrinterData if key is "PrinterDriverData" */
8866 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8870 if ( Printer
->printer_type
== PRINTER_HANDLE_IS_PRINTSERVER
) {
8871 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
8872 return WERR_INVALID_PARAM
;
8875 if ( !get_printer_snum(p
,handle
, &snum
) )
8879 * Access check : NT returns "access denied" if you make a
8880 * SetPrinterData call without the necessary privildge.
8881 * we were originally returning OK if nothing changed
8882 * which made Win2k issue **a lot** of SetPrinterData
8883 * when connecting to a printer --jerry
8886 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8888 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
8889 return WERR_ACCESS_DENIED
;
8892 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8893 if (!W_ERROR_IS_OK(status
))
8896 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
8897 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
8899 /* check for OID in valuename */
8901 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
8907 /* save the registry data */
8909 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
8911 if ( W_ERROR_IS_OK(status
) )
8913 /* save the OID if one was specified */
8915 fstrcat( keyname
, "\\" );
8916 fstrcat( keyname
, SPOOL_OID_KEY
);
8919 * I'm not checking the status here on purpose. Don't know
8920 * if this is right, but I'm returning the status from the
8921 * previous set_printer_dataex() call. I have no idea if
8922 * this is right. --jerry
8925 set_printer_dataex( printer
, keyname
, valuename
,
8926 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
8929 status
= mod_a_printer(printer
, 2);
8932 free_a_printer(&printer
, 2);
8938 /********************************************************************
8939 * spoolss_deleteprinterdataex
8940 ********************************************************************/
8942 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
8944 POLICY_HND
*handle
= &q_u
->handle
;
8945 UNISTR2
*value
= &q_u
->valuename
;
8946 UNISTR2
*key
= &q_u
->keyname
;
8948 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8950 WERROR status
= WERR_OK
;
8951 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8952 pstring valuename
, keyname
;
8954 DEBUG(5,("spoolss_deleteprinterdataex\n"));
8957 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8961 if (!get_printer_snum(p
, handle
, &snum
))
8964 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8965 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
8966 return WERR_ACCESS_DENIED
;
8969 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8970 if (!W_ERROR_IS_OK(status
))
8973 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8974 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
8976 status
= delete_printer_dataex( printer
, keyname
, valuename
);
8978 if ( W_ERROR_IS_OK(status
) )
8979 mod_a_printer( printer
, 2 );
8981 free_a_printer(&printer
, 2);
8986 /********************************************************************
8987 * spoolss_enumprinterkey
8988 ********************************************************************/
8991 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
8994 fstring
*keynames
= NULL
;
8995 uint16
*enumkeys
= NULL
;
8998 POLICY_HND
*handle
= &q_u
->handle
;
8999 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9000 NT_PRINTER_DATA
*data
;
9001 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9003 WERROR status
= WERR_BADFILE
;
9006 DEBUG(4,("_spoolss_enumprinterkey\n"));
9009 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9013 if ( !get_printer_snum(p
,handle
, &snum
) )
9016 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9017 if (!W_ERROR_IS_OK(status
))
9020 /* get the list of subkey names */
9022 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
9023 data
= &printer
->info_2
->data
;
9025 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
9027 if ( num_keys
== -1 ) {
9028 status
= WERR_BADFILE
;
9032 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
9034 r_u
->needed
= printerkey_len
*2;
9036 if ( q_u
->size
< r_u
->needed
) {
9037 status
= WERR_MORE_DATA
;
9041 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
9042 status
= WERR_NOMEM
;
9048 if ( q_u
->size
< r_u
->needed
)
9049 status
= WERR_MORE_DATA
;
9052 free_a_printer( &printer
, 2 );
9053 SAFE_FREE( keynames
);
9058 /********************************************************************
9059 * spoolss_deleteprinterkey
9060 ********************************************************************/
9062 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
9064 POLICY_HND
*handle
= &q_u
->handle
;
9065 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9067 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9071 DEBUG(5,("spoolss_deleteprinterkey\n"));
9074 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9078 /* if keyname == NULL, return error */
9080 if ( !q_u
->keyname
.buffer
)
9081 return WERR_INVALID_PARAM
;
9083 if (!get_printer_snum(p
, handle
, &snum
))
9086 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9087 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9088 return WERR_ACCESS_DENIED
;
9091 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9092 if (!W_ERROR_IS_OK(status
))
9095 /* delete the key and all subneys */
9097 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
9099 status
= delete_all_printer_data( printer
->info_2
, key
);
9101 if ( W_ERROR_IS_OK(status
) )
9102 status
= mod_a_printer(printer
, 2);
9104 free_a_printer( &printer
, 2 );
9110 /********************************************************************
9111 * spoolss_enumprinterdataex
9112 ********************************************************************/
9114 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9116 POLICY_HND
*handle
= &q_u
->handle
;
9117 uint32 in_size
= q_u
->size
;
9120 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9121 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9122 NT_PRINTER_DATA
*p_data
;
9124 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9129 REGISTRY_VALUE
*val
;
9134 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9137 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9142 * first check for a keyname of NULL or "". Win2k seems to send
9143 * this a lot and we should send back WERR_INVALID_PARAM
9144 * no need to spend time looking up the printer in this case.
9148 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9149 if ( !strlen(key
) ) {
9150 result
= WERR_INVALID_PARAM
;
9154 /* get the printer off of disk */
9156 if (!get_printer_snum(p
,handle
, &snum
))
9159 ZERO_STRUCT(printer
);
9160 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9161 if (!W_ERROR_IS_OK(result
))
9164 /* now look for a match on the key name */
9166 p_data
= &printer
->info_2
->data
;
9168 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9169 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9171 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9172 result
= WERR_INVALID_PARAM
;
9179 /* allocate the memory for the array of pointers -- if necessary */
9181 num_entries
= regval_ctr_numvals( &p_data
->keys
[key_index
].values
);
9184 if ( (enum_values
=talloc(p
->mem_ctx
, num_entries
*sizeof(PRINTER_ENUM_VALUES
))) == NULL
)
9186 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9187 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9188 result
= WERR_NOMEM
;
9192 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9196 * loop through all params and build the array to pass
9197 * back to the client
9200 for ( i
=0; i
<num_entries
; i
++ )
9202 /* lookup the registry value */
9204 val
= regval_ctr_specific_value( &p_data
->keys
[key_index
].values
, i
);
9205 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9209 value_name
= regval_name( val
);
9210 init_unistr( &enum_values
[i
].valuename
, value_name
);
9211 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9212 enum_values
[i
].type
= regval_type( val
);
9214 data_len
= regval_size( val
);
9216 if ( !(enum_values
[i
].data
= talloc_memdup(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9218 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9220 result
= WERR_NOMEM
;
9224 enum_values
[i
].data_len
= data_len
;
9226 /* keep track of the size of the array in bytes */
9228 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9231 /* housekeeping information in the reply */
9233 r_u
->needed
= needed
;
9234 r_u
->returned
= num_entries
;
9236 if (needed
> in_size
) {
9237 result
= WERR_MORE_DATA
;
9241 /* copy data into the reply */
9243 r_u
->ctr
.size
= r_u
->needed
;
9244 r_u
->ctr
.size_of_array
= r_u
->returned
;
9245 r_u
->ctr
.values
= enum_values
;
9251 free_a_printer(&printer
, 2);
9256 /****************************************************************************
9257 ****************************************************************************/
9259 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9261 init_unistr(&info
->name
, name
);
9264 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9265 UNISTR2
*environment
,
9272 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9274 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9276 if (!get_short_archi(long_archi
))
9277 return WERR_INVALID_ENVIRONMENT
;
9279 if((info
=(PRINTPROCESSOR_DIRECTORY_1
*)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1
))) == NULL
)
9282 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9284 fill_printprocessordirectory_1(info
, path
);
9286 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9288 if (!alloc_buffer_size(buffer
, *needed
)) {
9290 return WERR_INSUFFICIENT_BUFFER
;
9293 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9297 if (*needed
> offered
)
9298 return WERR_INSUFFICIENT_BUFFER
;
9303 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9305 uint32 level
= q_u
->level
;
9306 NEW_BUFFER
*buffer
= NULL
;
9307 uint32 offered
= q_u
->offered
;
9308 uint32
*needed
= &r_u
->needed
;
9311 /* that's an [in out] buffer */
9312 spoolss_move_buffer(q_u
->buffer
, &r_u
->buffer
);
9313 buffer
= r_u
->buffer
;
9315 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9321 result
= getprintprocessordirectory_level_1
9322 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9325 result
= WERR_UNKNOWN_LEVEL
;
9333 WERROR
_spoolss_replyopenprinter(pipes_struct
*p
, SPOOL_Q_REPLYOPENPRINTER
*q_u
,
9334 SPOOL_R_REPLYOPENPRINTER
*r_u
)
9336 DEBUG(5,("_spoolss_replyopenprinter\n"));
9338 DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u
->printer
));
9343 WERROR
_spoolss_replycloseprinter(pipes_struct
*p
, SPOOL_Q_REPLYCLOSEPRINTER
*q_u
,
9344 SPOOL_R_REPLYCLOSEPRINTER
*r_u
)
9346 DEBUG(5,("_spoolss_replycloseprinter\n"));