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. */
31 extern userdom_struct current_user_info
;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 const char *long_archi
;
45 const char *short_archi
;
49 static Printer_entry
*printers_list
;
51 typedef struct _counter_printer_0
{
52 struct _counter_printer_0
*next
;
53 struct _counter_printer_0
*prev
;
59 static counter_printer_0
*counter_list
;
61 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections
=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
69 /* API table for Xcv Monitor functions */
71 struct xcv_api_table
{
73 WERROR(*fn
) (NT_USER_TOKEN
*token
, RPC_BUFFER
*in
, RPC_BUFFER
*out
, uint32
*needed
);
77 /* translate between internal status numbers and NT status numbers */
78 static int nt_printj_status(int v
)
84 return JOB_STATUS_PAUSED
;
86 return JOB_STATUS_SPOOLING
;
88 return JOB_STATUS_PRINTING
;
90 return JOB_STATUS_ERROR
;
92 return JOB_STATUS_DELETING
;
94 return JOB_STATUS_OFFLINE
;
96 return JOB_STATUS_PAPEROUT
;
98 return JOB_STATUS_PRINTED
;
100 return JOB_STATUS_DELETED
;
102 return JOB_STATUS_BLOCKED
;
103 case LPQ_USER_INTERVENTION
:
104 return JOB_STATUS_USER_INTERVENTION
;
109 static int nt_printq_status(int v
)
113 return PRINTER_STATUS_PAUSED
;
122 /****************************************************************************
123 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
124 ****************************************************************************/
126 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
131 SAFE_FREE((*pp
)->ctr
.type
);
135 /***************************************************************************
136 Disconnect from the client
137 ****************************************************************************/
139 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
144 * Tell the specific printing tdb we no longer want messages for this printer
145 * by deregistering our PID.
148 if (!print_notify_deregister_pid(snum
))
149 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
151 /* weird if the test succeds !!! */
152 if (smb_connections
==0) {
153 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
157 result
= rpccli_spoolss_reply_close_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, handle
);
159 if (!W_ERROR_IS_OK(result
))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 dos_errstr(result
)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections
==1) {
166 cli_shutdown( notify_cli_pipe
->cli
);
167 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
169 message_deregister(MSG_PRINTER_NOTIFY2
);
171 /* Tell the connections db we're no longer interested in
172 * printer notify messages. */
174 register_message_flags( False
, FLAG_MSG_PRINT_NOTIFY
);
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr
)
186 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
188 if (Printer
->notify
.client_connected
==True
) {
191 if ( Printer
->printer_type
== SPLHND_SERVER
) {
193 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
194 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
195 snum
= print_queue_snum(Printer
->sharename
);
197 srv_spoolss_replycloseprinter(snum
,
198 &Printer
->notify
.client_hnd
);
202 Printer
->notify
.flags
=0;
203 Printer
->notify
.options
=0;
204 Printer
->notify
.localmachine
[0]='\0';
205 Printer
->notify
.printerlocal
=0;
206 free_spool_notify_option(&Printer
->notify
.option
);
207 Printer
->notify
.option
=NULL
;
208 Printer
->notify
.client_connected
=False
;
210 free_nt_devicemode( &Printer
->nt_devmode
);
211 free_a_printer( &Printer
->printer_info
, 2 );
213 talloc_destroy( Printer
->ctx
);
215 /* Remove from the internal list. */
216 DLIST_REMOVE(printers_list
, Printer
);
221 /****************************************************************************
222 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
223 ****************************************************************************/
225 static SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
227 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
232 new_sp
= SMB_MALLOC_P(SPOOL_NOTIFY_OPTION
);
239 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
241 if (!new_sp
->ctr
.type
) {
250 /****************************************************************************
251 find printer index by handle
252 ****************************************************************************/
254 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
256 Printer_entry
*find_printer
= NULL
;
258 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
259 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
266 /****************************************************************************
267 Close printer index by handle.
268 ****************************************************************************/
270 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
272 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
275 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
279 close_policy_hnd(p
, hnd
);
284 /****************************************************************************
285 Delete a printer given a handle.
286 ****************************************************************************/
287 WERROR
delete_printer_hook( NT_USER_TOKEN
*token
, const char *sharename
)
289 char *cmd
= lp_deleteprinter_cmd();
292 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
293 BOOL is_print_op
= False
;
295 /* can't fail if we don't try */
300 pstr_sprintf(command
, "%s \"%s\"", cmd
, sharename
);
303 is_print_op
= user_has_privileges( token
, &se_printop
);
305 DEBUG(10,("Running [%s]\n", command
));
307 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
312 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
313 /* Tell everyone we updated smb.conf. */
314 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
320 /********** END SePrintOperatorPrivlege BLOCK **********/
322 DEBUGADD(10,("returned [%d]\n", ret
));
325 return WERR_BADFID
; /* What to return here? */
327 /* go ahead and re-read the services immediately */
328 reload_services( False
);
330 if ( lp_servicenumber( sharename
) < 0 )
331 return WERR_ACCESS_DENIED
;
336 /****************************************************************************
337 Delete a printer given a handle.
338 ****************************************************************************/
340 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
342 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
345 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
350 * It turns out that Windows allows delete printer on a handle
351 * opened by an admin user, then used on a pipe handle created
352 * by an anonymous user..... but they're working on security.... riiight !
356 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
357 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
358 return WERR_ACCESS_DENIED
;
361 /* this does not need a become root since the access check has been
362 done on the handle already */
364 if (del_a_printer( Printer
->sharename
) != 0) {
365 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
369 return delete_printer_hook( p
->pipe_user
.nt_user_token
, Printer
->sharename
);
372 /****************************************************************************
373 Return the snum of a printer corresponding to an handle.
374 ****************************************************************************/
376 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
378 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
381 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
385 switch (Printer
->printer_type
) {
387 DEBUG(4,("short name:%s\n", Printer
->sharename
));
388 *number
= print_queue_snum(Printer
->sharename
);
389 return (*number
!= -1);
397 /****************************************************************************
398 Set printer handle type.
399 Check if it's \\server or \\server\printer
400 ****************************************************************************/
402 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
404 DEBUG(3,("Setting printer type=%s\n", handlename
));
406 if ( strlen(handlename
) < 3 ) {
407 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
411 /* it's a print server */
412 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
413 DEBUGADD(4,("Printer is a print server\n"));
414 Printer
->printer_type
= SPLHND_SERVER
;
416 /* it's a printer (set_printer_hnd_name() will handle port monitors */
418 DEBUGADD(4,("Printer is a printer\n"));
419 Printer
->printer_type
= SPLHND_PRINTER
;
425 /****************************************************************************
426 Set printer handle name.. Accept names like \\server, \\server\printer,
427 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
428 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
429 XcvDataPort() interface.
430 ****************************************************************************/
432 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
435 int n_services
=lp_numservices();
436 char *aprinter
, *printername
;
437 const char *servername
;
440 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
443 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
, (unsigned long)strlen(handlename
)));
445 aprinter
= handlename
;
446 if ( *handlename
== '\\' ) {
447 servername
= handlename
+ 2;
448 if ( (aprinter
= strchr_m( handlename
+2, '\\' )) != NULL
) {
457 /* save the servername to fill in replies on this handle */
459 if ( !is_myname_or_ipaddr( servername
) )
462 fstrcpy( Printer
->servername
, servername
);
464 if ( Printer
->printer_type
== SPLHND_SERVER
)
467 if ( Printer
->printer_type
!= SPLHND_PRINTER
)
470 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
472 /* check for the Port Monitor Interface */
474 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
475 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
476 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
479 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
480 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
481 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
485 /* Search all sharenames first as this is easier than pulling
486 the printer_info_2 off of disk. Don't use find_service() since
487 that calls out to map_username() */
489 /* do another loop to look for printernames */
491 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
493 /* no point going on if this is not a printer */
495 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
498 fstrcpy(sname
, lp_servicename(snum
));
499 if ( strequal( aprinter
, sname
) ) {
504 /* no point looking up the printer object if
505 we aren't allowing printername != sharename */
507 if ( lp_force_printername(snum
) )
510 fstrcpy(sname
, lp_servicename(snum
));
513 result
= get_a_printer( NULL
, &printer
, 2, sname
);
514 if ( !W_ERROR_IS_OK(result
) ) {
515 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
516 sname
, dos_errstr(result
)));
520 /* printername is always returned as \\server\printername */
521 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
522 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
523 printer
->info_2
->printername
));
524 free_a_printer( &printer
, 2);
530 if ( strequal(printername
, aprinter
) ) {
531 free_a_printer( &printer
, 2);
536 DEBUGADD(10, ("printername: %s\n", printername
));
538 free_a_printer( &printer
, 2);
541 free_a_printer( &printer
, 2);
544 DEBUGADD(4,("Printer not found\n"));
548 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
550 fstrcpy(Printer
->sharename
, sname
);
555 /****************************************************************************
556 Find first available printer slot. creates a printer handle for you.
557 ****************************************************************************/
559 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
561 Printer_entry
*new_printer
;
563 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
565 if((new_printer
=SMB_MALLOC_P(Printer_entry
)) == NULL
)
568 ZERO_STRUCTP(new_printer
);
570 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
571 SAFE_FREE(new_printer
);
575 /* Add to the internal list. */
576 DLIST_ADD(printers_list
, new_printer
);
578 new_printer
->notify
.option
=NULL
;
580 if ( !(new_printer
->ctx
= talloc_init("Printer Entry [%p]", hnd
)) ) {
581 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
582 close_printer_handle(p
, hnd
);
586 if (!set_printer_hnd_printertype(new_printer
, name
)) {
587 close_printer_handle(p
, hnd
);
591 if (!set_printer_hnd_name(new_printer
, name
)) {
592 close_printer_handle(p
, hnd
);
596 new_printer
->access_granted
= access_granted
;
598 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
603 /***************************************************************************
604 check to see if the client motify handle is monitoring the notification
605 given by (notify_type, notify_field).
606 **************************************************************************/
608 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
614 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
617 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
621 * Flags should always be zero when the change notify
622 * is registered by the client's spooler. A user Win32 app
623 * might use the flags though instead of the NOTIFY_OPTION_INFO
632 return is_monitoring_event_flags(
633 p
->notify
.flags
, notify_type
, notify_field
);
635 for (i
= 0; i
< option
->count
; i
++) {
637 /* Check match for notify_type */
639 if (option
->ctr
.type
[i
].type
!= notify_type
)
642 /* Check match for field */
644 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
645 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
651 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
652 p
->servername
, p
->sharename
, notify_type
, notify_field
));
657 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
659 static void notify_one_value(struct spoolss_notify_msg
*msg
,
660 SPOOL_NOTIFY_INFO_DATA
*data
,
663 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
664 data
->notify_data
.value
[1] = 0;
667 static void notify_string(struct spoolss_notify_msg
*msg
,
668 SPOOL_NOTIFY_INFO_DATA
*data
,
673 /* The length of the message includes the trailing \0 */
675 init_unistr2(&unistr
, msg
->notify
.data
, UNI_STR_TERMINATE
);
677 data
->notify_data
.data
.length
= msg
->len
* 2;
678 data
->notify_data
.data
.string
= TALLOC_ARRAY(mem_ctx
, uint16
, msg
->len
);
680 if (!data
->notify_data
.data
.string
) {
681 data
->notify_data
.data
.length
= 0;
685 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
688 static void notify_system_time(struct spoolss_notify_msg
*msg
,
689 SPOOL_NOTIFY_INFO_DATA
*data
,
695 if (msg
->len
!= sizeof(time_t)) {
696 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
701 if (!prs_init(&ps
, RPC_MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
702 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
706 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
707 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
712 if (!spoolss_io_system_time("", &ps
, 0, &systime
)) {
717 data
->notify_data
.data
.length
= prs_offset(&ps
);
718 data
->notify_data
.data
.string
= (uint16
*)
719 TALLOC(mem_ctx
, prs_offset(&ps
));
720 if (!data
->notify_data
.data
.string
) {
725 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
730 struct notify2_message_table
{
732 void (*fn
)(struct spoolss_notify_msg
*msg
,
733 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
736 static struct notify2_message_table printer_notify_table
[] = {
737 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
738 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
739 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
740 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
741 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
742 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
743 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
744 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
745 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
746 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
747 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
748 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
749 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
750 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
751 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
752 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
753 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
754 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
755 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
758 static struct notify2_message_table job_notify_table
[] = {
759 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
760 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
761 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
762 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
763 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
764 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
765 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
766 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
767 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
768 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
769 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
770 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
771 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
772 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
773 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
774 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
775 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
776 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
777 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
778 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
779 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
780 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
781 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
782 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
786 /***********************************************************************
787 Allocate talloc context for container object
788 **********************************************************************/
790 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
795 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
800 /***********************************************************************
801 release all allocated memory and zero out structure
802 **********************************************************************/
804 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
810 talloc_destroy(ctr
->ctx
);
817 /***********************************************************************
818 **********************************************************************/
820 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
828 /***********************************************************************
829 **********************************************************************/
831 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
833 if ( !ctr
|| !ctr
->msg_groups
)
836 if ( idx
>= ctr
->num_groups
)
839 return &ctr
->msg_groups
[idx
];
843 /***********************************************************************
844 How many groups of change messages do we have ?
845 **********************************************************************/
847 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
852 return ctr
->num_groups
;
855 /***********************************************************************
856 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
857 **********************************************************************/
859 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
861 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
862 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
863 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
869 /* loop over all groups looking for a matching printer name */
871 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
872 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
876 /* add a new group? */
878 if ( i
== ctr
->num_groups
) {
881 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
882 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
885 ctr
->msg_groups
= groups
;
887 /* clear the new entry and set the printer name */
889 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
890 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
893 /* add the change messages; 'i' is the correct index now regardless */
895 msg_grp
= &ctr
->msg_groups
[i
];
899 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
900 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
903 msg_grp
->msgs
= msg_list
;
905 new_slot
= msg_grp
->num_msgs
-1;
906 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
908 /* need to allocate own copy of data */
911 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
912 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
914 return ctr
->num_groups
;
917 /***********************************************************************
918 Send a change notication message on all handles which have a call
920 **********************************************************************/
922 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
925 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
926 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
927 SPOOLSS_NOTIFY_MSG
*messages
;
928 int sending_msg_count
;
931 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
935 messages
= msg_group
->msgs
;
938 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
942 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
944 /* loop over all printers */
946 for (p
= printers_list
; p
; p
= p
->next
) {
947 SPOOL_NOTIFY_INFO_DATA
*data
;
952 /* Is there notification on this handle? */
954 if ( !p
->notify
.client_connected
)
957 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
959 /* For this printer? Print servers always receive
962 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
963 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
966 DEBUG(10,("Our printer\n"));
968 /* allocate the max entries possible */
970 data
= TALLOC_ARRAY( mem_ctx
, SPOOL_NOTIFY_INFO_DATA
, msg_group
->num_msgs
);
977 /* build the array of change notifications */
979 sending_msg_count
= 0;
981 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
982 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
984 /* Are we monitoring this event? */
986 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
992 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
993 msg
->type
, msg
->field
, p
->sharename
));
996 * if the is a printer notification handle and not a job notification
997 * type, then set the id to 0. Other wise just use what was specified
1000 * When registering change notification on a print server handle
1001 * we always need to send back the id (snum) matching the printer
1002 * for which the change took place. For change notify registered
1003 * on a printer handle, this does not matter and the id should be 0.
1008 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1014 /* Convert unix jobid to smb jobid */
1016 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1017 id
= sysjob_to_jobid(msg
->id
);
1020 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1025 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1028 case PRINTER_NOTIFY_TYPE
:
1029 if ( printer_notify_table
[msg
->field
].fn
)
1030 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1033 case JOB_NOTIFY_TYPE
:
1034 if ( job_notify_table
[msg
->field
].fn
)
1035 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1039 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1046 if ( sending_msg_count
) {
1047 rpccli_spoolss_rrpcn( notify_cli_pipe
, mem_ctx
, &p
->notify
.client_hnd
,
1048 data_len
, data
, p
->notify
.change
, 0 );
1053 DEBUG(8,("send_notify2_changes: Exit...\n"));
1057 /***********************************************************************
1058 **********************************************************************/
1060 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1063 uint32 tv_sec
, tv_usec
;
1066 /* Unpack message */
1068 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1071 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddddd",
1073 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1076 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1077 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1079 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1080 &msg
->len
, &msg
->notify
.data
);
1082 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1083 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1085 tv
->tv_sec
= tv_sec
;
1086 tv
->tv_usec
= tv_usec
;
1089 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1090 msg
->notify
.value
[1]));
1092 dump_data(3, msg
->notify
.data
, msg
->len
);
1097 /********************************************************************
1098 Receive a notify2 message list
1099 ********************************************************************/
1101 static void receive_notify2_message_list(int msg_type
, struct process_id src
,
1102 void *msg
, size_t len
,
1105 size_t msg_count
, i
;
1106 char *buf
= (char *)msg
;
1109 SPOOLSS_NOTIFY_MSG notify
;
1110 SPOOLSS_NOTIFY_MSG_CTR messages
;
1114 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1118 msg_count
= IVAL(buf
, 0);
1121 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1123 if (msg_count
== 0) {
1124 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1128 /* initialize the container */
1130 ZERO_STRUCT( messages
);
1131 notify_msg_ctr_init( &messages
);
1134 * build message groups for each printer identified
1135 * in a change_notify msg. Remember that a PCN message
1136 * includes the handle returned for the srv_spoolss_replyopenprinter()
1137 * call. Therefore messages are grouped according to printer handle.
1140 for ( i
=0; i
<msg_count
; i
++ ) {
1141 struct timeval msg_tv
;
1143 if (msg_ptr
+ 4 - buf
> len
) {
1144 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1148 msg_len
= IVAL(msg_ptr
,0);
1151 if (msg_ptr
+ msg_len
- buf
> len
) {
1152 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1156 /* unpack messages */
1158 ZERO_STRUCT( notify
);
1159 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1162 /* add to correct list in container */
1164 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1166 /* free memory that might have been allocated by notify2_unpack_msg() */
1168 if ( notify
.len
!= 0 )
1169 SAFE_FREE( notify
.notify
.data
);
1172 /* process each group of messages */
1174 num_groups
= notify_msg_ctr_numgroups( &messages
);
1175 for ( i
=0; i
<num_groups
; i
++ )
1176 send_notify2_changes( &messages
, i
);
1181 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1183 notify_msg_ctr_destroy( &messages
);
1188 /********************************************************************
1189 Send a message to ourself about new driver being installed
1190 so we can upgrade the information for each printer bound to this
1192 ********************************************************************/
1194 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1196 int len
= strlen(drivername
);
1201 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1204 message_send_pid(pid_to_procid(sys_getpid()),
1205 MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1210 /**********************************************************************
1211 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1212 over all printers, upgrading ones as necessary
1213 **********************************************************************/
1215 void do_drv_upgrade_printer(int msg_type
, struct process_id src
,
1216 void *buf
, size_t len
, void *private_data
)
1220 int n_services
= lp_numservices();
1222 len
= MIN(len
,sizeof(drivername
)-1);
1223 strncpy(drivername
, (const char *)buf
, len
);
1225 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1227 /* Iterate the printer list */
1229 for (snum
=0; snum
<n_services
; snum
++)
1231 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1234 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1236 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1237 if (!W_ERROR_IS_OK(result
))
1240 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1242 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1244 /* all we care about currently is the change_id */
1246 result
= mod_a_printer(printer
, 2);
1247 if (!W_ERROR_IS_OK(result
)) {
1248 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1249 dos_errstr(result
)));
1253 free_a_printer(&printer
, 2);
1260 /********************************************************************
1261 Update the cache for all printq's with a registered client
1263 ********************************************************************/
1265 void update_monitored_printq_cache( void )
1267 Printer_entry
*printer
= printers_list
;
1270 /* loop through all printers and update the cache where
1271 client_connected == True */
1274 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1275 && printer
->notify
.client_connected
)
1277 snum
= print_queue_snum(printer
->sharename
);
1278 print_queue_status( snum
, NULL
, NULL
);
1281 printer
= printer
->next
;
1286 /********************************************************************
1287 Send a message to ourself about new driver being installed
1288 so we can upgrade the information for each printer bound to this
1290 ********************************************************************/
1292 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1294 int len
= strlen(drivername
);
1299 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1302 message_send_pid(pid_to_procid(sys_getpid()),
1303 MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1308 /**********************************************************************
1309 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1310 over all printers, resetting printer data as neessary
1311 **********************************************************************/
1313 void reset_all_printerdata(int msg_type
, struct process_id src
,
1314 void *buf
, size_t len
, void *private_data
)
1318 int n_services
= lp_numservices();
1320 len
= MIN( len
, sizeof(drivername
)-1 );
1321 strncpy( drivername
, (const char *)buf
, len
);
1323 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1325 /* Iterate the printer list */
1327 for ( snum
=0; snum
<n_services
; snum
++ )
1329 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1332 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1334 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1335 if ( !W_ERROR_IS_OK(result
) )
1339 * if the printer is bound to the driver,
1340 * then reset to the new driver initdata
1343 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1345 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1347 if ( !set_driver_init(printer
, 2) ) {
1348 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1349 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1352 result
= mod_a_printer( printer
, 2 );
1353 if ( !W_ERROR_IS_OK(result
) ) {
1354 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1355 get_dos_error_msg(result
)));
1359 free_a_printer( &printer
, 2 );
1368 /********************************************************************
1369 Copy routines used by convert_to_openprinterex()
1370 *******************************************************************/
1372 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1380 DEBUG (8,("dup_devmode\n"));
1382 /* bulk copy first */
1384 d
= (DEVICEMODE
*)TALLOC_MEMDUP(ctx
, devmode
, sizeof(DEVICEMODE
));
1388 /* dup the pointer members separately */
1390 len
= unistrlen(devmode
->devicename
.buffer
);
1392 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1393 if (!d
->devicename
.buffer
) {
1396 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1401 len
= unistrlen(devmode
->formname
.buffer
);
1403 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1404 if (!d
->devicename
.buffer
) {
1407 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1411 d
->dev_private
= (uint8
*)TALLOC_MEMDUP(ctx
, devmode
->dev_private
,
1412 devmode
->driverextra
);
1413 if (!d
->dev_private
) {
1419 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1421 if (!new_ctr
|| !ctr
)
1424 DEBUG(8,("copy_devmode_ctr\n"));
1426 new_ctr
->size
= ctr
->size
;
1427 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1429 if(ctr
->devmode_ptr
)
1430 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1433 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1435 if (!new_def
|| !def
)
1438 DEBUG(8,("copy_printer_defaults\n"));
1440 new_def
->datatype_ptr
= def
->datatype_ptr
;
1442 if (def
->datatype_ptr
)
1443 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1445 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1447 new_def
->access_required
= def
->access_required
;
1450 /********************************************************************
1451 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1452 * SPOOL_Q_OPEN_PRINTER_EX structure
1453 ********************************************************************/
1455 static WERROR
convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1457 if (!q_u_ex
|| !q_u
)
1460 DEBUG(8,("convert_to_openprinterex\n"));
1462 if ( q_u
->printername
) {
1463 q_u_ex
->printername
= TALLOC_ZERO_P( ctx
, UNISTR2
);
1464 if (q_u_ex
->printername
== NULL
)
1466 copy_unistr2(q_u_ex
->printername
, q_u
->printername
);
1469 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1474 /********************************************************************
1475 * spoolss_open_printer
1477 * called from the spoolss dispatcher
1478 ********************************************************************/
1480 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1482 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1483 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1488 ZERO_STRUCT(q_u_ex
);
1489 ZERO_STRUCT(r_u_ex
);
1491 /* convert the OpenPrinter() call to OpenPrinterEx() */
1493 r_u_ex
.status
= convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1494 if (!W_ERROR_IS_OK(r_u_ex
.status
))
1495 return r_u_ex
.status
;
1497 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1499 /* convert back to OpenPrinter() */
1501 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1506 /********************************************************************
1507 ********************************************************************/
1509 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1511 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1512 POLICY_HND
*handle
= &r_u
->handle
;
1516 struct current_user user
;
1517 Printer_entry
*Printer
=NULL
;
1519 if ( !q_u
->printername
)
1520 return WERR_INVALID_PRINTER_NAME
;
1522 /* some sanity check because you can open a printer or a print server */
1523 /* aka: \\server\printer or \\server */
1525 unistr2_to_ascii(name
, q_u
->printername
, sizeof(name
)-1);
1527 DEBUGADD(3,("checking name: %s\n",name
));
1529 if (!open_printer_hnd(p
, handle
, name
, 0))
1530 return WERR_INVALID_PRINTER_NAME
;
1532 Printer
=find_printer_index_by_hnd(p
, handle
);
1534 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1535 "handle we created for printer %s\n", name
));
1536 close_printer_handle(p
,handle
);
1537 return WERR_INVALID_PRINTER_NAME
;
1540 get_current_user(&user
, p
);
1543 * First case: the user is opening the print server:
1545 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1546 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1548 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1549 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1550 * or if the user is listed in the smb.conf printer admin parameter.
1552 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1553 * client view printer folder, but does not show the MSAPW.
1555 * Note: this test needs code to check access rights here too. Jeremy
1556 * could you look at this?
1558 * Second case: the user is opening a printer:
1559 * NT doesn't let us connect to a printer if the connecting user
1560 * doesn't have print permission.
1562 * Third case: user is opening a Port Monitor
1563 * access checks same as opening a handle to the print server.
1566 switch (Printer
->printer_type
)
1569 case SPLHND_PORTMON_TCP
:
1570 case SPLHND_PORTMON_LOCAL
:
1571 /* Printserver handles use global struct... */
1575 /* Map standard access rights to object specific access rights */
1577 se_map_standard(&printer_default
->access_required
,
1578 &printserver_std_mapping
);
1580 /* Deny any object specific bits that don't apply to print
1581 servers (i.e printer and job specific bits) */
1583 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1585 if (printer_default
->access_required
&
1586 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1587 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1588 close_printer_handle(p
, handle
);
1589 return WERR_ACCESS_DENIED
;
1592 /* Allow admin access */
1594 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1596 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1598 if (!lp_ms_add_printer_wizard()) {
1599 close_printer_handle(p
, handle
);
1600 return WERR_ACCESS_DENIED
;
1603 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1604 and not a printer admin, then fail */
1606 if ((user
.ut
.uid
!= 0) &&
1607 !user_has_privileges(user
.nt_user_token
,
1609 !token_contains_name_in_list(
1610 uidtoname(user
.ut
.uid
), NULL
,
1612 lp_printer_admin(snum
))) {
1613 close_printer_handle(p
, handle
);
1614 return WERR_ACCESS_DENIED
;
1617 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1621 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1624 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1625 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1627 /* We fall through to return WERR_OK */
1630 case SPLHND_PRINTER
:
1631 /* NT doesn't let us connect to a printer if the connecting user
1632 doesn't have print permission. */
1634 if (!get_printer_snum(p
, handle
, &snum
)) {
1635 close_printer_handle(p
, handle
);
1639 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1641 /* map an empty access mask to the minimum access mask */
1642 if (printer_default
->access_required
== 0x0)
1643 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1646 * If we are not serving the printer driver for this printer,
1647 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1648 * will keep NT clients happy --jerry
1651 if (lp_use_client_driver(snum
)
1652 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1654 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1657 /* check smb.conf parameters and the the sec_desc */
1659 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1660 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1661 return WERR_ACCESS_DENIED
;
1664 if (!user_ok_token(uidtoname(user
.ut
.uid
), user
.nt_user_token
,
1666 !print_access_check(&user
, snum
,
1667 printer_default
->access_required
)) {
1668 DEBUG(3, ("access DENIED for printer open\n"));
1669 close_printer_handle(p
, handle
);
1670 return WERR_ACCESS_DENIED
;
1673 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1674 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1675 close_printer_handle(p
, handle
);
1676 return WERR_ACCESS_DENIED
;
1679 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1680 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1682 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1684 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1685 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1690 /* sanity check to prevent programmer error */
1694 Printer
->access_granted
= printer_default
->access_required
;
1697 * If the client sent a devmode in the OpenPrinter() call, then
1698 * save it here in case we get a job submission on this handle
1701 if ( (Printer
->printer_type
!= SPLHND_SERVER
)
1702 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1704 convert_devicemode( Printer
->sharename
, q_u
->printer_default
.devmode_cont
.devmode
,
1705 &Printer
->nt_devmode
);
1708 #if 0 /* JERRY -- I'm doubtful this is really effective */
1709 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1710 optimization in Windows 2000 clients --jerry */
1712 if ( (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1713 && (RA_WIN2K
== get_remote_arch()) )
1715 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1716 sys_usleep( 500000 );
1723 /****************************************************************************
1724 ****************************************************************************/
1726 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1727 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1733 /* allocate memory if needed. Messy because
1734 convert_printer_info is used to update an existing
1735 printer or build a new one */
1737 if ( !printer
->info_2
) {
1738 printer
->info_2
= TALLOC_ZERO_P( printer
, NT_PRINTER_INFO_LEVEL_2
);
1739 if ( !printer
->info_2
) {
1740 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1745 ret
= uni_2_asc_printer_info_2(uni
->info_2
, printer
->info_2
);
1746 printer
->info_2
->setuptime
= time(NULL
);
1754 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1755 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1761 printer
->info_3
=NULL
;
1762 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1766 printer
->info_6
=NULL
;
1767 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1777 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1778 NT_DEVICEMODE
**pp_nt_devmode
)
1780 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1783 * Ensure nt_devmode is a valid pointer
1784 * as we will be overwriting it.
1787 if (nt_devmode
== NULL
) {
1788 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1789 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1793 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1794 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1796 nt_devmode
->specversion
=devmode
->specversion
;
1797 nt_devmode
->driverversion
=devmode
->driverversion
;
1798 nt_devmode
->size
=devmode
->size
;
1799 nt_devmode
->fields
=devmode
->fields
;
1800 nt_devmode
->orientation
=devmode
->orientation
;
1801 nt_devmode
->papersize
=devmode
->papersize
;
1802 nt_devmode
->paperlength
=devmode
->paperlength
;
1803 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1804 nt_devmode
->scale
=devmode
->scale
;
1805 nt_devmode
->copies
=devmode
->copies
;
1806 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1807 nt_devmode
->printquality
=devmode
->printquality
;
1808 nt_devmode
->color
=devmode
->color
;
1809 nt_devmode
->duplex
=devmode
->duplex
;
1810 nt_devmode
->yresolution
=devmode
->yresolution
;
1811 nt_devmode
->ttoption
=devmode
->ttoption
;
1812 nt_devmode
->collate
=devmode
->collate
;
1814 nt_devmode
->logpixels
=devmode
->logpixels
;
1815 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1816 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1817 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1818 nt_devmode
->displayflags
=devmode
->displayflags
;
1819 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1820 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1821 nt_devmode
->icmintent
=devmode
->icmintent
;
1822 nt_devmode
->mediatype
=devmode
->mediatype
;
1823 nt_devmode
->dithertype
=devmode
->dithertype
;
1824 nt_devmode
->reserved1
=devmode
->reserved1
;
1825 nt_devmode
->reserved2
=devmode
->reserved2
;
1826 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1827 nt_devmode
->panningheight
=devmode
->panningheight
;
1830 * Only change private and driverextra if the incoming devmode
1831 * has a new one. JRA.
1834 if ((devmode
->driverextra
!= 0) && (devmode
->dev_private
!= NULL
)) {
1835 SAFE_FREE(nt_devmode
->nt_dev_private
);
1836 nt_devmode
->driverextra
=devmode
->driverextra
;
1837 if((nt_devmode
->nt_dev_private
=SMB_MALLOC_ARRAY(uint8
, nt_devmode
->driverextra
)) == NULL
)
1839 memcpy(nt_devmode
->nt_dev_private
, devmode
->dev_private
, nt_devmode
->driverextra
);
1842 *pp_nt_devmode
= nt_devmode
;
1847 /********************************************************************
1848 * _spoolss_enddocprinter_internal.
1849 ********************************************************************/
1851 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1853 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1857 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1861 if (!get_printer_snum(p
, handle
, &snum
))
1864 Printer
->document_started
=False
;
1865 print_job_end(snum
, Printer
->jobid
,NORMAL_CLOSE
);
1866 /* error codes unhandled so far ... */
1871 /********************************************************************
1872 * api_spoolss_closeprinter
1873 ********************************************************************/
1875 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1877 POLICY_HND
*handle
= &q_u
->handle
;
1879 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1881 if (Printer
&& Printer
->document_started
)
1882 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1884 if (!close_printer_handle(p
, handle
))
1887 /* clear the returned printer handle. Observed behavior
1888 from Win2k server. Don't think this really matters.
1889 Previous code just copied the value of the closed
1892 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1897 /********************************************************************
1898 * api_spoolss_deleteprinter
1900 ********************************************************************/
1902 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1904 POLICY_HND
*handle
= &q_u
->handle
;
1905 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1908 if (Printer
&& Printer
->document_started
)
1909 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1911 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1913 result
= delete_printer_handle(p
, handle
);
1915 update_c_setprinter(False
);
1920 /*******************************************************************
1921 * static function to lookup the version id corresponding to an
1922 * long architecture string
1923 ******************************************************************/
1925 static int get_version_id (char * arch
)
1928 struct table_node archi_table
[]= {
1930 {"Windows 4.0", "WIN40", 0 },
1931 {"Windows NT x86", "W32X86", 2 },
1932 {"Windows NT R4000", "W32MIPS", 2 },
1933 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1934 {"Windows NT PowerPC", "W32PPC", 2 },
1935 {"Windows IA64", "IA64", 3 },
1936 {"Windows x64", "x64", 3 },
1940 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1942 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1943 return (archi_table
[i
].version
);
1949 /********************************************************************
1950 * _spoolss_deleteprinterdriver
1951 ********************************************************************/
1953 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1957 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1958 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1960 struct current_user user
;
1962 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1963 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1965 get_current_user(&user
, p
);
1967 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1968 and not a printer admin, then fail */
1970 if ( (user
.ut
.uid
!= 0)
1971 && !user_has_privileges(user
.nt_user_token
, &se_printop
)
1972 && !token_contains_name_in_list( uidtoname(user
.ut
.uid
),
1973 NULL
, user
.nt_user_token
, lp_printer_admin(-1)) )
1975 return WERR_ACCESS_DENIED
;
1978 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1979 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1981 /* check that we have a valid driver name first */
1983 if ((version
=get_version_id(arch
)) == -1)
1984 return WERR_INVALID_ENVIRONMENT
;
1987 ZERO_STRUCT(info_win2k
);
1989 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1991 /* try for Win2k driver if "Windows NT x86" */
1993 if ( version
== 2 ) {
1995 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1996 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2000 /* otherwise it was a failure */
2002 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2008 if (printer_driver_in_use(info
.info_3
)) {
2009 status
= WERR_PRINTER_DRIVER_IN_USE
;
2015 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2017 /* if we get to here, we now have 2 driver info structures to remove */
2018 /* remove the Win2k driver first*/
2020 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
2021 free_a_printer_driver( info_win2k
, 3 );
2023 /* this should not have failed---if it did, report to client */
2024 if ( !W_ERROR_IS_OK(status_win2k
) )
2026 status
= status_win2k
;
2032 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
2034 /* if at least one of the deletes succeeded return OK */
2036 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2040 free_a_printer_driver( info
, 3 );
2045 /********************************************************************
2046 * spoolss_deleteprinterdriverex
2047 ********************************************************************/
2049 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
2053 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2054 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2056 uint32 flags
= q_u
->delete_flags
;
2058 struct current_user user
;
2060 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2061 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2063 get_current_user(&user
, p
);
2065 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2066 and not a printer admin, then fail */
2068 if ( (user
.ut
.uid
!= 0)
2069 && !user_has_privileges(user
.nt_user_token
, &se_printop
)
2070 && !token_contains_name_in_list( uidtoname(user
.ut
.uid
),
2071 NULL
, user
.nt_user_token
, lp_printer_admin(-1)) )
2073 return WERR_ACCESS_DENIED
;
2076 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2077 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2079 /* check that we have a valid driver name first */
2080 if ((version
=get_version_id(arch
)) == -1) {
2081 /* this is what NT returns */
2082 return WERR_INVALID_ENVIRONMENT
;
2085 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2086 version
= q_u
->version
;
2089 ZERO_STRUCT(info_win2k
);
2091 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2093 if ( !W_ERROR_IS_OK(status
) )
2096 * if the client asked for a specific version,
2097 * or this is something other than Windows NT x86,
2101 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2104 /* try for Win2k driver if "Windows NT x86" */
2107 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2108 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2113 if ( printer_driver_in_use(info
.info_3
) ) {
2114 status
= WERR_PRINTER_DRIVER_IN_USE
;
2119 * we have a couple of cases to consider.
2120 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2121 * then the delete should fail if **any** files overlap with
2123 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2124 * non-overlapping files
2125 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2126 * is set, the do not delete any files
2127 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2130 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2132 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2134 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2135 /* no idea of the correct error here */
2136 status
= WERR_ACCESS_DENIED
;
2141 /* also check for W32X86/3 if necessary; maybe we already have? */
2143 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2144 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2147 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2148 /* no idea of the correct error here */
2149 free_a_printer_driver( info_win2k
, 3 );
2150 status
= WERR_ACCESS_DENIED
;
2154 /* if we get to here, we now have 2 driver info structures to remove */
2155 /* remove the Win2k driver first*/
2157 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2158 free_a_printer_driver( info_win2k
, 3 );
2160 /* this should not have failed---if it did, report to client */
2162 if ( !W_ERROR_IS_OK(status_win2k
) )
2167 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2169 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2172 free_a_printer_driver( info
, 3 );
2178 /****************************************************************************
2179 Internal routine for retreiving printerdata
2180 ***************************************************************************/
2182 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2183 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2184 uint32
*needed
, uint32 in_size
)
2186 REGISTRY_VALUE
*val
;
2190 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2191 return WERR_BADFILE
;
2193 *type
= regval_type( val
);
2195 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2197 size
= regval_size( val
);
2199 /* copy the min(in_size, len) */
2202 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2204 /* special case for 0 length values */
2206 if ( (*data
= (uint8
*)TALLOC_MEMDUP(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2210 if ( (*data
= (uint8
*)TALLOC_ZERO(ctx
, in_size
)) == NULL
)
2219 DEBUG(5,("get_printer_dataex: copy done\n"));
2224 /****************************************************************************
2225 Internal routine for removing printerdata
2226 ***************************************************************************/
2228 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2230 return delete_printer_data( printer
->info_2
, key
, value
);
2233 /****************************************************************************
2234 Internal routine for storing printerdata
2235 ***************************************************************************/
2237 WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2238 uint32 type
, uint8
*data
, int real_len
)
2240 /* the registry objects enforce uniqueness based on value name */
2242 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2245 /********************************************************************
2246 GetPrinterData on a printer server Handle.
2247 ********************************************************************/
2249 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2253 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2255 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2257 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2263 if (!StrCaseCmp(value
, "BeepEnabled")) {
2265 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2267 SIVAL(*data
, 0, 0x00);
2272 if (!StrCaseCmp(value
, "EventLog")) {
2274 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2276 /* formally was 0x1b */
2277 SIVAL(*data
, 0, 0x0);
2282 if (!StrCaseCmp(value
, "NetPopup")) {
2284 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2286 SIVAL(*data
, 0, 0x00);
2291 if (!StrCaseCmp(value
, "MajorVersion")) {
2293 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2296 /* Windows NT 4.0 seems to not allow uploading of drivers
2297 to a server that reports 0x3 as the MajorVersion.
2298 need to investigate more how Win2k gets around this .
2301 if ( RA_WINNT
== get_remote_arch() )
2310 if (!StrCaseCmp(value
, "MinorVersion")) {
2312 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2320 * uint32 size = 0x114
2322 * uint32 minor = [0|1]
2323 * uint32 build = [2195|2600]
2324 * extra unicode string = e.g. "Service Pack 3"
2326 if (!StrCaseCmp(value
, "OSVersion")) {
2330 if ( !(*data
= TALLOC_ZERO_ARRAY(ctx
, uint8
, (*needed
> in_size
) ? *needed
:in_size
)) )
2333 SIVAL(*data
, 0, *needed
); /* size */
2334 SIVAL(*data
, 4, 5); /* Windows 2000 == 5.0 */
2336 SIVAL(*data
, 12, 2195); /* build */
2338 /* leave extra string empty */
2344 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2345 const char *string
="C:\\PRINTERS";
2347 *needed
= 2*(strlen(string
)+1);
2348 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2350 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2352 /* it's done by hand ready to go on the wire */
2353 for (i
=0; i
<strlen(string
); i
++) {
2354 (*data
)[2*i
]=string
[i
];
2355 (*data
)[2*i
+1]='\0';
2360 if (!StrCaseCmp(value
, "Architecture")) {
2361 const char *string
="Windows NT x86";
2363 *needed
= 2*(strlen(string
)+1);
2364 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2366 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2367 for (i
=0; i
<strlen(string
); i
++) {
2368 (*data
)[2*i
]=string
[i
];
2369 (*data
)[2*i
+1]='\0';
2374 if (!StrCaseCmp(value
, "DsPresent")) {
2376 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2379 /* only show the publish check box if we are a
2380 memeber of a AD domain */
2382 if ( lp_security() == SEC_ADS
)
2383 SIVAL(*data
, 0, 0x01);
2385 SIVAL(*data
, 0, 0x00);
2391 if (!StrCaseCmp(value
, "DNSMachineName")) {
2394 if (!get_mydnsfullname(hostname
))
2395 return WERR_BADFILE
;
2397 *needed
= 2*(strlen(hostname
)+1);
2398 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2400 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2401 for (i
=0; i
<strlen(hostname
); i
++) {
2402 (*data
)[2*i
]=hostname
[i
];
2403 (*data
)[2*i
+1]='\0';
2409 return WERR_BADFILE
;
2412 /********************************************************************
2413 * spoolss_getprinterdata
2414 ********************************************************************/
2416 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2418 POLICY_HND
*handle
= &q_u
->handle
;
2419 UNISTR2
*valuename
= &q_u
->valuename
;
2420 uint32 in_size
= q_u
->size
;
2421 uint32
*type
= &r_u
->type
;
2422 uint32
*out_size
= &r_u
->size
;
2423 uint8
**data
= &r_u
->data
;
2424 uint32
*needed
= &r_u
->needed
;
2427 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2428 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2432 * Reminder: when it's a string, the length is in BYTES
2433 * even if UNICODE is negociated.
2438 *out_size
= in_size
;
2440 /* in case of problem, return some default values */
2445 DEBUG(4,("_spoolss_getprinterdata\n"));
2448 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2449 status
= WERR_BADFID
;
2453 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2455 if ( Printer
->printer_type
== SPLHND_SERVER
)
2456 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2459 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2460 status
= WERR_BADFID
;
2464 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2465 if ( !W_ERROR_IS_OK(status
) )
2468 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2470 if ( strequal(value
, "ChangeId") ) {
2472 *needed
= sizeof(uint32
);
2473 if ( (*data
= (uint8
*)TALLOC(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2474 status
= WERR_NOMEM
;
2477 SIVAL( *data
, 0, printer
->info_2
->changeid
);
2481 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2484 if (*needed
> *out_size
)
2485 status
= WERR_MORE_DATA
;
2488 if ( !W_ERROR_IS_OK(status
) )
2490 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2492 /* reply this param doesn't exist */
2495 if((*data
=(uint8
*)TALLOC_ZERO_ARRAY(p
->mem_ctx
, uint8
, *out_size
)) == NULL
) {
2497 free_a_printer( &printer
, 2 );
2506 /* cleanup & exit */
2509 free_a_printer( &printer
, 2 );
2514 /*********************************************************
2515 Connect to the client machine.
2516 **********************************************************/
2518 static BOOL
spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2519 struct in_addr
*client_ip
, const char *remote_machine
)
2522 struct cli_state
*the_cli
;
2523 struct in_addr rm_addr
;
2525 if ( is_zero_ip(*client_ip
) ) {
2526 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20) ) {
2527 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2531 if ( ismyip( rm_addr
)) {
2532 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2536 rm_addr
.s_addr
= client_ip
->s_addr
;
2537 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2538 inet_ntoa(*client_ip
) ));
2541 /* setup the connection */
2543 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2544 &rm_addr
, 0, "IPC$", "IPC",
2548 0, lp_client_signing(), NULL
);
2550 if ( !NT_STATUS_IS_OK( ret
) ) {
2551 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2556 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2557 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2558 cli_shutdown(the_cli
);
2563 * Ok - we have an anonymous connection to the IPC$ share.
2564 * Now start the NT Domain stuff :-).
2567 if ( !(*pp_pipe
= cli_rpc_pipe_open_noauth(the_cli
, PI_SPOOLSS
, &ret
)) ) {
2568 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2569 remote_machine
, nt_errstr(ret
)));
2570 cli_shutdown(the_cli
);
2574 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2576 (*pp_pipe
)->cli
= the_cli
;
2581 /***************************************************************************
2582 Connect to the client.
2583 ****************************************************************************/
2585 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2586 uint32 localprinter
, uint32 type
,
2587 POLICY_HND
*handle
, struct in_addr
*client_ip
)
2592 * If it's the first connection, contact the client
2593 * and connect to the IPC$ share anonymously
2595 if (smb_connections
==0) {
2596 fstring unix_printer
;
2598 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2600 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ip
, unix_printer
))
2603 message_register(MSG_PRINTER_NOTIFY2
,
2604 receive_notify2_message_list
, NULL
);
2605 /* Tell the connections db we're now interested in printer
2606 * notify messages. */
2607 register_message_flags( True
, FLAG_MSG_PRINT_NOTIFY
);
2611 * Tell the specific printing tdb we want messages for this printer
2612 * by registering our PID.
2615 if (!print_notify_register_pid(snum
))
2616 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2620 result
= rpccli_spoolss_reply_open_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, printer
, localprinter
,
2623 if (!W_ERROR_IS_OK(result
))
2624 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2625 dos_errstr(result
)));
2627 return (W_ERROR_IS_OK(result
));
2630 /********************************************************************
2632 * ReplyFindFirstPrinterChangeNotifyEx
2634 * before replying OK: status=0 a rpc call is made to the workstation
2635 * asking ReplyOpenPrinter
2637 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2638 * called from api_spoolss_rffpcnex
2639 ********************************************************************/
2641 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2643 POLICY_HND
*handle
= &q_u
->handle
;
2644 uint32 flags
= q_u
->flags
;
2645 uint32 options
= q_u
->options
;
2646 UNISTR2
*localmachine
= &q_u
->localmachine
;
2647 uint32 printerlocal
= q_u
->printerlocal
;
2649 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2650 struct in_addr client_ip
;
2652 /* store the notify value in the printer struct */
2654 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2657 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2661 Printer
->notify
.flags
=flags
;
2662 Printer
->notify
.options
=options
;
2663 Printer
->notify
.printerlocal
=printerlocal
;
2665 if (Printer
->notify
.option
)
2666 free_spool_notify_option(&Printer
->notify
.option
);
2668 Printer
->notify
.option
=dup_spool_notify_option(option
);
2670 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2671 sizeof(Printer
->notify
.localmachine
)-1);
2673 /* Connect to the client machine and send a ReplyOpenPrinter */
2675 if ( Printer
->printer_type
== SPLHND_SERVER
)
2677 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2678 !get_printer_snum(p
, handle
, &snum
) )
2681 client_ip
.s_addr
= inet_addr(p
->conn
->client_address
);
2683 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2684 Printer
->notify
.printerlocal
, 1,
2685 &Printer
->notify
.client_hnd
, &client_ip
))
2686 return WERR_SERVER_UNAVAILABLE
;
2688 Printer
->notify
.client_connected
=True
;
2693 /*******************************************************************
2694 * fill a notify_info_data with the servername
2695 ********************************************************************/
2697 void spoolss_notify_server_name(int snum
,
2698 SPOOL_NOTIFY_INFO_DATA
*data
,
2699 print_queue_struct
*queue
,
2700 NT_PRINTER_INFO_LEVEL
*printer
,
2701 TALLOC_CTX
*mem_ctx
)
2706 len
= rpcstr_push(temp
, printer
->info_2
->servername
, sizeof(temp
)-2, STR_TERMINATE
);
2708 data
->notify_data
.data
.length
= len
;
2709 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2711 if (!data
->notify_data
.data
.string
) {
2712 data
->notify_data
.data
.length
= 0;
2716 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2719 /*******************************************************************
2720 * fill a notify_info_data with the printername (not including the servername).
2721 ********************************************************************/
2723 void spoolss_notify_printer_name(int snum
,
2724 SPOOL_NOTIFY_INFO_DATA
*data
,
2725 print_queue_struct
*queue
,
2726 NT_PRINTER_INFO_LEVEL
*printer
,
2727 TALLOC_CTX
*mem_ctx
)
2732 /* the notify name should not contain the \\server\ part */
2733 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2736 p
= printer
->info_2
->printername
;
2741 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2743 data
->notify_data
.data
.length
= len
;
2744 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2746 if (!data
->notify_data
.data
.string
) {
2747 data
->notify_data
.data
.length
= 0;
2751 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2754 /*******************************************************************
2755 * fill a notify_info_data with the servicename
2756 ********************************************************************/
2758 void spoolss_notify_share_name(int snum
,
2759 SPOOL_NOTIFY_INFO_DATA
*data
,
2760 print_queue_struct
*queue
,
2761 NT_PRINTER_INFO_LEVEL
*printer
,
2762 TALLOC_CTX
*mem_ctx
)
2767 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2769 data
->notify_data
.data
.length
= len
;
2770 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2772 if (!data
->notify_data
.data
.string
) {
2773 data
->notify_data
.data
.length
= 0;
2777 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2780 /*******************************************************************
2781 * fill a notify_info_data with the port name
2782 ********************************************************************/
2784 void spoolss_notify_port_name(int snum
,
2785 SPOOL_NOTIFY_INFO_DATA
*data
,
2786 print_queue_struct
*queue
,
2787 NT_PRINTER_INFO_LEVEL
*printer
,
2788 TALLOC_CTX
*mem_ctx
)
2793 /* even if it's strange, that's consistant in all the code */
2795 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2797 data
->notify_data
.data
.length
= len
;
2798 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2800 if (!data
->notify_data
.data
.string
) {
2801 data
->notify_data
.data
.length
= 0;
2805 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2808 /*******************************************************************
2809 * fill a notify_info_data with the printername
2810 * but it doesn't exist, have to see what to do
2811 ********************************************************************/
2813 void spoolss_notify_driver_name(int snum
,
2814 SPOOL_NOTIFY_INFO_DATA
*data
,
2815 print_queue_struct
*queue
,
2816 NT_PRINTER_INFO_LEVEL
*printer
,
2817 TALLOC_CTX
*mem_ctx
)
2822 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2824 data
->notify_data
.data
.length
= len
;
2825 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2827 if (!data
->notify_data
.data
.string
) {
2828 data
->notify_data
.data
.length
= 0;
2832 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2835 /*******************************************************************
2836 * fill a notify_info_data with the comment
2837 ********************************************************************/
2839 void spoolss_notify_comment(int snum
,
2840 SPOOL_NOTIFY_INFO_DATA
*data
,
2841 print_queue_struct
*queue
,
2842 NT_PRINTER_INFO_LEVEL
*printer
,
2843 TALLOC_CTX
*mem_ctx
)
2848 if (*printer
->info_2
->comment
== '\0')
2849 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2851 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2853 data
->notify_data
.data
.length
= len
;
2854 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2856 if (!data
->notify_data
.data
.string
) {
2857 data
->notify_data
.data
.length
= 0;
2861 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2864 /*******************************************************************
2865 * fill a notify_info_data with the comment
2866 * location = "Room 1, floor 2, building 3"
2867 ********************************************************************/
2869 void spoolss_notify_location(int snum
,
2870 SPOOL_NOTIFY_INFO_DATA
*data
,
2871 print_queue_struct
*queue
,
2872 NT_PRINTER_INFO_LEVEL
*printer
,
2873 TALLOC_CTX
*mem_ctx
)
2878 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2880 data
->notify_data
.data
.length
= len
;
2881 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2883 if (!data
->notify_data
.data
.string
) {
2884 data
->notify_data
.data
.length
= 0;
2888 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2891 /*******************************************************************
2892 * fill a notify_info_data with the device mode
2893 * jfm:xxxx don't to it for know but that's a real problem !!!
2894 ********************************************************************/
2896 static void spoolss_notify_devmode(int snum
,
2897 SPOOL_NOTIFY_INFO_DATA
*data
,
2898 print_queue_struct
*queue
,
2899 NT_PRINTER_INFO_LEVEL
*printer
,
2900 TALLOC_CTX
*mem_ctx
)
2902 /* for a dummy implementation we have to zero the fields */
2903 data
->notify_data
.data
.length
= 0;
2904 data
->notify_data
.data
.string
= NULL
;
2907 /*******************************************************************
2908 * fill a notify_info_data with the separator file name
2909 ********************************************************************/
2911 void spoolss_notify_sepfile(int snum
,
2912 SPOOL_NOTIFY_INFO_DATA
*data
,
2913 print_queue_struct
*queue
,
2914 NT_PRINTER_INFO_LEVEL
*printer
,
2915 TALLOC_CTX
*mem_ctx
)
2920 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, 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 print processor
2935 * jfm:xxxx return always winprint to indicate we don't do anything to it
2936 ********************************************************************/
2938 void spoolss_notify_print_processor(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
->printprocessor
, 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 print processor options
2962 * jfm:xxxx send an empty string
2963 ********************************************************************/
2965 void spoolss_notify_parameters(int snum
,
2966 SPOOL_NOTIFY_INFO_DATA
*data
,
2967 print_queue_struct
*queue
,
2968 NT_PRINTER_INFO_LEVEL
*printer
,
2969 TALLOC_CTX
*mem_ctx
)
2974 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
2976 data
->notify_data
.data
.length
= len
;
2977 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2979 if (!data
->notify_data
.data
.string
) {
2980 data
->notify_data
.data
.length
= 0;
2984 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2987 /*******************************************************************
2988 * fill a notify_info_data with the data type
2989 * jfm:xxxx always send RAW as data type
2990 ********************************************************************/
2992 void spoolss_notify_datatype(int snum
,
2993 SPOOL_NOTIFY_INFO_DATA
*data
,
2994 print_queue_struct
*queue
,
2995 NT_PRINTER_INFO_LEVEL
*printer
,
2996 TALLOC_CTX
*mem_ctx
)
3001 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
3003 data
->notify_data
.data
.length
= len
;
3004 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3006 if (!data
->notify_data
.data
.string
) {
3007 data
->notify_data
.data
.length
= 0;
3011 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3014 /*******************************************************************
3015 * fill a notify_info_data with the security descriptor
3016 * jfm:xxxx send an null pointer to say no security desc
3017 * have to implement security before !
3018 ********************************************************************/
3020 static void spoolss_notify_security_desc(int snum
,
3021 SPOOL_NOTIFY_INFO_DATA
*data
,
3022 print_queue_struct
*queue
,
3023 NT_PRINTER_INFO_LEVEL
*printer
,
3024 TALLOC_CTX
*mem_ctx
)
3026 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
3027 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
3030 /*******************************************************************
3031 * fill a notify_info_data with the attributes
3032 * jfm:xxxx a samba printer is always shared
3033 ********************************************************************/
3035 void spoolss_notify_attributes(int snum
,
3036 SPOOL_NOTIFY_INFO_DATA
*data
,
3037 print_queue_struct
*queue
,
3038 NT_PRINTER_INFO_LEVEL
*printer
,
3039 TALLOC_CTX
*mem_ctx
)
3041 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
3042 data
->notify_data
.value
[1] = 0;
3045 /*******************************************************************
3046 * fill a notify_info_data with the priority
3047 ********************************************************************/
3049 static void spoolss_notify_priority(int snum
,
3050 SPOOL_NOTIFY_INFO_DATA
*data
,
3051 print_queue_struct
*queue
,
3052 NT_PRINTER_INFO_LEVEL
*printer
,
3053 TALLOC_CTX
*mem_ctx
)
3055 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
3056 data
->notify_data
.value
[1] = 0;
3059 /*******************************************************************
3060 * fill a notify_info_data with the default priority
3061 ********************************************************************/
3063 static void spoolss_notify_default_priority(int snum
,
3064 SPOOL_NOTIFY_INFO_DATA
*data
,
3065 print_queue_struct
*queue
,
3066 NT_PRINTER_INFO_LEVEL
*printer
,
3067 TALLOC_CTX
*mem_ctx
)
3069 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
3070 data
->notify_data
.value
[1] = 0;
3073 /*******************************************************************
3074 * fill a notify_info_data with the start time
3075 ********************************************************************/
3077 static void spoolss_notify_start_time(int snum
,
3078 SPOOL_NOTIFY_INFO_DATA
*data
,
3079 print_queue_struct
*queue
,
3080 NT_PRINTER_INFO_LEVEL
*printer
,
3081 TALLOC_CTX
*mem_ctx
)
3083 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
3084 data
->notify_data
.value
[1] = 0;
3087 /*******************************************************************
3088 * fill a notify_info_data with the until time
3089 ********************************************************************/
3091 static void spoolss_notify_until_time(int snum
,
3092 SPOOL_NOTIFY_INFO_DATA
*data
,
3093 print_queue_struct
*queue
,
3094 NT_PRINTER_INFO_LEVEL
*printer
,
3095 TALLOC_CTX
*mem_ctx
)
3097 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3098 data
->notify_data
.value
[1] = 0;
3101 /*******************************************************************
3102 * fill a notify_info_data with the status
3103 ********************************************************************/
3105 static void spoolss_notify_status(int snum
,
3106 SPOOL_NOTIFY_INFO_DATA
*data
,
3107 print_queue_struct
*queue
,
3108 NT_PRINTER_INFO_LEVEL
*printer
,
3109 TALLOC_CTX
*mem_ctx
)
3111 print_status_struct status
;
3113 print_queue_length(snum
, &status
);
3114 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3115 data
->notify_data
.value
[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the number of jobs queued
3120 ********************************************************************/
3122 void spoolss_notify_cjobs(int snum
,
3123 SPOOL_NOTIFY_INFO_DATA
*data
,
3124 print_queue_struct
*queue
,
3125 NT_PRINTER_INFO_LEVEL
*printer
,
3126 TALLOC_CTX
*mem_ctx
)
3128 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3129 data
->notify_data
.value
[1] = 0;
3132 /*******************************************************************
3133 * fill a notify_info_data with the average ppm
3134 ********************************************************************/
3136 static void spoolss_notify_average_ppm(int snum
,
3137 SPOOL_NOTIFY_INFO_DATA
*data
,
3138 print_queue_struct
*queue
,
3139 NT_PRINTER_INFO_LEVEL
*printer
,
3140 TALLOC_CTX
*mem_ctx
)
3142 /* always respond 8 pages per minutes */
3143 /* a little hard ! */
3144 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3145 data
->notify_data
.value
[1] = 0;
3148 /*******************************************************************
3149 * fill a notify_info_data with username
3150 ********************************************************************/
3152 static void spoolss_notify_username(int snum
,
3153 SPOOL_NOTIFY_INFO_DATA
*data
,
3154 print_queue_struct
*queue
,
3155 NT_PRINTER_INFO_LEVEL
*printer
,
3156 TALLOC_CTX
*mem_ctx
)
3161 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3163 data
->notify_data
.data
.length
= len
;
3164 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3166 if (!data
->notify_data
.data
.string
) {
3167 data
->notify_data
.data
.length
= 0;
3171 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3174 /*******************************************************************
3175 * fill a notify_info_data with job status
3176 ********************************************************************/
3178 static void spoolss_notify_job_status(int snum
,
3179 SPOOL_NOTIFY_INFO_DATA
*data
,
3180 print_queue_struct
*queue
,
3181 NT_PRINTER_INFO_LEVEL
*printer
,
3182 TALLOC_CTX
*mem_ctx
)
3184 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3185 data
->notify_data
.value
[1] = 0;
3188 /*******************************************************************
3189 * fill a notify_info_data with job name
3190 ********************************************************************/
3192 static void spoolss_notify_job_name(int snum
,
3193 SPOOL_NOTIFY_INFO_DATA
*data
,
3194 print_queue_struct
*queue
,
3195 NT_PRINTER_INFO_LEVEL
*printer
,
3196 TALLOC_CTX
*mem_ctx
)
3201 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3203 data
->notify_data
.data
.length
= len
;
3204 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3206 if (!data
->notify_data
.data
.string
) {
3207 data
->notify_data
.data
.length
= 0;
3211 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3214 /*******************************************************************
3215 * fill a notify_info_data with job status
3216 ********************************************************************/
3218 static void spoolss_notify_job_status_string(int snum
,
3219 SPOOL_NOTIFY_INFO_DATA
*data
,
3220 print_queue_struct
*queue
,
3221 NT_PRINTER_INFO_LEVEL
*printer
,
3222 TALLOC_CTX
*mem_ctx
)
3225 * Now we're returning job status codes we just return a "" here. JRA.
3232 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3235 switch (queue
->status
) {
3240 p
= ""; /* NT provides the paused string */
3249 #endif /* NO LONGER NEEDED. */
3251 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3253 data
->notify_data
.data
.length
= len
;
3254 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3256 if (!data
->notify_data
.data
.string
) {
3257 data
->notify_data
.data
.length
= 0;
3261 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3264 /*******************************************************************
3265 * fill a notify_info_data with job time
3266 ********************************************************************/
3268 static void spoolss_notify_job_time(int snum
,
3269 SPOOL_NOTIFY_INFO_DATA
*data
,
3270 print_queue_struct
*queue
,
3271 NT_PRINTER_INFO_LEVEL
*printer
,
3272 TALLOC_CTX
*mem_ctx
)
3274 data
->notify_data
.value
[0]=0x0;
3275 data
->notify_data
.value
[1]=0;
3278 /*******************************************************************
3279 * fill a notify_info_data with job size
3280 ********************************************************************/
3282 static void spoolss_notify_job_size(int snum
,
3283 SPOOL_NOTIFY_INFO_DATA
*data
,
3284 print_queue_struct
*queue
,
3285 NT_PRINTER_INFO_LEVEL
*printer
,
3286 TALLOC_CTX
*mem_ctx
)
3288 data
->notify_data
.value
[0]=queue
->size
;
3289 data
->notify_data
.value
[1]=0;
3292 /*******************************************************************
3293 * fill a notify_info_data with page info
3294 ********************************************************************/
3295 static void spoolss_notify_total_pages(int snum
,
3296 SPOOL_NOTIFY_INFO_DATA
*data
,
3297 print_queue_struct
*queue
,
3298 NT_PRINTER_INFO_LEVEL
*printer
,
3299 TALLOC_CTX
*mem_ctx
)
3301 data
->notify_data
.value
[0]=queue
->page_count
;
3302 data
->notify_data
.value
[1]=0;
3305 /*******************************************************************
3306 * fill a notify_info_data with pages printed info.
3307 ********************************************************************/
3308 static void spoolss_notify_pages_printed(int snum
,
3309 SPOOL_NOTIFY_INFO_DATA
*data
,
3310 print_queue_struct
*queue
,
3311 NT_PRINTER_INFO_LEVEL
*printer
,
3312 TALLOC_CTX
*mem_ctx
)
3314 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3315 data
->notify_data
.value
[1]=0;
3318 /*******************************************************************
3319 Fill a notify_info_data with job position.
3320 ********************************************************************/
3322 static void spoolss_notify_job_position(int snum
,
3323 SPOOL_NOTIFY_INFO_DATA
*data
,
3324 print_queue_struct
*queue
,
3325 NT_PRINTER_INFO_LEVEL
*printer
,
3326 TALLOC_CTX
*mem_ctx
)
3328 data
->notify_data
.value
[0]=queue
->job
;
3329 data
->notify_data
.value
[1]=0;
3332 /*******************************************************************
3333 Fill a notify_info_data with submitted time.
3334 ********************************************************************/
3336 static void spoolss_notify_submitted_time(int snum
,
3337 SPOOL_NOTIFY_INFO_DATA
*data
,
3338 print_queue_struct
*queue
,
3339 NT_PRINTER_INFO_LEVEL
*printer
,
3340 TALLOC_CTX
*mem_ctx
)
3347 t
=gmtime(&queue
->time
);
3349 len
= sizeof(SYSTEMTIME
);
3351 data
->notify_data
.data
.length
= len
;
3352 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3354 if (!data
->notify_data
.data
.string
) {
3355 data
->notify_data
.data
.length
= 0;
3359 make_systemtime(&st
, t
);
3362 * Systemtime must be linearized as a set of UINT16's.
3363 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3366 p
= (char *)data
->notify_data
.data
.string
;
3367 SSVAL(p
, 0, st
.year
);
3368 SSVAL(p
, 2, st
.month
);
3369 SSVAL(p
, 4, st
.dayofweek
);
3370 SSVAL(p
, 6, st
.day
);
3371 SSVAL(p
, 8, st
.hour
);
3372 SSVAL(p
, 10, st
.minute
);
3373 SSVAL(p
, 12, st
.second
);
3374 SSVAL(p
, 14, st
.milliseconds
);
3377 struct s_notify_info_data_table
3383 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3384 print_queue_struct
*queue
,
3385 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3388 /* A table describing the various print notification constants and
3389 whether the notification data is a pointer to a variable sized
3390 buffer, a one value uint32 or a two value uint32. */
3392 static const struct s_notify_info_data_table notify_info_data_table
[] =
3394 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3395 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3396 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3397 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3398 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3399 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3400 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3401 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3402 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3403 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3404 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3405 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3406 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3407 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3408 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3409 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3410 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3411 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3412 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3413 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3414 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3415 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3416 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3417 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3418 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3419 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3420 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3421 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3422 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3423 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3424 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3425 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3426 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3427 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3428 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3429 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3430 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3431 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3432 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3433 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3434 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3435 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3436 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3437 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3438 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3439 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3440 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3441 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3442 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3443 { PRINT_TABLE_END
, 0x0, NULL
, 0x0, NULL
},
3446 /*******************************************************************
3447 Return the size of info_data structure.
3448 ********************************************************************/
3450 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3454 for (i
= 0; i
< (sizeof(notify_info_data_table
)/sizeof(struct s_notify_info_data_table
)); i
++) {
3455 if ( (notify_info_data_table
[i
].type
== type
)
3456 && (notify_info_data_table
[i
].field
== field
) ) {
3457 switch(notify_info_data_table
[i
].size
) {
3458 case NOTIFY_ONE_VALUE
:
3459 case NOTIFY_TWO_VALUE
:
3464 /* The only pointer notify data I have seen on
3465 the wire is the submitted time and this has
3466 the notify size set to 4. -tpot */
3468 case NOTIFY_POINTER
:
3471 case NOTIFY_SECDESC
:
3477 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3482 /*******************************************************************
3483 Return the type of notify_info_data.
3484 ********************************************************************/
3486 static uint32
type_of_notify_info_data(uint16 type
, uint16 field
)
3490 for (i
= 0; i
< (sizeof(notify_info_data_table
)/sizeof(struct s_notify_info_data_table
)); i
++) {
3491 if (notify_info_data_table
[i
].type
== type
&&
3492 notify_info_data_table
[i
].field
== field
)
3493 return notify_info_data_table
[i
].size
;
3499 /****************************************************************************
3500 ****************************************************************************/
3502 static BOOL
search_notify(uint16 type
, uint16 field
, int *value
)
3506 for (i
= 0; notify_info_data_table
[i
].type
!= PRINT_TABLE_END
; i
++) {
3507 if (notify_info_data_table
[i
].type
== type
&&
3508 notify_info_data_table
[i
].field
== field
&&
3509 notify_info_data_table
[i
].fn
!= NULL
) {
3518 /****************************************************************************
3519 ****************************************************************************/
3521 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3523 info_data
->type
= type
;
3524 info_data
->field
= field
;
3525 info_data
->reserved
= 0;
3527 info_data
->size
= size_of_notify_info_data(type
, field
);
3528 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3533 /*******************************************************************
3535 * fill a notify_info struct with info asked
3537 ********************************************************************/
3539 static BOOL
construct_notify_printer_info(Printer_entry
*print_hnd
, SPOOL_NOTIFY_INFO
*info
, int
3540 snum
, SPOOL_NOTIFY_OPTION_TYPE
3541 *option_type
, uint32 id
,
3542 TALLOC_CTX
*mem_ctx
)
3548 SPOOL_NOTIFY_INFO_DATA
*current_data
;
3549 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3550 print_queue_struct
*queue
=NULL
;
3552 type
=option_type
->type
;
3554 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3555 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3556 option_type
->count
, lp_servicename(snum
)));
3558 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3561 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3562 field
= option_type
->fields
[field_num
];
3564 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3566 if (!search_notify(type
, field
, &j
) )
3569 if((info
->data
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3570 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3571 free_a_printer(&printer
, 2);
3575 current_data
= &info
->data
[info
->count
];
3577 construct_info_data(current_data
, type
, field
, id
);
3579 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3580 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3582 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3588 free_a_printer(&printer
, 2);
3592 /*******************************************************************
3594 * fill a notify_info struct with info asked
3596 ********************************************************************/
3598 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3599 SPOOL_NOTIFY_INFO
*info
,
3600 NT_PRINTER_INFO_LEVEL
*printer
,
3601 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3602 *option_type
, uint32 id
,
3603 TALLOC_CTX
*mem_ctx
)
3609 SPOOL_NOTIFY_INFO_DATA
*current_data
;
3611 DEBUG(4,("construct_notify_jobs_info\n"));
3613 type
= option_type
->type
;
3615 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3616 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3617 option_type
->count
));
3619 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3620 field
= option_type
->fields
[field_num
];
3622 if (!search_notify(type
, field
, &j
) )
3625 if((info
->data
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3626 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3630 current_data
=&(info
->data
[info
->count
]);
3632 construct_info_data(current_data
, type
, field
, id
);
3633 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3642 * JFM: The enumeration is not that simple, it's even non obvious.
3644 * let's take an example: I want to monitor the PRINTER SERVER for
3645 * the printer's name and the number of jobs currently queued.
3646 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3647 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3649 * I have 3 printers on the back of my server.
3651 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3654 * 1 printer 1 name 1
3655 * 2 printer 1 cjob 1
3656 * 3 printer 2 name 2
3657 * 4 printer 2 cjob 2
3658 * 5 printer 3 name 3
3659 * 6 printer 3 name 3
3661 * that's the print server case, the printer case is even worse.
3664 /*******************************************************************
3666 * enumerate all printers on the printserver
3667 * fill a notify_info struct with info asked
3669 ********************************************************************/
3671 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3672 SPOOL_NOTIFY_INFO
*info
,
3673 TALLOC_CTX
*mem_ctx
)
3676 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3677 int n_services
=lp_numservices();
3679 SPOOL_NOTIFY_OPTION
*option
;
3680 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3682 DEBUG(4,("printserver_notify_info\n"));
3687 option
=Printer
->notify
.option
;
3692 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3693 sending a ffpcn() request first */
3698 for (i
=0; i
<option
->count
; i
++) {
3699 option_type
=&(option
->ctr
.type
[i
]);
3701 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3704 for (snum
=0; snum
<n_services
; snum
++)
3706 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3707 construct_notify_printer_info ( Printer
, info
, snum
, option_type
, snum
, mem_ctx
);
3713 * Debugging information, don't delete.
3716 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3717 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3718 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3720 for (i
=0; i
<info
->count
; i
++) {
3721 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3722 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3723 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3730 /*******************************************************************
3732 * fill a notify_info struct with info asked
3734 ********************************************************************/
3736 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3737 TALLOC_CTX
*mem_ctx
)
3740 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3743 SPOOL_NOTIFY_OPTION
*option
;
3744 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3746 print_queue_struct
*queue
=NULL
;
3747 print_status_struct status
;
3749 DEBUG(4,("printer_notify_info\n"));
3754 option
=Printer
->notify
.option
;
3760 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3761 sending a ffpcn() request first */
3766 get_printer_snum(p
, hnd
, &snum
);
3768 for (i
=0; i
<option
->count
; i
++) {
3769 option_type
=&option
->ctr
.type
[i
];
3771 switch ( option_type
->type
) {
3772 case PRINTER_NOTIFY_TYPE
:
3773 if(construct_notify_printer_info(Printer
, info
, snum
,
3779 case JOB_NOTIFY_TYPE
: {
3780 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3782 count
= print_queue_status(snum
, &queue
, &status
);
3784 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3787 for (j
=0; j
<count
; j
++) {
3788 construct_notify_jobs_info(&queue
[j
], info
,
3795 free_a_printer(&printer
, 2);
3805 * Debugging information, don't delete.
3808 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3809 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3810 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3812 for (i=0; i<info->count; i++) {
3813 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3814 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3815 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3821 /********************************************************************
3823 ********************************************************************/
3825 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3827 POLICY_HND
*handle
= &q_u
->handle
;
3828 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3830 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3831 WERROR result
= WERR_BADFID
;
3833 /* we always have a NOTIFY_INFO struct */
3837 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3838 OUR_HANDLE(handle
)));
3842 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3845 * We are now using the change value, and
3846 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3847 * I don't have a global notification system, I'm sending back all the
3848 * informations even when _NOTHING_ has changed.
3851 /* We need to keep track of the change value to send back in
3852 RRPCN replies otherwise our updates are ignored. */
3854 Printer
->notify
.fnpcn
= True
;
3856 if (Printer
->notify
.client_connected
) {
3857 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3858 Printer
->notify
.change
= q_u
->change
;
3861 /* just ignore the SPOOL_NOTIFY_OPTION */
3863 switch (Printer
->printer_type
) {
3865 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3868 case SPLHND_PRINTER
:
3869 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3873 Printer
->notify
.fnpcn
= False
;
3879 /********************************************************************
3880 * construct_printer_info_0
3881 * fill a printer_info_0 struct
3882 ********************************************************************/
3884 static BOOL
construct_printer_info_0(Printer_entry
*print_hnd
, PRINTER_INFO_0
*printer
, int snum
)
3888 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3889 counter_printer_0
*session_counter
;
3890 uint32 global_counter
;
3893 print_status_struct status
;
3895 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3898 count
= print_queue_length(snum
, &status
);
3900 /* check if we already have a counter for this printer */
3901 for(session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3902 if (session_counter
->snum
== snum
)
3906 /* it's the first time, add it to the list */
3907 if (session_counter
==NULL
) {
3908 if((session_counter
=SMB_MALLOC_P(counter_printer_0
)) == NULL
) {
3909 free_a_printer(&ntprinter
, 2);
3912 ZERO_STRUCTP(session_counter
);
3913 session_counter
->snum
=snum
;
3914 session_counter
->counter
=0;
3915 DLIST_ADD(counter_list
, session_counter
);
3919 session_counter
->counter
++;
3922 * the global_counter should be stored in a TDB as it's common to all the clients
3923 * and should be zeroed on samba startup
3925 global_counter
=session_counter
->counter
;
3927 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3929 init_unistr(&printer
->printername
, chaine
);
3931 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_server_name(print_hnd
));
3932 init_unistr(&printer
->servername
, chaine
);
3934 printer
->cjobs
= count
;
3935 printer
->total_jobs
= 0;
3936 printer
->total_bytes
= 0;
3938 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3939 t
=gmtime(&setuptime
);
3941 printer
->year
= t
->tm_year
+1900;
3942 printer
->month
= t
->tm_mon
+1;
3943 printer
->dayofweek
= t
->tm_wday
;
3944 printer
->day
= t
->tm_mday
;
3945 printer
->hour
= t
->tm_hour
;
3946 printer
->minute
= t
->tm_min
;
3947 printer
->second
= t
->tm_sec
;
3948 printer
->milliseconds
= 0;
3950 printer
->global_counter
= global_counter
;
3951 printer
->total_pages
= 0;
3953 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3954 printer
->major_version
= 0x0005; /* NT 5 */
3955 printer
->build_version
= 0x0893; /* build 2195 */
3957 printer
->unknown7
= 0x1;
3958 printer
->unknown8
= 0x0;
3959 printer
->unknown9
= 0x0;
3960 printer
->session_counter
= session_counter
->counter
;
3961 printer
->unknown11
= 0x0;
3962 printer
->printer_errors
= 0x0; /* number of print failure */
3963 printer
->unknown13
= 0x0;
3964 printer
->unknown14
= 0x1;
3965 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3966 printer
->unknown16
= 0x0;
3967 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3968 printer
->unknown18
= 0x0;
3969 printer
->status
= nt_printq_status(status
.status
);
3970 printer
->unknown20
= 0x0;
3971 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3972 printer
->unknown22
= 0x0;
3973 printer
->unknown23
= 0x6; /* 6 ???*/
3974 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3975 printer
->unknown25
= 0;
3976 printer
->unknown26
= 0;
3977 printer
->unknown27
= 0;
3978 printer
->unknown28
= 0;
3979 printer
->unknown29
= 0;
3981 free_a_printer(&ntprinter
,2);
3985 /********************************************************************
3986 * construct_printer_info_1
3987 * fill a printer_info_1 struct
3988 ********************************************************************/
3989 static BOOL
construct_printer_info_1(Printer_entry
*print_hnd
, uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
3993 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3995 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3998 printer
->flags
=flags
;
4000 if (*ntprinter
->info_2
->comment
== '\0') {
4001 init_unistr(&printer
->comment
, lp_comment(snum
));
4002 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4003 ntprinter
->info_2
->drivername
, lp_comment(snum
));
4006 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4007 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4008 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
4011 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
4013 init_unistr(&printer
->description
, chaine
);
4014 init_unistr(&printer
->name
, chaine2
);
4016 free_a_printer(&ntprinter
,2);
4021 /****************************************************************************
4022 Free a DEVMODE struct.
4023 ****************************************************************************/
4025 static void free_dev_mode(DEVICEMODE
*dev
)
4030 SAFE_FREE(dev
->dev_private
);
4035 /****************************************************************************
4036 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4037 should be valid upon entry
4038 ****************************************************************************/
4040 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
4042 if ( !devmode
|| !ntdevmode
)
4045 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
4047 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
4049 devmode
->specversion
= ntdevmode
->specversion
;
4050 devmode
->driverversion
= ntdevmode
->driverversion
;
4051 devmode
->size
= ntdevmode
->size
;
4052 devmode
->driverextra
= ntdevmode
->driverextra
;
4053 devmode
->fields
= ntdevmode
->fields
;
4055 devmode
->orientation
= ntdevmode
->orientation
;
4056 devmode
->papersize
= ntdevmode
->papersize
;
4057 devmode
->paperlength
= ntdevmode
->paperlength
;
4058 devmode
->paperwidth
= ntdevmode
->paperwidth
;
4059 devmode
->scale
= ntdevmode
->scale
;
4060 devmode
->copies
= ntdevmode
->copies
;
4061 devmode
->defaultsource
= ntdevmode
->defaultsource
;
4062 devmode
->printquality
= ntdevmode
->printquality
;
4063 devmode
->color
= ntdevmode
->color
;
4064 devmode
->duplex
= ntdevmode
->duplex
;
4065 devmode
->yresolution
= ntdevmode
->yresolution
;
4066 devmode
->ttoption
= ntdevmode
->ttoption
;
4067 devmode
->collate
= ntdevmode
->collate
;
4068 devmode
->icmmethod
= ntdevmode
->icmmethod
;
4069 devmode
->icmintent
= ntdevmode
->icmintent
;
4070 devmode
->mediatype
= ntdevmode
->mediatype
;
4071 devmode
->dithertype
= ntdevmode
->dithertype
;
4073 if (ntdevmode
->nt_dev_private
!= NULL
) {
4074 if ((devmode
->dev_private
=(uint8
*)memdup(ntdevmode
->nt_dev_private
, ntdevmode
->driverextra
)) == NULL
)
4081 /****************************************************************************
4082 Create a DEVMODE struct. Returns malloced memory.
4083 ****************************************************************************/
4085 DEVICEMODE
*construct_dev_mode(const char *servicename
)
4087 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4088 DEVICEMODE
*devmode
= NULL
;
4090 DEBUG(7,("construct_dev_mode\n"));
4092 DEBUGADD(8,("getting printer characteristics\n"));
4094 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
4097 if ( !printer
->info_2
->devmode
) {
4098 DEBUG(5, ("BONG! There was no device mode!\n"));
4102 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) == NULL
) {
4103 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4107 ZERO_STRUCTP(devmode
);
4109 DEBUGADD(8,("loading DEVICEMODE\n"));
4111 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4112 free_dev_mode( devmode
);
4117 free_a_printer(&printer
,2);
4122 /********************************************************************
4123 * construct_printer_info_2
4124 * fill a printer_info_2 struct
4125 ********************************************************************/
4127 static BOOL
construct_printer_info_2(Printer_entry
*print_hnd
, PRINTER_INFO_2
*printer
, int snum
)
4130 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4132 print_status_struct status
;
4134 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4137 count
= print_queue_length(snum
, &status
);
4139 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4140 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4141 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4142 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4143 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4145 if (*ntprinter
->info_2
->comment
== '\0')
4146 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4148 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4150 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4151 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4152 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4153 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4154 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4156 printer
->attributes
= ntprinter
->info_2
->attributes
;
4158 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4159 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4160 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4161 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4162 printer
->status
= nt_printq_status(status
.status
); /* status */
4163 printer
->cjobs
= count
; /* jobs */
4164 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4166 if ( !(printer
->devmode
= construct_dev_mode(
4167 lp_const_servicename(snum
))) )
4168 DEBUG(8, ("Returning NULL Devicemode!\n"));
4170 printer
->secdesc
= NULL
;
4172 if ( ntprinter
->info_2
->secdesc_buf
4173 && ntprinter
->info_2
->secdesc_buf
->len
!= 0 )
4175 /* don't use talloc_steal() here unless you do a deep steal of all
4176 the SEC_DESC members */
4178 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4179 ntprinter
->info_2
->secdesc_buf
->sec
);
4182 free_a_printer(&ntprinter
, 2);
4187 /********************************************************************
4188 * construct_printer_info_3
4189 * fill a printer_info_3 struct
4190 ********************************************************************/
4192 static BOOL
construct_printer_info_3(Printer_entry
*print_hnd
, PRINTER_INFO_3
**pp_printer
, int snum
)
4194 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4195 PRINTER_INFO_3
*printer
= NULL
;
4197 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4201 if ((printer
= SMB_MALLOC_P(PRINTER_INFO_3
)) == NULL
) {
4202 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4203 free_a_printer(&ntprinter
, 2);
4207 ZERO_STRUCTP(printer
);
4209 /* These are the components of the SD we are returning. */
4211 printer
->flags
= 0x4;
4213 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4214 /* don't use talloc_steal() here unless you do a deep steal of all
4215 the SEC_DESC members */
4217 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4218 ntprinter
->info_2
->secdesc_buf
->sec
);
4221 free_a_printer(&ntprinter
, 2);
4223 *pp_printer
= printer
;
4227 /********************************************************************
4228 * construct_printer_info_4
4229 * fill a printer_info_4 struct
4230 ********************************************************************/
4232 static BOOL
construct_printer_info_4(Printer_entry
*print_hnd
, PRINTER_INFO_4
*printer
, int snum
)
4234 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4236 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4239 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4240 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4241 printer
->attributes
= ntprinter
->info_2
->attributes
;
4243 free_a_printer(&ntprinter
, 2);
4247 /********************************************************************
4248 * construct_printer_info_5
4249 * fill a printer_info_5 struct
4250 ********************************************************************/
4252 static BOOL
construct_printer_info_5(Printer_entry
*print_hnd
, PRINTER_INFO_5
*printer
, int snum
)
4254 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4256 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4259 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4260 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4261 printer
->attributes
= ntprinter
->info_2
->attributes
;
4263 /* these two are not used by NT+ according to MSDN */
4265 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4266 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4268 free_a_printer(&ntprinter
, 2);
4273 /********************************************************************
4274 * construct_printer_info_7
4275 * fill a printer_info_7 struct
4276 ********************************************************************/
4278 static BOOL
construct_printer_info_7(Printer_entry
*print_hnd
, PRINTER_INFO_7
*printer
, int snum
)
4280 char *guid_str
= NULL
;
4283 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4284 asprintf(&guid_str
, "{%s}", smb_uuid_string_static(guid
));
4285 strupper_m(guid_str
);
4286 init_unistr(&printer
->guid
, guid_str
);
4287 printer
->action
= SPOOL_DS_PUBLISH
;
4289 init_unistr(&printer
->guid
, "");
4290 printer
->action
= SPOOL_DS_UNPUBLISH
;
4296 /********************************************************************
4297 Spoolss_enumprinters.
4298 ********************************************************************/
4300 static WERROR
enum_all_printers_info_1(uint32 flags
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4304 int n_services
=lp_numservices();
4305 PRINTER_INFO_1
*printers
=NULL
;
4306 PRINTER_INFO_1 current_prt
;
4307 WERROR result
= WERR_OK
;
4309 DEBUG(4,("enum_all_printers_info_1\n"));
4311 for (snum
=0; snum
<n_services
; snum
++) {
4312 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4313 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4315 if (construct_printer_info_1(NULL
, flags
, ¤t_prt
, snum
)) {
4316 if((printers
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_1
, *returned
+1)) == NULL
) {
4317 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4321 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4323 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4329 /* check the required size. */
4330 for (i
=0; i
<*returned
; i
++)
4331 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4333 if (*needed
> offered
) {
4334 result
= WERR_INSUFFICIENT_BUFFER
;
4338 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4339 result
= WERR_NOMEM
;
4343 /* fill the buffer with the structures */
4344 for (i
=0; i
<*returned
; i
++)
4345 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4350 SAFE_FREE(printers
);
4352 if ( !W_ERROR_IS_OK(result
) )
4358 /********************************************************************
4359 enum_all_printers_info_1_local.
4360 *********************************************************************/
4362 static WERROR
enum_all_printers_info_1_local(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4364 DEBUG(4,("enum_all_printers_info_1_local\n"));
4366 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4369 /********************************************************************
4370 enum_all_printers_info_1_name.
4371 *********************************************************************/
4373 static WERROR
enum_all_printers_info_1_name(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4377 DEBUG(4,("enum_all_printers_info_1_name\n"));
4379 if ((name
[0] == '\\') && (name
[1] == '\\'))
4382 if (is_myname_or_ipaddr(s
)) {
4383 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4386 return WERR_INVALID_NAME
;
4389 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4390 /********************************************************************
4391 enum_all_printers_info_1_remote.
4392 *********************************************************************/
4394 static WERROR
enum_all_printers_info_1_remote(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4396 PRINTER_INFO_1
*printer
;
4397 fstring printername
;
4400 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4401 WERROR result
= WERR_OK
;
4403 /* JFM: currently it's more a place holder than anything else.
4404 * In the spooler world there is a notion of server registration.
4405 * the print servers are registered on the PDC (in the same domain)
4407 * We should have a TDB here. The registration is done thru an
4408 * undocumented RPC call.
4411 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4416 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", name
);
4417 slprintf(desc
, sizeof(desc
)-1,"%s", name
);
4418 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4420 init_unistr(&printer
->description
, desc
);
4421 init_unistr(&printer
->name
, printername
);
4422 init_unistr(&printer
->comment
, comment
);
4423 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4425 /* check the required size. */
4426 *needed
+= spoolss_size_printer_info_1(printer
);
4428 if (*needed
> offered
) {
4429 result
= WERR_INSUFFICIENT_BUFFER
;
4433 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4434 result
= WERR_NOMEM
;
4438 /* fill the buffer with the structures */
4439 smb_io_printer_info_1("", buffer
, printer
, 0);
4445 if ( !W_ERROR_IS_OK(result
) )
4453 /********************************************************************
4454 enum_all_printers_info_1_network.
4455 *********************************************************************/
4457 static WERROR
enum_all_printers_info_1_network(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4461 DEBUG(4,("enum_all_printers_info_1_network\n"));
4463 /* If we respond to a enum_printers level 1 on our name with flags
4464 set to PRINTER_ENUM_REMOTE with a list of printers then these
4465 printers incorrectly appear in the APW browse list.
4466 Specifically the printers for the server appear at the workgroup
4467 level where all the other servers in the domain are
4468 listed. Windows responds to this call with a
4469 WERR_CAN_NOT_COMPLETE so we should do the same. */
4471 if (name
[0] == '\\' && name
[1] == '\\')
4474 if (is_myname_or_ipaddr(s
))
4475 return WERR_CAN_NOT_COMPLETE
;
4477 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4480 /********************************************************************
4481 * api_spoolss_enumprinters
4483 * called from api_spoolss_enumprinters (see this to understand)
4484 ********************************************************************/
4486 static WERROR
enum_all_printers_info_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4490 int n_services
=lp_numservices();
4491 PRINTER_INFO_2
*printers
=NULL
;
4492 PRINTER_INFO_2 current_prt
;
4493 WERROR result
= WERR_OK
;
4497 for (snum
=0; snum
<n_services
; snum
++) {
4498 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4499 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4501 if (construct_printer_info_2(NULL
, ¤t_prt
, snum
)) {
4502 if ( !(printers
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_2
, *returned
+1)) ) {
4503 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4508 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
+ 1));
4510 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4517 /* check the required size. */
4518 for (i
=0; i
<*returned
; i
++)
4519 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4521 if (*needed
> offered
) {
4522 result
= WERR_INSUFFICIENT_BUFFER
;
4526 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4527 result
= WERR_NOMEM
;
4531 /* fill the buffer with the structures */
4532 for (i
=0; i
<*returned
; i
++)
4533 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4538 for (i
=0; i
<*returned
; i
++)
4539 free_devmode(printers
[i
].devmode
);
4541 SAFE_FREE(printers
);
4543 if ( !W_ERROR_IS_OK(result
) )
4549 /********************************************************************
4550 * handle enumeration of printers at level 1
4551 ********************************************************************/
4553 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4554 RPC_BUFFER
*buffer
, uint32 offered
,
4555 uint32
*needed
, uint32
*returned
)
4557 /* Not all the flags are equals */
4559 if (flags
& PRINTER_ENUM_LOCAL
)
4560 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4562 if (flags
& PRINTER_ENUM_NAME
)
4563 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4565 #if 0 /* JERRY - disabled for now */
4566 if (flags
& PRINTER_ENUM_REMOTE
)
4567 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4570 if (flags
& PRINTER_ENUM_NETWORK
)
4571 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4573 return WERR_OK
; /* NT4sp5 does that */
4576 /********************************************************************
4577 * handle enumeration of printers at level 2
4578 ********************************************************************/
4580 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4581 RPC_BUFFER
*buffer
, uint32 offered
,
4582 uint32
*needed
, uint32
*returned
)
4584 char *s
= servername
;
4586 if (flags
& PRINTER_ENUM_LOCAL
) {
4587 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4590 if (flags
& PRINTER_ENUM_NAME
) {
4591 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4593 if (is_myname_or_ipaddr(s
))
4594 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4596 return WERR_INVALID_NAME
;
4599 if (flags
& PRINTER_ENUM_REMOTE
)
4600 return WERR_UNKNOWN_LEVEL
;
4605 /********************************************************************
4606 * handle enumeration of printers at level 5
4607 ********************************************************************/
4609 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4610 RPC_BUFFER
*buffer
, uint32 offered
,
4611 uint32
*needed
, uint32
*returned
)
4613 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4617 /********************************************************************
4618 * api_spoolss_enumprinters
4620 * called from api_spoolss_enumprinters (see this to understand)
4621 ********************************************************************/
4623 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4625 uint32 flags
= q_u
->flags
;
4626 UNISTR2
*servername
= &q_u
->servername
;
4627 uint32 level
= q_u
->level
;
4628 RPC_BUFFER
*buffer
= NULL
;
4629 uint32 offered
= q_u
->offered
;
4630 uint32
*needed
= &r_u
->needed
;
4631 uint32
*returned
= &r_u
->returned
;
4635 /* that's an [in out] buffer */
4637 if (!q_u
->buffer
&& (offered
!=0)) {
4638 return WERR_INVALID_PARAM
;
4641 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
4642 buffer
= r_u
->buffer
;
4644 DEBUG(4,("_spoolss_enumprinters\n"));
4651 * flags==PRINTER_ENUM_NAME
4652 * if name=="" then enumerates all printers
4653 * if name!="" then enumerate the printer
4654 * flags==PRINTER_ENUM_REMOTE
4655 * name is NULL, enumerate printers
4656 * Level 2: name!="" enumerates printers, name can't be NULL
4657 * Level 3: doesn't exist
4658 * Level 4: does a local registry lookup
4659 * Level 5: same as Level 2
4662 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4667 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4669 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4671 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4676 return WERR_UNKNOWN_LEVEL
;
4679 /****************************************************************************
4680 ****************************************************************************/
4682 static WERROR
getprinter_level_0(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4684 PRINTER_INFO_0
*printer
=NULL
;
4685 WERROR result
= WERR_OK
;
4687 if((printer
=SMB_MALLOC_P(PRINTER_INFO_0
)) == NULL
)
4690 construct_printer_info_0(print_hnd
, printer
, snum
);
4692 /* check the required size. */
4693 *needed
+= spoolss_size_printer_info_0(printer
);
4695 if (*needed
> offered
) {
4696 result
= WERR_INSUFFICIENT_BUFFER
;
4700 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4701 result
= WERR_NOMEM
;
4705 /* fill the buffer with the structures */
4706 smb_io_printer_info_0("", buffer
, printer
, 0);
4716 /****************************************************************************
4717 ****************************************************************************/
4719 static WERROR
getprinter_level_1(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4721 PRINTER_INFO_1
*printer
=NULL
;
4722 WERROR result
= WERR_OK
;
4724 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4727 construct_printer_info_1(print_hnd
, PRINTER_ENUM_ICON8
, printer
, snum
);
4729 /* check the required size. */
4730 *needed
+= spoolss_size_printer_info_1(printer
);
4732 if (*needed
> offered
) {
4733 result
= WERR_INSUFFICIENT_BUFFER
;
4737 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4738 result
= WERR_NOMEM
;
4742 /* fill the buffer with the structures */
4743 smb_io_printer_info_1("", buffer
, printer
, 0);
4752 /****************************************************************************
4753 ****************************************************************************/
4755 static WERROR
getprinter_level_2(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4757 PRINTER_INFO_2
*printer
=NULL
;
4758 WERROR result
= WERR_OK
;
4760 if((printer
=SMB_MALLOC_P(PRINTER_INFO_2
))==NULL
)
4763 construct_printer_info_2(print_hnd
, printer
, snum
);
4765 /* check the required size. */
4766 *needed
+= spoolss_size_printer_info_2(printer
);
4768 if (*needed
> offered
) {
4769 result
= WERR_INSUFFICIENT_BUFFER
;
4773 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4774 result
= WERR_NOMEM
;
4778 /* fill the buffer with the structures */
4779 if (!smb_io_printer_info_2("", buffer
, printer
, 0))
4780 result
= WERR_NOMEM
;
4784 free_printer_info_2(printer
);
4789 /****************************************************************************
4790 ****************************************************************************/
4792 static WERROR
getprinter_level_3(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4794 PRINTER_INFO_3
*printer
=NULL
;
4795 WERROR result
= WERR_OK
;
4797 if (!construct_printer_info_3(print_hnd
, &printer
, snum
))
4800 /* check the required size. */
4801 *needed
+= spoolss_size_printer_info_3(printer
);
4803 if (*needed
> offered
) {
4804 result
= WERR_INSUFFICIENT_BUFFER
;
4808 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4809 result
= WERR_NOMEM
;
4813 /* fill the buffer with the structures */
4814 smb_io_printer_info_3("", buffer
, printer
, 0);
4818 free_printer_info_3(printer
);
4823 /****************************************************************************
4824 ****************************************************************************/
4826 static WERROR
getprinter_level_4(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4828 PRINTER_INFO_4
*printer
=NULL
;
4829 WERROR result
= WERR_OK
;
4831 if((printer
=SMB_MALLOC_P(PRINTER_INFO_4
))==NULL
)
4834 if (!construct_printer_info_4(print_hnd
, printer
, snum
)) {
4839 /* check the required size. */
4840 *needed
+= spoolss_size_printer_info_4(printer
);
4842 if (*needed
> offered
) {
4843 result
= WERR_INSUFFICIENT_BUFFER
;
4847 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4848 result
= WERR_NOMEM
;
4852 /* fill the buffer with the structures */
4853 smb_io_printer_info_4("", buffer
, printer
, 0);
4857 free_printer_info_4(printer
);
4862 /****************************************************************************
4863 ****************************************************************************/
4865 static WERROR
getprinter_level_5(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4867 PRINTER_INFO_5
*printer
=NULL
;
4868 WERROR result
= WERR_OK
;
4870 if((printer
=SMB_MALLOC_P(PRINTER_INFO_5
))==NULL
)
4873 if (!construct_printer_info_5(print_hnd
, printer
, snum
)) {
4874 free_printer_info_5(printer
);
4878 /* check the required size. */
4879 *needed
+= spoolss_size_printer_info_5(printer
);
4881 if (*needed
> offered
) {
4882 result
= WERR_INSUFFICIENT_BUFFER
;
4886 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4887 result
= WERR_NOMEM
;
4891 /* fill the buffer with the structures */
4892 smb_io_printer_info_5("", buffer
, printer
, 0);
4896 free_printer_info_5(printer
);
4901 static WERROR
getprinter_level_7(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4903 PRINTER_INFO_7
*printer
=NULL
;
4904 WERROR result
= WERR_OK
;
4906 if((printer
=SMB_MALLOC_P(PRINTER_INFO_7
))==NULL
)
4909 if (!construct_printer_info_7(print_hnd
, printer
, snum
))
4912 /* check the required size. */
4913 *needed
+= spoolss_size_printer_info_7(printer
);
4915 if (*needed
> offered
) {
4916 result
= WERR_INSUFFICIENT_BUFFER
;
4920 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4921 result
= WERR_NOMEM
;
4926 /* fill the buffer with the structures */
4927 smb_io_printer_info_7("", buffer
, printer
, 0);
4931 free_printer_info_7(printer
);
4936 /****************************************************************************
4937 ****************************************************************************/
4939 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4941 POLICY_HND
*handle
= &q_u
->handle
;
4942 uint32 level
= q_u
->level
;
4943 RPC_BUFFER
*buffer
= NULL
;
4944 uint32 offered
= q_u
->offered
;
4945 uint32
*needed
= &r_u
->needed
;
4946 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
4950 /* that's an [in out] buffer */
4952 if (!q_u
->buffer
&& (offered
!=0)) {
4953 return WERR_INVALID_PARAM
;
4956 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
4957 buffer
= r_u
->buffer
;
4961 if (!get_printer_snum(p
, handle
, &snum
))
4966 return getprinter_level_0(Printer
, snum
, buffer
, offered
, needed
);
4968 return getprinter_level_1(Printer
, snum
, buffer
, offered
, needed
);
4970 return getprinter_level_2(Printer
, snum
, buffer
, offered
, needed
);
4972 return getprinter_level_3(Printer
, snum
, buffer
, offered
, needed
);
4974 return getprinter_level_4(Printer
, snum
, buffer
, offered
, needed
);
4976 return getprinter_level_5(Printer
, snum
, buffer
, offered
, needed
);
4978 return getprinter_level_7(Printer
, snum
, buffer
, offered
, needed
);
4980 return WERR_UNKNOWN_LEVEL
;
4983 /********************************************************************
4984 * fill a DRIVER_INFO_1 struct
4985 ********************************************************************/
4987 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4989 init_unistr( &info
->name
, driver
.info_3
->name
);
4992 /********************************************************************
4993 * construct_printer_driver_info_1
4994 ********************************************************************/
4996 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4998 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4999 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5001 ZERO_STRUCT(driver
);
5003 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5004 return WERR_INVALID_PRINTER_NAME
;
5006 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5007 free_a_printer(&printer
, 2);
5008 return WERR_UNKNOWN_PRINTER_DRIVER
;
5011 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
5013 free_a_printer(&printer
,2);
5018 /********************************************************************
5019 * construct_printer_driver_info_2
5020 * fill a printer_info_2 struct
5021 ********************************************************************/
5023 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5027 info
->version
=driver
.info_3
->cversion
;
5029 init_unistr( &info
->name
, driver
.info_3
->name
);
5030 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5033 if (strlen(driver
.info_3
->driverpath
)) {
5034 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5035 init_unistr( &info
->driverpath
, temp
);
5037 init_unistr( &info
->driverpath
, "" );
5039 if (strlen(driver
.info_3
->datafile
)) {
5040 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5041 init_unistr( &info
->datafile
, temp
);
5043 init_unistr( &info
->datafile
, "" );
5045 if (strlen(driver
.info_3
->configfile
)) {
5046 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5047 init_unistr( &info
->configfile
, temp
);
5049 init_unistr( &info
->configfile
, "" );
5052 /********************************************************************
5053 * construct_printer_driver_info_2
5054 * fill a printer_info_2 struct
5055 ********************************************************************/
5057 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5059 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5060 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5062 ZERO_STRUCT(printer
);
5063 ZERO_STRUCT(driver
);
5065 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5066 return WERR_INVALID_PRINTER_NAME
;
5068 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5069 free_a_printer(&printer
, 2);
5070 return WERR_UNKNOWN_PRINTER_DRIVER
;
5073 fill_printer_driver_info_2(info
, driver
, servername
);
5075 free_a_printer(&printer
,2);
5080 /********************************************************************
5081 * copy a strings array and convert to UNICODE
5083 * convert an array of ascii string to a UNICODE string
5084 ********************************************************************/
5086 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
5093 DEBUG(6,("init_unistr_array\n"));
5104 v
= ""; /* hack to handle null lists */
5107 /* hack to allow this to be used in places other than when generating
5108 the list of dependent files */
5111 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
5115 DEBUGADD(6,("%d:%s:%lu\n", i
, line
, (unsigned long)strlen(line
)));
5117 /* add one extra unit16 for the second terminating NULL */
5119 if ( (*uni_array
=SMB_REALLOC_ARRAY(*uni_array
, uint16
, j
+1+strlen(line
)+2)) == NULL
) {
5120 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5127 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
5132 /* special case for ""; we need to add both NULL's here */
5134 (*uni_array
)[j
++]=0x0000;
5135 (*uni_array
)[j
]=0x0000;
5138 DEBUGADD(6,("last one:done\n"));
5140 /* return size of array in uint16's */
5145 /********************************************************************
5146 * construct_printer_info_3
5147 * fill a printer_info_3 struct
5148 ********************************************************************/
5150 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5156 info
->version
=driver
.info_3
->cversion
;
5158 init_unistr( &info
->name
, driver
.info_3
->name
);
5159 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5161 if (strlen(driver
.info_3
->driverpath
)) {
5162 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5163 init_unistr( &info
->driverpath
, temp
);
5165 init_unistr( &info
->driverpath
, "" );
5167 if (strlen(driver
.info_3
->datafile
)) {
5168 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5169 init_unistr( &info
->datafile
, temp
);
5171 init_unistr( &info
->datafile
, "" );
5173 if (strlen(driver
.info_3
->configfile
)) {
5174 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5175 init_unistr( &info
->configfile
, temp
);
5177 init_unistr( &info
->configfile
, "" );
5179 if (strlen(driver
.info_3
->helpfile
)) {
5180 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5181 init_unistr( &info
->helpfile
, temp
);
5183 init_unistr( &info
->helpfile
, "" );
5185 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5186 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5188 info
->dependentfiles
=NULL
;
5189 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5192 /********************************************************************
5193 * construct_printer_info_3
5194 * fill a printer_info_3 struct
5195 ********************************************************************/
5197 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5199 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5200 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5202 ZERO_STRUCT(driver
);
5204 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5205 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5206 if (!W_ERROR_IS_OK(status
))
5207 return WERR_INVALID_PRINTER_NAME
;
5209 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5210 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5215 * I put this code in during testing. Helpful when commenting out the
5216 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5217 * as win2k always queries the driver using an infor level of 6.
5218 * I've left it in (but ifdef'd out) because I'll probably
5219 * use it in experimentation again in the future. --jerry 22/01/2002
5222 if (!W_ERROR_IS_OK(status
)) {
5224 * Is this a W2k client ?
5227 /* Yes - try again with a WinNT driver. */
5229 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5230 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5234 if (!W_ERROR_IS_OK(status
)) {
5235 free_a_printer(&printer
,2);
5236 return WERR_UNKNOWN_PRINTER_DRIVER
;
5244 fill_printer_driver_info_3(info
, driver
, servername
);
5246 free_a_printer(&printer
,2);
5251 /********************************************************************
5252 * construct_printer_info_6
5253 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5254 ********************************************************************/
5256 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5262 memset(&nullstr
, '\0', sizeof(fstring
));
5264 info
->version
=driver
.info_3
->cversion
;
5266 init_unistr( &info
->name
, driver
.info_3
->name
);
5267 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5269 if (strlen(driver
.info_3
->driverpath
)) {
5270 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5271 init_unistr( &info
->driverpath
, temp
);
5273 init_unistr( &info
->driverpath
, "" );
5275 if (strlen(driver
.info_3
->datafile
)) {
5276 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5277 init_unistr( &info
->datafile
, temp
);
5279 init_unistr( &info
->datafile
, "" );
5281 if (strlen(driver
.info_3
->configfile
)) {
5282 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5283 init_unistr( &info
->configfile
, temp
);
5285 init_unistr( &info
->configfile
, "" );
5287 if (strlen(driver
.info_3
->helpfile
)) {
5288 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5289 init_unistr( &info
->helpfile
, temp
);
5291 init_unistr( &info
->helpfile
, "" );
5293 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5294 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5296 info
->dependentfiles
= NULL
;
5297 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5299 info
->previousdrivernames
=NULL
;
5300 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5302 info
->driver_date
=0;
5305 info
->driver_version_low
=0;
5306 info
->driver_version_high
=0;
5308 init_unistr( &info
->mfgname
, "");
5309 init_unistr( &info
->oem_url
, "");
5310 init_unistr( &info
->hardware_id
, "");
5311 init_unistr( &info
->provider
, "");
5314 /********************************************************************
5315 * construct_printer_info_6
5316 * fill a printer_info_6 struct
5317 ********************************************************************/
5319 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5320 fstring servername
, fstring architecture
, uint32 version
)
5322 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5323 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5326 ZERO_STRUCT(driver
);
5328 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5330 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5332 if (!W_ERROR_IS_OK(status
))
5333 return WERR_INVALID_PRINTER_NAME
;
5335 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5337 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5339 if (!W_ERROR_IS_OK(status
))
5342 * Is this a W2k client ?
5346 free_a_printer(&printer
,2);
5347 return WERR_UNKNOWN_PRINTER_DRIVER
;
5350 /* Yes - try again with a WinNT driver. */
5352 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5353 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5354 if (!W_ERROR_IS_OK(status
)) {
5355 free_a_printer(&printer
,2);
5356 return WERR_UNKNOWN_PRINTER_DRIVER
;
5360 fill_printer_driver_info_6(info
, driver
, servername
);
5362 free_a_printer(&printer
,2);
5363 free_a_printer_driver(driver
, 3);
5368 /****************************************************************************
5369 ****************************************************************************/
5371 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5373 SAFE_FREE(info
->dependentfiles
);
5376 /****************************************************************************
5377 ****************************************************************************/
5379 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5381 SAFE_FREE(info
->dependentfiles
);
5384 /****************************************************************************
5385 ****************************************************************************/
5387 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5389 DRIVER_INFO_1
*info
=NULL
;
5392 if((info
=SMB_MALLOC_P(DRIVER_INFO_1
)) == NULL
)
5395 result
= construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5396 if (!W_ERROR_IS_OK(result
))
5399 /* check the required size. */
5400 *needed
+= spoolss_size_printer_driver_info_1(info
);
5402 if (*needed
> offered
) {
5403 result
= WERR_INSUFFICIENT_BUFFER
;
5407 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5408 result
= WERR_NOMEM
;
5412 /* fill the buffer with the structures */
5413 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5422 /****************************************************************************
5423 ****************************************************************************/
5425 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5427 DRIVER_INFO_2
*info
=NULL
;
5430 if((info
=SMB_MALLOC_P(DRIVER_INFO_2
)) == NULL
)
5433 result
= construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5434 if (!W_ERROR_IS_OK(result
))
5437 /* check the required size. */
5438 *needed
+= spoolss_size_printer_driver_info_2(info
);
5440 if (*needed
> offered
) {
5441 result
= WERR_INSUFFICIENT_BUFFER
;
5445 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5446 result
= WERR_NOMEM
;
5450 /* fill the buffer with the structures */
5451 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5460 /****************************************************************************
5461 ****************************************************************************/
5463 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5470 result
= construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5471 if (!W_ERROR_IS_OK(result
))
5474 /* check the required size. */
5475 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5477 if (*needed
> offered
) {
5478 result
= WERR_INSUFFICIENT_BUFFER
;
5482 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5483 result
= WERR_NOMEM
;
5487 /* fill the buffer with the structures */
5488 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5491 free_printer_driver_info_3(&info
);
5496 /****************************************************************************
5497 ****************************************************************************/
5499 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5506 result
= construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5507 if (!W_ERROR_IS_OK(result
))
5510 /* check the required size. */
5511 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5513 if (*needed
> offered
) {
5514 result
= WERR_INSUFFICIENT_BUFFER
;
5518 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5519 result
= WERR_NOMEM
;
5523 /* fill the buffer with the structures */
5524 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5527 free_printer_driver_info_6(&info
);
5532 /****************************************************************************
5533 ****************************************************************************/
5535 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5537 POLICY_HND
*handle
= &q_u
->handle
;
5538 UNISTR2
*uni_arch
= &q_u
->architecture
;
5539 uint32 level
= q_u
->level
;
5540 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5541 RPC_BUFFER
*buffer
= NULL
;
5542 uint32 offered
= q_u
->offered
;
5543 uint32
*needed
= &r_u
->needed
;
5544 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5545 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5546 Printer_entry
*printer
;
5549 fstring architecture
;
5552 /* that's an [in out] buffer */
5554 if (!q_u
->buffer
&& (offered
!=0)) {
5555 return WERR_INVALID_PARAM
;
5558 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5559 buffer
= r_u
->buffer
;
5561 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5563 if ( !(printer
= find_printer_index_by_hnd( p
, handle
)) ) {
5564 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5565 return WERR_INVALID_PRINTER_NAME
;
5569 *servermajorversion
= 0;
5570 *serverminorversion
= 0;
5572 fstrcpy(servername
, get_server_name( printer
));
5573 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5575 if (!get_printer_snum(p
, handle
, &snum
))
5580 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5582 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5584 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5586 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5589 /* apparently this call is the equivalent of
5590 EnumPrinterDataEx() for the DsDriver key */
5595 return WERR_UNKNOWN_LEVEL
;
5598 /****************************************************************************
5599 ****************************************************************************/
5601 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5603 POLICY_HND
*handle
= &q_u
->handle
;
5605 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5608 DEBUG(3,("Error in startpageprinter printer handle\n"));
5612 Printer
->page_started
=True
;
5616 /****************************************************************************
5617 ****************************************************************************/
5619 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5621 POLICY_HND
*handle
= &q_u
->handle
;
5624 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5627 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5631 if (!get_printer_snum(p
, handle
, &snum
))
5634 Printer
->page_started
=False
;
5635 print_job_endpage(snum
, Printer
->jobid
);
5640 /********************************************************************
5641 * api_spoolss_getprinter
5642 * called from the spoolss dispatcher
5644 ********************************************************************/
5646 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5648 POLICY_HND
*handle
= &q_u
->handle
;
5649 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5650 uint32
*jobid
= &r_u
->jobid
;
5652 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5656 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5657 struct current_user user
;
5660 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5664 get_current_user(&user
, p
);
5667 * a nice thing with NT is it doesn't listen to what you tell it.
5668 * when asked to send _only_ RAW datas, it tries to send datas
5671 * So I add checks like in NT Server ...
5674 if (info_1
->p_datatype
!= 0) {
5675 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5676 if (strcmp(datatype
, "RAW") != 0) {
5678 return WERR_INVALID_DATATYPE
;
5682 /* get the share number of the printer */
5683 if (!get_printer_snum(p
, handle
, &snum
)) {
5687 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5689 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5691 /* An error occured in print_job_start() so return an appropriate
5694 if (Printer
->jobid
== -1) {
5695 return map_werror_from_unix(errno
);
5698 Printer
->document_started
=True
;
5699 (*jobid
) = Printer
->jobid
;
5704 /********************************************************************
5705 * api_spoolss_getprinter
5706 * called from the spoolss dispatcher
5708 ********************************************************************/
5710 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5712 POLICY_HND
*handle
= &q_u
->handle
;
5714 return _spoolss_enddocprinter_internal(p
, handle
);
5717 /****************************************************************************
5718 ****************************************************************************/
5720 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5722 POLICY_HND
*handle
= &q_u
->handle
;
5723 uint32 buffer_size
= q_u
->buffer_size
;
5724 uint8
*buffer
= q_u
->buffer
;
5725 uint32
*buffer_written
= &q_u
->buffer_size2
;
5727 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5730 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5731 r_u
->buffer_written
= q_u
->buffer_size2
;
5735 if (!get_printer_snum(p
, handle
, &snum
))
5738 (*buffer_written
) = (uint32
)print_job_write(snum
, Printer
->jobid
, (const char *)buffer
,
5739 (SMB_OFF_T
)-1, (size_t)buffer_size
);
5740 if (*buffer_written
== (uint32
)-1) {
5741 r_u
->buffer_written
= 0;
5742 if (errno
== ENOSPC
)
5743 return WERR_NO_SPOOL_SPACE
;
5745 return WERR_ACCESS_DENIED
;
5748 r_u
->buffer_written
= q_u
->buffer_size2
;
5753 /********************************************************************
5754 * api_spoolss_getprinter
5755 * called from the spoolss dispatcher
5757 ********************************************************************/
5759 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5762 struct current_user user
;
5764 WERROR errcode
= WERR_BADFUNC
;
5765 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5767 get_current_user(&user
, p
);
5770 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5774 if (!get_printer_snum(p
, handle
, &snum
))
5778 case PRINTER_CONTROL_PAUSE
:
5779 if (print_queue_pause(&user
, snum
, &errcode
)) {
5783 case PRINTER_CONTROL_RESUME
:
5784 case PRINTER_CONTROL_UNPAUSE
:
5785 if (print_queue_resume(&user
, snum
, &errcode
)) {
5789 case PRINTER_CONTROL_PURGE
:
5790 if (print_queue_purge(&user
, snum
, &errcode
)) {
5795 return WERR_UNKNOWN_LEVEL
;
5801 /********************************************************************
5802 * api_spoolss_abortprinter
5803 * From MSDN: "Deletes printer's spool file if printer is configured
5805 ********************************************************************/
5807 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5809 POLICY_HND
*handle
= &q_u
->handle
;
5810 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5812 struct current_user user
;
5813 WERROR errcode
= WERR_OK
;
5816 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5820 if (!get_printer_snum(p
, handle
, &snum
))
5823 get_current_user( &user
, p
);
5825 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5830 /********************************************************************
5831 * called by spoolss_api_setprinter
5832 * when updating a printer description
5833 ********************************************************************/
5835 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5836 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5837 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5839 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5843 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5845 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5846 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5847 OUR_HANDLE(handle
)));
5849 result
= WERR_BADFID
;
5854 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5855 result
= WERR_INVALID_PARAM
;
5859 /* Check the user has permissions to change the security
5860 descriptor. By experimentation with two NT machines, the user
5861 requires Full Access to the printer to change security
5864 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5865 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5866 result
= WERR_ACCESS_DENIED
;
5870 /* NT seems to like setting the security descriptor even though
5871 nothing may have actually changed. */
5873 nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
);
5875 if (DEBUGLEVEL
>= 10) {
5879 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5880 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5881 PRINTERNAME(snum
), the_acl
->num_aces
));
5883 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5886 sid_to_string(sid_str
, &the_acl
->aces
[i
].trustee
);
5888 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5889 the_acl
->aces
[i
].access_mask
));
5892 the_acl
= secdesc_ctr
->sec
->dacl
;
5895 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5896 PRINTERNAME(snum
), the_acl
->num_aces
));
5898 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5901 sid_to_string(sid_str
, &the_acl
->aces
[i
].trustee
);
5903 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5904 the_acl
->aces
[i
].access_mask
));
5907 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5911 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5912 if (!new_secdesc_ctr
) {
5913 result
= WERR_NOMEM
;
5917 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5922 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5929 /********************************************************************
5930 Canonicalize printer info from a client
5932 ATTN: It does not matter what we set the servername to hear
5933 since we do the necessary work in get_a_printer() to set it to
5934 the correct value based on what the client sent in the
5935 _spoolss_open_printer_ex().
5936 ********************************************************************/
5938 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5940 fstring printername
;
5943 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5944 "portname=%s drivername=%s comment=%s location=%s\n",
5945 info
->servername
, info
->printername
, info
->sharename
,
5946 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5948 /* we force some elements to "correct" values */
5949 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5950 fstrcpy(info
->sharename
, lp_servicename(snum
));
5952 /* check to see if we allow printername != sharename */
5954 if ( lp_force_printername(snum
) ) {
5955 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5956 global_myname(), info
->sharename
);
5959 /* make sure printername is in \\server\printername format */
5961 fstrcpy( printername
, info
->printername
);
5963 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5964 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5968 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5969 global_myname(), p
);
5972 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5973 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5980 /****************************************************************************
5981 ****************************************************************************/
5983 WERROR
add_port_hook(NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
5985 char *cmd
= lp_addport_cmd();
5989 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5990 BOOL is_print_op
= False
;
5993 return WERR_ACCESS_DENIED
;
5996 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
5999 is_print_op
= user_has_privileges( token
, &se_printop
);
6001 DEBUG(10,("Running [%s]\n", command
));
6003 /********* BEGIN SePrintOperatorPrivilege **********/
6008 ret
= smbrun(command
, &fd
);
6013 /********* END SePrintOperatorPrivilege **********/
6015 DEBUGADD(10,("returned [%d]\n", ret
));
6020 return WERR_ACCESS_DENIED
;
6026 /****************************************************************************
6027 ****************************************************************************/
6029 BOOL
add_printer_hook(NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
6031 char *cmd
= lp_addprinter_cmd();
6037 fstring remote_machine
= "%m";
6038 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
6039 BOOL is_print_op
= False
;
6041 standard_sub_basic(current_user_info
.smb_name
,
6042 current_user_info
.domain
,
6043 remote_machine
,sizeof(remote_machine
));
6045 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6046 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
6047 printer
->info_2
->portname
, printer
->info_2
->drivername
,
6048 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
6051 is_print_op
= user_has_privileges( token
, &se_printop
);
6053 DEBUG(10,("Running [%s]\n", command
));
6055 /********* BEGIN SePrintOperatorPrivilege **********/
6060 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6061 /* Tell everyone we updated smb.conf. */
6062 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
6068 /********* END SePrintOperatorPrivilege **********/
6070 DEBUGADD(10,("returned [%d]\n", ret
));
6078 /* reload our services immediately */
6079 reload_services( False
);
6082 /* Get lines and convert them back to dos-codepage */
6083 qlines
= fd_lines_load(fd
, &numlines
, 0);
6084 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6087 /* Set the portname to what the script says the portname should be. */
6088 /* but don't require anything to be return from the script exit a good error code */
6091 /* Set the portname to what the script says the portname should be. */
6092 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
6093 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6096 file_lines_free(qlines
);
6101 /********************************************************************
6102 * Called by spoolss_api_setprinter
6103 * when updating a printer description.
6104 ********************************************************************/
6106 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
6107 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6108 DEVICEMODE
*devmode
)
6111 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6112 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6117 DEBUG(8,("update_printer\n"));
6122 result
= WERR_BADFID
;
6126 if (!get_printer_snum(p
, handle
, &snum
)) {
6127 result
= WERR_BADFID
;
6131 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6132 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6133 result
= WERR_BADFID
;
6137 DEBUGADD(8,("Converting info_2 struct\n"));
6140 * convert_printer_info converts the incoming
6141 * info from the client and overwrites the info
6142 * just read from the tdb in the pointer 'printer'.
6145 if (!convert_printer_info(info
, printer
, level
)) {
6146 result
= WERR_NOMEM
;
6151 /* we have a valid devmode
6152 convert it and link it*/
6154 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6155 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6156 &printer
->info_2
->devmode
)) {
6157 result
= WERR_NOMEM
;
6162 /* Do sanity check on the requested changes for Samba */
6164 if (!check_printer_ok(printer
->info_2
, snum
)) {
6165 result
= WERR_INVALID_PARAM
;
6169 /* FIXME!!! If the driver has changed we really should verify that
6170 it is installed before doing much else --jerry */
6172 /* Check calling user has permission to update printer description */
6174 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6175 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6176 result
= WERR_ACCESS_DENIED
;
6180 /* Call addprinter hook */
6181 /* Check changes to see if this is really needed */
6183 if ( *lp_addprinter_cmd()
6184 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6185 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6186 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6187 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6189 /* add_printer_hook() will call reload_services() */
6191 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
6192 result
= WERR_ACCESS_DENIED
;
6198 * When a *new* driver is bound to a printer, the drivername is used to
6199 * lookup previously saved driver initialization info, which is then
6200 * bound to the printer, simulating what happens in the Windows arch.
6202 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6204 if (!set_driver_init(printer
, 2))
6206 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6207 printer
->info_2
->drivername
));
6210 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6211 printer
->info_2
->drivername
));
6213 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6217 * flag which changes actually occured. This is a small subset of
6218 * all the possible changes. We also have to update things in the
6222 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6223 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6224 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6225 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6227 notify_printer_comment(snum
, printer
->info_2
->comment
);
6230 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6231 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6232 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6233 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6235 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6238 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6241 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6244 pname
= printer
->info_2
->printername
;
6247 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6248 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6249 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6251 notify_printer_printername( snum
, pname
);
6254 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6255 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6256 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6257 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6259 notify_printer_port(snum
, printer
->info_2
->portname
);
6262 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6263 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6264 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6265 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6267 notify_printer_location(snum
, printer
->info_2
->location
);
6270 /* here we need to update some more DsSpooler keys */
6271 /* uNCName, serverName, shortServerName */
6273 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6274 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6275 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6276 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6277 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6279 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6280 global_myname(), printer
->info_2
->sharename
);
6281 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6282 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6283 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6285 /* Update printer info */
6286 result
= mod_a_printer(printer
, 2);
6289 free_a_printer(&printer
, 2);
6290 free_a_printer(&old_printer
, 2);
6296 /****************************************************************************
6297 ****************************************************************************/
6298 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6299 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6302 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6304 Printer_entry
*Printer
;
6306 if ( lp_security() != SEC_ADS
) {
6307 return WERR_UNKNOWN_LEVEL
;
6310 Printer
= find_printer_index_by_hnd(p
, handle
);
6312 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6317 if (!get_printer_snum(p
, handle
, &snum
))
6320 nt_printer_publish(Printer
, snum
, info7
->action
);
6324 return WERR_UNKNOWN_LEVEL
;
6327 /****************************************************************************
6328 ****************************************************************************/
6330 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6332 POLICY_HND
*handle
= &q_u
->handle
;
6333 uint32 level
= q_u
->level
;
6334 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6335 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6336 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6337 uint32 command
= q_u
->command
;
6340 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6343 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6347 /* check the level */
6350 return control_printer(handle
, command
, p
);
6352 result
= update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6353 if (!W_ERROR_IS_OK(result
))
6356 result
= update_printer_sec(handle
, level
, info
, p
, secdesc_ctr
);
6359 return update_printer_sec(handle
, level
, info
, p
,
6362 return publish_or_unpublish_printer(p
, handle
, info
);
6364 return WERR_UNKNOWN_LEVEL
;
6368 /****************************************************************************
6369 ****************************************************************************/
6371 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6373 POLICY_HND
*handle
= &q_u
->handle
;
6374 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6377 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6381 if (Printer
->notify
.client_connected
==True
) {
6384 if ( Printer
->printer_type
== SPLHND_SERVER
)
6386 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
6387 !get_printer_snum(p
, handle
, &snum
) )
6390 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6393 Printer
->notify
.flags
=0;
6394 Printer
->notify
.options
=0;
6395 Printer
->notify
.localmachine
[0]='\0';
6396 Printer
->notify
.printerlocal
=0;
6397 if (Printer
->notify
.option
)
6398 free_spool_notify_option(&Printer
->notify
.option
);
6399 Printer
->notify
.client_connected
=False
;
6404 /****************************************************************************
6405 ****************************************************************************/
6407 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6409 /* that's an [in out] buffer */
6411 if (!q_u
->buffer
&& (q_u
->offered
!=0)) {
6412 return WERR_INVALID_PARAM
;
6415 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6418 return WERR_INVALID_PARAM
; /* this is what a NT server
6419 returns for AddJob. AddJob
6420 must fail on non-local
6424 /****************************************************************************
6425 ****************************************************************************/
6427 static void fill_job_info_1(JOB_INFO_1
*job_info
, const print_queue_struct
*queue
,
6428 int position
, int snum
,
6429 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
6433 t
=gmtime(&queue
->time
);
6435 job_info
->jobid
=queue
->job
;
6436 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6437 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6438 init_unistr(&job_info
->username
, queue
->fs_user
);
6439 init_unistr(&job_info
->document
, queue
->fs_file
);
6440 init_unistr(&job_info
->datatype
, "RAW");
6441 init_unistr(&job_info
->text_status
, "");
6442 job_info
->status
=nt_printj_status(queue
->status
);
6443 job_info
->priority
=queue
->priority
;
6444 job_info
->position
=position
;
6445 job_info
->totalpages
=queue
->page_count
;
6446 job_info
->pagesprinted
=0;
6448 make_systemtime(&job_info
->submitted
, t
);
6451 /****************************************************************************
6452 ****************************************************************************/
6454 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, const print_queue_struct
*queue
,
6455 int position
, int snum
,
6456 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6457 DEVICEMODE
*devmode
)
6461 t
=gmtime(&queue
->time
);
6463 job_info
->jobid
=queue
->job
;
6465 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6467 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6468 init_unistr(&job_info
->username
, queue
->fs_user
);
6469 init_unistr(&job_info
->document
, queue
->fs_file
);
6470 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6471 init_unistr(&job_info
->datatype
, "RAW");
6472 init_unistr(&job_info
->printprocessor
, "winprint");
6473 init_unistr(&job_info
->parameters
, "");
6474 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6475 init_unistr(&job_info
->text_status
, "");
6477 /* and here the security descriptor */
6479 job_info
->status
=nt_printj_status(queue
->status
);
6480 job_info
->priority
=queue
->priority
;
6481 job_info
->position
=position
;
6482 job_info
->starttime
=0;
6483 job_info
->untiltime
=0;
6484 job_info
->totalpages
=queue
->page_count
;
6485 job_info
->size
=queue
->size
;
6486 make_systemtime(&(job_info
->submitted
), t
);
6487 job_info
->timeelapsed
=0;
6488 job_info
->pagesprinted
=0;
6490 job_info
->devmode
= devmode
;
6495 /****************************************************************************
6496 Enumjobs at level 1.
6497 ****************************************************************************/
6499 static WERROR
enumjobs_level1(const print_queue_struct
*queue
, int snum
,
6500 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6501 RPC_BUFFER
*buffer
, uint32 offered
,
6502 uint32
*needed
, uint32
*returned
)
6506 WERROR result
= WERR_OK
;
6508 info
=SMB_MALLOC_ARRAY(JOB_INFO_1
,*returned
);
6514 for (i
=0; i
<*returned
; i
++)
6515 fill_job_info_1( &info
[i
], &queue
[i
], i
, snum
, ntprinter
);
6517 /* check the required size. */
6518 for (i
=0; i
<*returned
; i
++)
6519 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6521 if (*needed
> offered
) {
6522 result
= WERR_INSUFFICIENT_BUFFER
;
6526 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6527 result
= WERR_NOMEM
;
6531 /* fill the buffer with the structures */
6532 for (i
=0; i
<*returned
; i
++)
6533 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6539 if ( !W_ERROR_IS_OK(result
) )
6545 /****************************************************************************
6546 Enumjobs at level 2.
6547 ****************************************************************************/
6549 static WERROR
enumjobs_level2(const print_queue_struct
*queue
, int snum
,
6550 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6551 RPC_BUFFER
*buffer
, uint32 offered
,
6552 uint32
*needed
, uint32
*returned
)
6554 JOB_INFO_2
*info
= NULL
;
6556 WERROR result
= WERR_OK
;
6557 DEVICEMODE
*devmode
= NULL
;
6559 if ( !(info
= SMB_MALLOC_ARRAY(JOB_INFO_2
,*returned
)) ) {
6564 /* this should not be a failure condition if the devmode is NULL */
6566 devmode
= construct_dev_mode(lp_const_servicename(snum
));
6568 for (i
=0; i
<*returned
; i
++)
6569 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
, devmode
);
6571 /* check the required size. */
6572 for (i
=0; i
<*returned
; i
++)
6573 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6575 if (*needed
> offered
) {
6576 result
= WERR_INSUFFICIENT_BUFFER
;
6580 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6581 result
= WERR_NOMEM
;
6585 /* fill the buffer with the structures */
6586 for (i
=0; i
<*returned
; i
++)
6587 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6590 free_devmode(devmode
);
6593 if ( !W_ERROR_IS_OK(result
) )
6600 /****************************************************************************
6602 ****************************************************************************/
6604 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6606 POLICY_HND
*handle
= &q_u
->handle
;
6607 uint32 level
= q_u
->level
;
6608 RPC_BUFFER
*buffer
= NULL
;
6609 uint32 offered
= q_u
->offered
;
6610 uint32
*needed
= &r_u
->needed
;
6611 uint32
*returned
= &r_u
->returned
;
6613 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6615 print_status_struct prt_status
;
6616 print_queue_struct
*queue
=NULL
;
6618 /* that's an [in out] buffer */
6620 if (!q_u
->buffer
&& (offered
!=0)) {
6621 return WERR_INVALID_PARAM
;
6624 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6625 buffer
= r_u
->buffer
;
6627 DEBUG(4,("_spoolss_enumjobs\n"));
6632 /* lookup the printer snum and tdb entry */
6634 if (!get_printer_snum(p
, handle
, &snum
))
6637 wret
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6638 if ( !W_ERROR_IS_OK(wret
) )
6641 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6642 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6644 if (*returned
== 0) {
6646 free_a_printer(&ntprinter
, 2);
6652 wret
= enumjobs_level1(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6655 wret
= enumjobs_level2(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6659 wret
= WERR_UNKNOWN_LEVEL
;
6664 free_a_printer( &ntprinter
, 2 );
6668 /****************************************************************************
6669 ****************************************************************************/
6671 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6676 /****************************************************************************
6677 ****************************************************************************/
6679 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6681 POLICY_HND
*handle
= &q_u
->handle
;
6682 uint32 jobid
= q_u
->jobid
;
6683 uint32 command
= q_u
->command
;
6685 struct current_user user
;
6687 WERROR errcode
= WERR_BADFUNC
;
6689 if (!get_printer_snum(p
, handle
, &snum
)) {
6693 if (!print_job_exists(lp_const_servicename(snum
), jobid
)) {
6694 return WERR_INVALID_PRINTER_NAME
;
6697 get_current_user(&user
, p
);
6700 case JOB_CONTROL_CANCEL
:
6701 case JOB_CONTROL_DELETE
:
6702 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6706 case JOB_CONTROL_PAUSE
:
6707 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6711 case JOB_CONTROL_RESTART
:
6712 case JOB_CONTROL_RESUME
:
6713 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6718 return WERR_UNKNOWN_LEVEL
;
6724 /****************************************************************************
6725 Enumerates all printer drivers at level 1.
6726 ****************************************************************************/
6728 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6733 fstring
*list
= NULL
;
6734 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6735 DRIVER_INFO_1
*driver_info_1
=NULL
;
6736 WERROR result
= WERR_OK
;
6740 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6742 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6743 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6745 if(ndrivers
== -1) {
6746 SAFE_FREE(driver_info_1
);
6751 if((driver_info_1
=SMB_REALLOC_ARRAY(driver_info_1
, DRIVER_INFO_1
, *returned
+ndrivers
)) == NULL
) {
6752 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6758 for (i
=0; i
<ndrivers
; i
++) {
6760 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6761 ZERO_STRUCT(driver
);
6762 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6763 architecture
, version
);
6764 if (!W_ERROR_IS_OK(status
)) {
6766 SAFE_FREE(driver_info_1
);
6769 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6770 free_a_printer_driver(driver
, 3);
6773 *returned
+=ndrivers
;
6777 /* check the required size. */
6778 for (i
=0; i
<*returned
; i
++) {
6779 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6780 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6783 if (*needed
> offered
) {
6784 result
= WERR_INSUFFICIENT_BUFFER
;
6788 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6789 result
= WERR_NOMEM
;
6793 /* fill the buffer with the driver structures */
6794 for (i
=0; i
<*returned
; i
++) {
6795 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6796 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6800 SAFE_FREE(driver_info_1
);
6802 if ( !W_ERROR_IS_OK(result
) )
6808 /****************************************************************************
6809 Enumerates all printer drivers at level 2.
6810 ****************************************************************************/
6812 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6817 fstring
*list
= NULL
;
6818 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6819 DRIVER_INFO_2
*driver_info_2
=NULL
;
6820 WERROR result
= WERR_OK
;
6824 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6826 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6827 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6829 if(ndrivers
== -1) {
6830 SAFE_FREE(driver_info_2
);
6835 if((driver_info_2
=SMB_REALLOC_ARRAY(driver_info_2
, DRIVER_INFO_2
, *returned
+ndrivers
)) == NULL
) {
6836 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6842 for (i
=0; i
<ndrivers
; i
++) {
6845 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6846 ZERO_STRUCT(driver
);
6847 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6848 architecture
, version
);
6849 if (!W_ERROR_IS_OK(status
)) {
6851 SAFE_FREE(driver_info_2
);
6854 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6855 free_a_printer_driver(driver
, 3);
6858 *returned
+=ndrivers
;
6862 /* check the required size. */
6863 for (i
=0; i
<*returned
; i
++) {
6864 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6865 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6868 if (*needed
> offered
) {
6869 result
= WERR_INSUFFICIENT_BUFFER
;
6873 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6874 result
= WERR_NOMEM
;
6878 /* fill the buffer with the form structures */
6879 for (i
=0; i
<*returned
; i
++) {
6880 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6881 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6885 SAFE_FREE(driver_info_2
);
6887 if ( !W_ERROR_IS_OK(result
) )
6893 /****************************************************************************
6894 Enumerates all printer drivers at level 3.
6895 ****************************************************************************/
6897 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6902 fstring
*list
= NULL
;
6903 DRIVER_INFO_3
*driver_info_3
=NULL
;
6904 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6905 WERROR result
= WERR_OK
;
6909 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6911 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6912 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6914 if(ndrivers
== -1) {
6915 SAFE_FREE(driver_info_3
);
6920 if((driver_info_3
=SMB_REALLOC_ARRAY(driver_info_3
, DRIVER_INFO_3
, *returned
+ndrivers
)) == NULL
) {
6921 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6927 for (i
=0; i
<ndrivers
; i
++) {
6930 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6931 ZERO_STRUCT(driver
);
6932 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6933 architecture
, version
);
6934 if (!W_ERROR_IS_OK(status
)) {
6936 SAFE_FREE(driver_info_3
);
6939 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6940 free_a_printer_driver(driver
, 3);
6943 *returned
+=ndrivers
;
6947 /* check the required size. */
6948 for (i
=0; i
<*returned
; i
++) {
6949 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6950 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6953 if (*needed
> offered
) {
6954 result
= WERR_INSUFFICIENT_BUFFER
;
6958 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6959 result
= WERR_NOMEM
;
6963 /* fill the buffer with the driver structures */
6964 for (i
=0; i
<*returned
; i
++) {
6965 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6966 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6970 for (i
=0; i
<*returned
; i
++) {
6971 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6974 SAFE_FREE(driver_info_3
);
6976 if ( !W_ERROR_IS_OK(result
) )
6982 /****************************************************************************
6983 Enumerates all printer drivers.
6984 ****************************************************************************/
6986 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6988 uint32 level
= q_u
->level
;
6989 RPC_BUFFER
*buffer
= NULL
;
6990 uint32 offered
= q_u
->offered
;
6991 uint32
*needed
= &r_u
->needed
;
6992 uint32
*returned
= &r_u
->returned
;
6995 fstring architecture
;
6997 /* that's an [in out] buffer */
6999 if (!q_u
->buffer
&& (offered
!=0)) {
7000 return WERR_INVALID_PARAM
;
7003 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7004 buffer
= r_u
->buffer
;
7006 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7011 unistr2_to_ascii(architecture
, &q_u
->environment
, sizeof(architecture
)-1);
7012 unistr2_to_ascii(servername
, &q_u
->name
, sizeof(servername
)-1);
7014 if ( !is_myname_or_ipaddr( servername
) )
7015 return WERR_UNKNOWN_PRINTER_DRIVER
;
7019 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
7021 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
7023 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
7025 return WERR_UNKNOWN_LEVEL
;
7029 /****************************************************************************
7030 ****************************************************************************/
7032 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
7034 form
->flag
=list
->flag
;
7035 init_unistr(&form
->name
, list
->name
);
7036 form
->width
=list
->width
;
7037 form
->length
=list
->length
;
7038 form
->left
=list
->left
;
7039 form
->top
=list
->top
;
7040 form
->right
=list
->right
;
7041 form
->bottom
=list
->bottom
;
7044 /****************************************************************************
7045 ****************************************************************************/
7047 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
7049 uint32 level
= q_u
->level
;
7050 RPC_BUFFER
*buffer
= NULL
;
7051 uint32 offered
= q_u
->offered
;
7052 uint32
*needed
= &r_u
->needed
;
7053 uint32
*numofforms
= &r_u
->numofforms
;
7054 uint32 numbuiltinforms
;
7056 nt_forms_struct
*list
=NULL
;
7057 nt_forms_struct
*builtinlist
=NULL
;
7062 /* that's an [in out] buffer */
7064 if (!q_u
->buffer
&& (offered
!=0) ) {
7065 return WERR_INVALID_PARAM
;
7068 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7069 buffer
= r_u
->buffer
;
7071 DEBUG(4,("_spoolss_enumforms\n"));
7072 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7073 DEBUGADD(5,("Info level [%d]\n", level
));
7075 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
7076 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
7077 *numofforms
= get_ntforms(&list
);
7078 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
7079 *numofforms
+= numbuiltinforms
;
7081 if (*numofforms
== 0) {
7082 SAFE_FREE(builtinlist
);
7084 return WERR_NO_MORE_ITEMS
;
7089 if ((forms_1
=SMB_MALLOC_ARRAY(FORM_1
, *numofforms
)) == NULL
) {
7090 SAFE_FREE(builtinlist
);
7096 /* construct the list of form structures */
7097 for (i
=0; i
<numbuiltinforms
; i
++) {
7098 DEBUGADD(6,("Filling form number [%d]\n",i
));
7099 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
7102 SAFE_FREE(builtinlist
);
7104 for (; i
<*numofforms
; i
++) {
7105 DEBUGADD(6,("Filling form number [%d]\n",i
));
7106 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
7111 /* check the required size. */
7112 for (i
=0; i
<numbuiltinforms
; i
++) {
7113 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7114 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7116 for (; i
<*numofforms
; i
++) {
7117 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7118 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7121 *needed
=buffer_size
;
7123 if (*needed
> offered
) {
7126 return WERR_INSUFFICIENT_BUFFER
;
7129 if (!rpcbuf_alloc_size(buffer
, buffer_size
)){
7135 /* fill the buffer with the form structures */
7136 for (i
=0; i
<numbuiltinforms
; i
++) {
7137 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7138 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7140 for (; i
<*numofforms
; i
++) {
7141 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7142 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7151 SAFE_FREE(builtinlist
);
7152 return WERR_UNKNOWN_LEVEL
;
7156 /****************************************************************************
7157 ****************************************************************************/
7159 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
7161 uint32 level
= q_u
->level
;
7162 UNISTR2
*uni_formname
= &q_u
->formname
;
7163 RPC_BUFFER
*buffer
= NULL
;
7164 uint32 offered
= q_u
->offered
;
7165 uint32
*needed
= &r_u
->needed
;
7167 nt_forms_struct
*list
=NULL
;
7168 nt_forms_struct builtin_form
;
7173 int numofforms
=0, i
=0;
7175 /* that's an [in out] buffer */
7177 if (!q_u
->buffer
&& (offered
!=0)) {
7178 return WERR_INVALID_PARAM
;
7181 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7182 buffer
= r_u
->buffer
;
7184 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
7186 DEBUG(4,("_spoolss_getform\n"));
7187 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7188 DEBUGADD(5,("Info level [%d]\n", level
));
7190 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
7191 if (!foundBuiltin
) {
7192 numofforms
= get_ntforms(&list
);
7193 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
7195 if (numofforms
== 0)
7202 fill_form_1(&form_1
, &builtin_form
);
7205 /* Check if the requested name is in the list of form structures */
7206 for (i
=0; i
<numofforms
; i
++) {
7208 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
7210 if (strequal(form_name
, list
[i
].name
)) {
7211 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
7212 fill_form_1(&form_1
, &list
[i
]);
7218 if (i
== numofforms
) {
7222 /* check the required size. */
7224 *needed
=spoolss_size_form_1(&form_1
);
7226 if (*needed
> offered
)
7227 return WERR_INSUFFICIENT_BUFFER
;
7229 if (!rpcbuf_alloc_size(buffer
, buffer_size
))
7232 /* fill the buffer with the form structures */
7233 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
7234 smb_io_form_1("", buffer
, &form_1
, 0);
7240 return WERR_UNKNOWN_LEVEL
;
7244 /****************************************************************************
7245 ****************************************************************************/
7247 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
7249 init_unistr(&port
->port_name
, name
);
7252 /****************************************************************************
7253 TODO: This probably needs distinguish between TCP/IP and Local ports
7255 ****************************************************************************/
7257 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
7259 init_unistr(&port
->port_name
, name
);
7260 init_unistr(&port
->monitor_name
, "Local Monitor");
7261 init_unistr(&port
->description
, SPL_LOCAL_PORT
);
7262 port
->port_type
=PORT_TYPE_WRITE
;
7267 /****************************************************************************
7268 wrapper around the enumer ports command
7269 ****************************************************************************/
7271 WERROR
enumports_hook( int *count
, char ***lines
)
7273 char *cmd
= lp_enumports_cmd();
7283 /* if no hook then just fill in the default port */
7286 qlines
= SMB_MALLOC_ARRAY( char*, 2 );
7287 qlines
[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME
);
7292 /* we have a valid enumport command */
7294 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
7296 DEBUG(10,("Running [%s]\n", command
));
7297 ret
= smbrun(command
, &fd
);
7298 DEBUG(10,("Returned [%d]\n", ret
));
7303 return WERR_ACCESS_DENIED
;
7307 qlines
= fd_lines_load(fd
, &numlines
, 0);
7308 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7318 /****************************************************************************
7320 ****************************************************************************/
7322 static WERROR
enumports_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7324 PORT_INFO_1
*ports
=NULL
;
7326 WERROR result
= WERR_OK
;
7327 char **qlines
= NULL
;
7330 result
= enumports_hook( &numlines
, &qlines
);
7331 if (!W_ERROR_IS_OK(result
)) {
7332 file_lines_free(qlines
);
7337 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_1
, numlines
)) == NULL
) {
7338 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7339 dos_errstr(WERR_NOMEM
)));
7340 file_lines_free(qlines
);
7344 for (i
=0; i
<numlines
; i
++) {
7345 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7346 fill_port_1(&ports
[i
], qlines
[i
]);
7349 file_lines_free(qlines
);
7351 *returned
= numlines
;
7353 /* check the required size. */
7354 for (i
=0; i
<*returned
; i
++) {
7355 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7356 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7359 if (*needed
> offered
) {
7360 result
= WERR_INSUFFICIENT_BUFFER
;
7364 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7365 result
= WERR_NOMEM
;
7369 /* fill the buffer with the ports structures */
7370 for (i
=0; i
<*returned
; i
++) {
7371 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7372 smb_io_port_1("", buffer
, &ports
[i
], 0);
7378 if ( !W_ERROR_IS_OK(result
) )
7384 /****************************************************************************
7386 ****************************************************************************/
7388 static WERROR
enumports_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7390 PORT_INFO_2
*ports
=NULL
;
7392 WERROR result
= WERR_OK
;
7393 char **qlines
= NULL
;
7396 result
= enumports_hook( &numlines
, &qlines
);
7397 if ( !W_ERROR_IS_OK(result
)) {
7398 file_lines_free(qlines
);
7403 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_2
, numlines
)) == NULL
) {
7404 file_lines_free(qlines
);
7408 for (i
=0; i
<numlines
; i
++) {
7409 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7410 fill_port_2(&(ports
[i
]), qlines
[i
]);
7414 file_lines_free(qlines
);
7416 *returned
= numlines
;
7418 /* check the required size. */
7419 for (i
=0; i
<*returned
; i
++) {
7420 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7421 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7424 if (*needed
> offered
) {
7425 result
= WERR_INSUFFICIENT_BUFFER
;
7429 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7430 result
= WERR_NOMEM
;
7434 /* fill the buffer with the ports structures */
7435 for (i
=0; i
<*returned
; i
++) {
7436 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7437 smb_io_port_2("", buffer
, &ports
[i
], 0);
7443 if ( !W_ERROR_IS_OK(result
) )
7449 /****************************************************************************
7451 ****************************************************************************/
7453 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7455 uint32 level
= q_u
->level
;
7456 RPC_BUFFER
*buffer
= NULL
;
7457 uint32 offered
= q_u
->offered
;
7458 uint32
*needed
= &r_u
->needed
;
7459 uint32
*returned
= &r_u
->returned
;
7461 /* that's an [in out] buffer */
7463 if (!q_u
->buffer
&& (offered
!=0)) {
7464 return WERR_INVALID_PARAM
;
7467 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7468 buffer
= r_u
->buffer
;
7470 DEBUG(4,("_spoolss_enumports\n"));
7477 return enumports_level_1(buffer
, offered
, needed
, returned
);
7479 return enumports_level_2(buffer
, offered
, needed
, returned
);
7481 return WERR_UNKNOWN_LEVEL
;
7485 /****************************************************************************
7486 ****************************************************************************/
7488 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7489 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7490 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7491 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7494 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7497 WERROR err
= WERR_OK
;
7499 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7500 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7504 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7505 if (!convert_printer_info(info
, printer
, 2)) {
7506 free_a_printer(&printer
, 2);
7510 /* check to see if the printer already exists */
7512 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7513 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7514 printer
->info_2
->sharename
));
7515 free_a_printer(&printer
, 2);
7516 return WERR_PRINTER_ALREADY_EXISTS
;
7519 /* FIXME!!! smbd should check to see if the driver is installed before
7520 trying to add a printer like this --jerry */
7522 if (*lp_addprinter_cmd() ) {
7523 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
7524 free_a_printer(&printer
,2);
7525 return WERR_ACCESS_DENIED
;
7528 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7529 "smb.conf parameter \"addprinter command\" is defined. This"
7530 "parameter must exist for this call to succeed\n",
7531 printer
->info_2
->sharename
));
7534 /* use our primary netbios name since get_a_printer() will convert
7535 it to what the client expects on a case by case basis */
7537 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7538 printer
->info_2
->sharename
);
7541 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7542 free_a_printer(&printer
,2);
7543 return WERR_ACCESS_DENIED
;
7546 /* you must be a printer admin to add a new printer */
7547 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7548 free_a_printer(&printer
,2);
7549 return WERR_ACCESS_DENIED
;
7553 * Do sanity check on the requested changes for Samba.
7556 if (!check_printer_ok(printer
->info_2
, snum
)) {
7557 free_a_printer(&printer
,2);
7558 return WERR_INVALID_PARAM
;
7562 * When a printer is created, the drivername bound to the printer is used
7563 * to lookup previously saved driver initialization info, which is then
7564 * bound to the new printer, simulating what happens in the Windows arch.
7569 set_driver_init(printer
, 2);
7573 /* A valid devmode was included, convert and link it
7575 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7577 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7578 &printer
->info_2
->devmode
))
7582 /* write the ASCII on disk */
7583 err
= mod_a_printer(printer
, 2);
7584 if (!W_ERROR_IS_OK(err
)) {
7585 free_a_printer(&printer
,2);
7589 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7590 /* Handle open failed - remove addition. */
7591 del_a_printer(printer
->info_2
->sharename
);
7592 free_a_printer(&printer
,2);
7593 return WERR_ACCESS_DENIED
;
7596 update_c_setprinter(False
);
7597 free_a_printer(&printer
,2);
7602 /****************************************************************************
7603 ****************************************************************************/
7605 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7607 UNISTR2
*uni_srv_name
= q_u
->server_name
;
7608 uint32 level
= q_u
->level
;
7609 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7610 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7611 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7612 uint32 user_switch
= q_u
->user_switch
;
7613 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7614 POLICY_HND
*handle
= &r_u
->handle
;
7618 /* we don't handle yet */
7619 /* but I know what to do ... */
7620 return WERR_UNKNOWN_LEVEL
;
7622 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7624 user_switch
, user
, handle
);
7626 return WERR_UNKNOWN_LEVEL
;
7630 /****************************************************************************
7631 ****************************************************************************/
7633 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7635 uint32 level
= q_u
->level
;
7636 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7637 WERROR err
= WERR_OK
;
7638 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7639 struct current_user user
;
7640 fstring driver_name
;
7643 ZERO_STRUCT(driver
);
7645 get_current_user(&user
, p
);
7647 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7652 DEBUG(5,("Cleaning driver's information\n"));
7653 err
= clean_up_driver_struct(driver
, level
, &user
);
7654 if (!W_ERROR_IS_OK(err
))
7657 DEBUG(5,("Moving driver to final destination\n"));
7658 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(driver
, level
, &user
, &err
)) ) {
7662 if (add_a_printer_driver(driver
, level
)!=0) {
7663 err
= WERR_ACCESS_DENIED
;
7668 * I think this is where he DrvUpgradePrinter() hook would be
7669 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7670 * server. Right now, we just need to send ourselves a message
7671 * to update each printer bound to this driver. --jerry
7674 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7675 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7680 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7681 * decide if the driver init data should be deleted. The rules are:
7682 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7683 * 2) delete init data only if there is no 2k/Xp driver
7684 * 3) always delete init data
7685 * The generalized rule is always use init data from the highest order driver.
7686 * It is necessary to follow the driver install by an initialization step to
7687 * finish off this process.
7690 version
= driver
.info_3
->cversion
;
7691 else if (level
== 6)
7692 version
= driver
.info_6
->version
;
7697 * 9x printer driver - never delete init data
7700 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7705 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7706 * there is no 2k/Xp driver init data for this driver name.
7710 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7712 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7714 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7716 if (!del_driver_init(driver_name
))
7717 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7720 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7722 free_a_printer_driver(driver1
,3);
7723 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7730 * 2k or Xp printer driver - always delete init data
7733 if (!del_driver_init(driver_name
))
7734 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7738 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7744 free_a_printer_driver(driver
, level
);
7748 /********************************************************************
7749 * spoolss_addprinterdriverex
7750 ********************************************************************/
7752 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7754 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7755 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7758 * we only support the semantics of AddPrinterDriver()
7759 * i.e. only copy files that are newer than existing ones
7762 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7763 return WERR_ACCESS_DENIED
;
7765 ZERO_STRUCT(q_u_local
);
7766 ZERO_STRUCT(r_u_local
);
7768 /* just pass the information off to _spoolss_addprinterdriver() */
7769 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7770 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7771 q_u_local
.level
= q_u
->level
;
7772 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7774 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7777 /****************************************************************************
7778 ****************************************************************************/
7780 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7782 init_unistr(&info
->name
, name
);
7785 /****************************************************************************
7786 ****************************************************************************/
7788 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7794 const char *short_archi
;
7795 DRIVER_DIRECTORY_1
*info
=NULL
;
7796 WERROR result
= WERR_OK
;
7798 unistr2_to_ascii(servername
, name
, sizeof(servername
)-1);
7799 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7801 /* check for beginning double '\'s and that the server
7804 pservername
= servername
;
7805 if ( *pservername
== '\\' && strlen(servername
)>2 ) {
7809 if ( !is_myname_or_ipaddr( pservername
) )
7810 return WERR_INVALID_PARAM
;
7812 if (!(short_archi
= get_short_archi(long_archi
)))
7813 return WERR_INVALID_ENVIRONMENT
;
7815 if((info
=SMB_MALLOC_P(DRIVER_DIRECTORY_1
)) == NULL
)
7818 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", pservername
, short_archi
);
7820 DEBUG(4,("printer driver directory: [%s]\n", path
));
7822 fill_driverdir_1(info
, path
);
7824 *needed
+= spoolss_size_driverdir_info_1(info
);
7826 if (*needed
> offered
) {
7827 result
= WERR_INSUFFICIENT_BUFFER
;
7831 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7832 result
= WERR_NOMEM
;
7836 smb_io_driverdir_1("", buffer
, info
, 0);
7844 /****************************************************************************
7845 ****************************************************************************/
7847 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7849 UNISTR2
*name
= &q_u
->name
;
7850 UNISTR2
*uni_environment
= &q_u
->environment
;
7851 uint32 level
= q_u
->level
;
7852 RPC_BUFFER
*buffer
= NULL
;
7853 uint32 offered
= q_u
->offered
;
7854 uint32
*needed
= &r_u
->needed
;
7856 /* that's an [in out] buffer */
7858 if (!q_u
->buffer
&& (offered
!=0)) {
7859 return WERR_INVALID_PARAM
;
7862 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7863 buffer
= r_u
->buffer
;
7865 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7871 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7873 return WERR_UNKNOWN_LEVEL
;
7877 /****************************************************************************
7878 ****************************************************************************/
7880 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7882 POLICY_HND
*handle
= &q_u
->handle
;
7883 uint32 idx
= q_u
->index
;
7884 uint32 in_value_len
= q_u
->valuesize
;
7885 uint32 in_data_len
= q_u
->datasize
;
7886 uint32
*out_max_value_len
= &r_u
->valuesize
;
7887 uint16
**out_value
= &r_u
->value
;
7888 uint32
*out_value_len
= &r_u
->realvaluesize
;
7889 uint32
*out_type
= &r_u
->type
;
7890 uint32
*out_max_data_len
= &r_u
->datasize
;
7891 uint8
**data_out
= &r_u
->data
;
7892 uint32
*out_data_len
= &r_u
->realdatasize
;
7894 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7896 uint32 biggest_valuesize
;
7897 uint32 biggest_datasize
;
7899 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7902 REGISTRY_VALUE
*val
= NULL
;
7903 NT_PRINTER_DATA
*p_data
;
7904 int i
, key_index
, num_values
;
7909 *out_max_data_len
= 0;
7913 DEBUG(5,("spoolss_enumprinterdata\n"));
7916 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7920 if (!get_printer_snum(p
,handle
, &snum
))
7923 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7924 if (!W_ERROR_IS_OK(result
))
7927 p_data
= printer
->info_2
->data
;
7928 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7933 * The NT machine wants to know the biggest size of value and data
7935 * cf: MSDN EnumPrinterData remark section
7938 if ( !in_value_len
&& !in_data_len
&& (key_index
!= -1) )
7940 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7942 biggest_valuesize
= 0;
7943 biggest_datasize
= 0;
7945 num_values
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
7947 for ( i
=0; i
<num_values
; i
++ )
7949 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
7951 name_length
= strlen(val
->valuename
);
7952 if ( strlen(val
->valuename
) > biggest_valuesize
)
7953 biggest_valuesize
= name_length
;
7955 if ( val
->size
> biggest_datasize
)
7956 biggest_datasize
= val
->size
;
7958 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7962 /* the value is an UNICODE string but real_value_size is the length
7963 in bytes including the trailing 0 */
7965 *out_value_len
= 2 * (1+biggest_valuesize
);
7966 *out_data_len
= biggest_datasize
;
7968 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7974 * the value len is wrong in NT sp3
7975 * that's the number of bytes not the number of unicode chars
7978 if ( key_index
!= -1 )
7979 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, idx
);
7984 /* out_value should default to "" or else NT4 has
7985 problems unmarshalling the response */
7987 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7989 if((*out_value
=(uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7991 result
= WERR_NOMEM
;
7995 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7997 /* the data is counted in bytes */
7999 *out_max_data_len
= in_data_len
;
8000 *out_data_len
= in_data_len
;
8002 /* only allocate when given a non-zero data_len */
8004 if ( in_data_len
&& ((*data_out
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
8006 result
= WERR_NOMEM
;
8010 result
= WERR_NO_MORE_ITEMS
;
8016 * - counted in bytes in the request
8017 * - counted in UNICODE chars in the max reply
8018 * - counted in bytes in the real size
8020 * take a pause *before* coding not *during* coding
8024 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
8025 if ( (*out_value
= (uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
8027 result
= WERR_NOMEM
;
8031 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), (size_t)in_value_len
, 0);
8035 *out_type
= regval_type( val
);
8037 /* data - counted in bytes */
8039 *out_max_data_len
= in_data_len
;
8040 if ( in_data_len
&& (*data_out
= (uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
8042 result
= WERR_NOMEM
;
8045 data_len
= regval_size(val
);
8047 memcpy( *data_out
, regval_data_p(val
), data_len
);
8048 *out_data_len
= data_len
;
8052 free_a_printer(&printer
, 2);
8056 /****************************************************************************
8057 ****************************************************************************/
8059 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
8061 POLICY_HND
*handle
= &q_u
->handle
;
8062 UNISTR2
*value
= &q_u
->value
;
8063 uint32 type
= q_u
->type
;
8064 uint8
*data
= q_u
->data
;
8065 uint32 real_len
= q_u
->real_len
;
8067 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8069 WERROR status
= WERR_OK
;
8070 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8073 DEBUG(5,("spoolss_setprinterdata\n"));
8076 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8080 if ( Printer
->printer_type
== SPLHND_SERVER
) {
8081 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8082 return WERR_INVALID_PARAM
;
8085 if (!get_printer_snum(p
,handle
, &snum
))
8089 * Access check : NT returns "access denied" if you make a
8090 * SetPrinterData call without the necessary privildge.
8091 * we were originally returning OK if nothing changed
8092 * which made Win2k issue **a lot** of SetPrinterData
8093 * when connecting to a printer --jerry
8096 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8098 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8099 status
= WERR_ACCESS_DENIED
;
8103 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8104 if (!W_ERROR_IS_OK(status
))
8107 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8110 * When client side code sets a magic printer data key, detect it and save
8111 * the current printer data and the magic key's data (its the DEVMODE) for
8112 * future printer/driver initializations.
8114 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
8116 /* Set devmode and printer initialization info */
8117 status
= save_driver_init( printer
, 2, data
, real_len
);
8119 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
8123 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
8124 type
, data
, real_len
);
8125 if ( W_ERROR_IS_OK(status
) )
8126 status
= mod_a_printer(printer
, 2);
8130 free_a_printer(&printer
, 2);
8135 /****************************************************************************
8136 ****************************************************************************/
8138 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
8140 POLICY_HND
*handle
= &q_u
->handle
;
8141 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8144 DEBUG(5,("_spoolss_resetprinter\n"));
8147 * All we do is to check to see if the handle and queue is valid.
8148 * This call really doesn't mean anything to us because we only
8149 * support RAW printing. --jerry
8153 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8157 if (!get_printer_snum(p
,handle
, &snum
))
8161 /* blindly return success */
8166 /****************************************************************************
8167 ****************************************************************************/
8169 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
8171 POLICY_HND
*handle
= &q_u
->handle
;
8172 UNISTR2
*value
= &q_u
->valuename
;
8174 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8176 WERROR status
= WERR_OK
;
8177 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8180 DEBUG(5,("spoolss_deleteprinterdata\n"));
8183 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8187 if (!get_printer_snum(p
, handle
, &snum
))
8190 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8191 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8192 return WERR_ACCESS_DENIED
;
8195 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8196 if (!W_ERROR_IS_OK(status
))
8199 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8201 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
8203 if ( W_ERROR_IS_OK(status
) )
8204 mod_a_printer( printer
, 2 );
8206 free_a_printer(&printer
, 2);
8211 /****************************************************************************
8212 ****************************************************************************/
8214 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
8216 POLICY_HND
*handle
= &q_u
->handle
;
8217 FORM
*form
= &q_u
->form
;
8218 nt_forms_struct tmpForm
;
8220 WERROR status
= WERR_OK
;
8221 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8224 nt_forms_struct
*list
=NULL
;
8225 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8227 DEBUG(5,("spoolss_addform\n"));
8230 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8235 /* forms can be added on printer of on the print server handle */
8237 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8239 if (!get_printer_snum(p
,handle
, &snum
))
8242 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8243 if (!W_ERROR_IS_OK(status
))
8247 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8248 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8249 status
= WERR_ACCESS_DENIED
;
8253 /* can't add if builtin */
8255 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8256 status
= WERR_ALREADY_EXISTS
;
8260 count
= get_ntforms(&list
);
8262 if(!add_a_form(&list
, form
, &count
)) {
8263 status
= WERR_NOMEM
;
8267 write_ntforms(&list
, count
);
8270 * ChangeID must always be set if this is a printer
8273 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8274 status
= mod_a_printer(printer
, 2);
8278 free_a_printer(&printer
, 2);
8284 /****************************************************************************
8285 ****************************************************************************/
8287 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
8289 POLICY_HND
*handle
= &q_u
->handle
;
8290 UNISTR2
*form_name
= &q_u
->name
;
8291 nt_forms_struct tmpForm
;
8293 nt_forms_struct
*list
=NULL
;
8294 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8296 WERROR status
= WERR_OK
;
8297 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8299 DEBUG(5,("spoolss_deleteform\n"));
8302 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8306 /* forms can be deleted on printer of on the print server handle */
8308 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8310 if (!get_printer_snum(p
,handle
, &snum
))
8313 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8314 if (!W_ERROR_IS_OK(status
))
8318 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8319 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8320 status
= WERR_ACCESS_DENIED
;
8324 /* can't delete if builtin */
8326 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
8327 status
= WERR_INVALID_PARAM
;
8331 count
= get_ntforms(&list
);
8333 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8337 * ChangeID must always be set if this is a printer
8340 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8341 status
= mod_a_printer(printer
, 2);
8345 free_a_printer(&printer
, 2);
8351 /****************************************************************************
8352 ****************************************************************************/
8354 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8356 POLICY_HND
*handle
= &q_u
->handle
;
8357 FORM
*form
= &q_u
->form
;
8358 nt_forms_struct tmpForm
;
8360 WERROR status
= WERR_OK
;
8361 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8364 nt_forms_struct
*list
=NULL
;
8365 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8367 DEBUG(5,("spoolss_setform\n"));
8370 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8374 /* forms can be modified on printer of on the print server handle */
8376 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8378 if (!get_printer_snum(p
,handle
, &snum
))
8381 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8382 if (!W_ERROR_IS_OK(status
))
8386 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8387 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8388 status
= WERR_ACCESS_DENIED
;
8392 /* can't set if builtin */
8393 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8394 status
= WERR_INVALID_PARAM
;
8398 count
= get_ntforms(&list
);
8399 update_a_form(&list
, form
, count
);
8400 write_ntforms(&list
, count
);
8403 * ChangeID must always be set if this is a printer
8406 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8407 status
= mod_a_printer(printer
, 2);
8412 free_a_printer(&printer
, 2);
8418 /****************************************************************************
8419 enumprintprocessors level 1.
8420 ****************************************************************************/
8422 static WERROR
enumprintprocessors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8424 PRINTPROCESSOR_1
*info_1
=NULL
;
8425 WERROR result
= WERR_OK
;
8427 if((info_1
= SMB_MALLOC_P(PRINTPROCESSOR_1
)) == NULL
)
8432 init_unistr(&info_1
->name
, "winprint");
8434 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8436 if (*needed
> offered
) {
8437 result
= WERR_INSUFFICIENT_BUFFER
;
8441 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8442 result
= WERR_NOMEM
;
8446 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8451 if ( !W_ERROR_IS_OK(result
) )
8457 /****************************************************************************
8458 ****************************************************************************/
8460 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8462 uint32 level
= q_u
->level
;
8463 RPC_BUFFER
*buffer
= NULL
;
8464 uint32 offered
= q_u
->offered
;
8465 uint32
*needed
= &r_u
->needed
;
8466 uint32
*returned
= &r_u
->returned
;
8468 /* that's an [in out] buffer */
8470 if (!q_u
->buffer
&& (offered
!=0)) {
8471 return WERR_INVALID_PARAM
;
8474 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8475 buffer
= r_u
->buffer
;
8477 DEBUG(5,("spoolss_enumprintprocessors\n"));
8480 * Enumerate the print processors ...
8482 * Just reply with "winprint", to keep NT happy
8483 * and I can use my nice printer checker.
8491 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8493 return WERR_UNKNOWN_LEVEL
;
8497 /****************************************************************************
8498 enumprintprocdatatypes level 1.
8499 ****************************************************************************/
8501 static WERROR
enumprintprocdatatypes_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8503 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8504 WERROR result
= WERR_OK
;
8506 if((info_1
= SMB_MALLOC_P(PRINTPROCDATATYPE_1
)) == NULL
)
8511 init_unistr(&info_1
->name
, "RAW");
8513 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8515 if (*needed
> offered
) {
8516 result
= WERR_INSUFFICIENT_BUFFER
;
8520 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8521 result
= WERR_NOMEM
;
8525 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8530 if ( !W_ERROR_IS_OK(result
) )
8536 /****************************************************************************
8537 ****************************************************************************/
8539 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8541 uint32 level
= q_u
->level
;
8542 RPC_BUFFER
*buffer
= NULL
;
8543 uint32 offered
= q_u
->offered
;
8544 uint32
*needed
= &r_u
->needed
;
8545 uint32
*returned
= &r_u
->returned
;
8547 /* that's an [in out] buffer */
8549 if (!q_u
->buffer
&& (offered
!=0)) {
8550 return WERR_INVALID_PARAM
;
8553 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8554 buffer
= r_u
->buffer
;
8556 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8563 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8565 return WERR_UNKNOWN_LEVEL
;
8569 /****************************************************************************
8570 enumprintmonitors level 1.
8571 ****************************************************************************/
8573 static WERROR
enumprintmonitors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8575 PRINTMONITOR_1
*info_1
;
8576 WERROR result
= WERR_OK
;
8579 if((info_1
= SMB_MALLOC_ARRAY(PRINTMONITOR_1
, 2)) == NULL
)
8584 init_unistr(&(info_1
[0].name
), SPL_LOCAL_PORT
);
8585 init_unistr(&(info_1
[1].name
), SPL_TCPIP_PORT
);
8587 for ( i
=0; i
<*returned
; i
++ ) {
8588 *needed
+= spoolss_size_printmonitor_info_1(&info_1
[i
]);
8591 if (*needed
> offered
) {
8592 result
= WERR_INSUFFICIENT_BUFFER
;
8596 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8597 result
= WERR_NOMEM
;
8601 for ( i
=0; i
<*returned
; i
++ ) {
8602 smb_io_printmonitor_info_1("", buffer
, &info_1
[i
], 0);
8608 if ( !W_ERROR_IS_OK(result
) )
8614 /****************************************************************************
8615 enumprintmonitors level 2.
8616 ****************************************************************************/
8618 static WERROR
enumprintmonitors_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8620 PRINTMONITOR_2
*info_2
;
8621 WERROR result
= WERR_OK
;
8624 if((info_2
= SMB_MALLOC_ARRAY(PRINTMONITOR_2
, 2)) == NULL
)
8629 init_unistr( &(info_2
[0].name
), SPL_LOCAL_PORT
);
8630 init_unistr( &(info_2
[0].environment
), "Windows NT X86" );
8631 init_unistr( &(info_2
[0].dll_name
), "localmon.dll" );
8633 init_unistr( &(info_2
[1].name
), SPL_TCPIP_PORT
);
8634 init_unistr( &(info_2
[1].environment
), "Windows NT X86" );
8635 init_unistr( &(info_2
[1].dll_name
), "tcpmon.dll" );
8637 for ( i
=0; i
<*returned
; i
++ ) {
8638 *needed
+= spoolss_size_printmonitor_info_2(&info_2
[i
]);
8641 if (*needed
> offered
) {
8642 result
= WERR_INSUFFICIENT_BUFFER
;
8646 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8647 result
= WERR_NOMEM
;
8651 for ( i
=0; i
<*returned
; i
++ ) {
8652 smb_io_printmonitor_info_2("", buffer
, &info_2
[i
], 0);
8658 if ( !W_ERROR_IS_OK(result
) )
8664 /****************************************************************************
8665 ****************************************************************************/
8667 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8669 uint32 level
= q_u
->level
;
8670 RPC_BUFFER
*buffer
= NULL
;
8671 uint32 offered
= q_u
->offered
;
8672 uint32
*needed
= &r_u
->needed
;
8673 uint32
*returned
= &r_u
->returned
;
8675 /* that's an [in out] buffer */
8677 if (!q_u
->buffer
&& (offered
!=0)) {
8678 return WERR_INVALID_PARAM
;
8681 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8682 buffer
= r_u
->buffer
;
8684 DEBUG(5,("spoolss_enumprintmonitors\n"));
8687 * Enumerate the print monitors ...
8689 * Just reply with "Local Port", to keep NT happy
8690 * and I can use my nice printer checker.
8698 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8700 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8702 return WERR_UNKNOWN_LEVEL
;
8706 /****************************************************************************
8707 ****************************************************************************/
8709 static WERROR
getjob_level_1(print_queue_struct
**queue
, int count
, int snum
,
8710 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8711 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8716 JOB_INFO_1
*info_1
=NULL
;
8717 WERROR result
= WERR_OK
;
8719 info_1
=SMB_MALLOC_P(JOB_INFO_1
);
8721 if (info_1
== NULL
) {
8725 for (i
=0; i
<count
&& found
==False
; i
++) {
8726 if ((*queue
)[i
].job
==(int)jobid
)
8732 /* NT treats not found as bad param... yet another bad choice */
8733 return WERR_INVALID_PARAM
;
8736 fill_job_info_1( info_1
, &((*queue
)[i
-1]), i
, snum
, ntprinter
);
8738 *needed
+= spoolss_size_job_info_1(info_1
);
8740 if (*needed
> offered
) {
8741 result
= WERR_INSUFFICIENT_BUFFER
;
8745 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8746 result
= WERR_NOMEM
;
8750 smb_io_job_info_1("", buffer
, info_1
, 0);
8758 /****************************************************************************
8759 ****************************************************************************/
8761 static WERROR
getjob_level_2(print_queue_struct
**queue
, int count
, int snum
,
8762 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8763 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8770 DEVICEMODE
*devmode
= NULL
;
8771 NT_DEVICEMODE
*nt_devmode
= NULL
;
8773 if ( !(info_2
=SMB_MALLOC_P(JOB_INFO_2
)) )
8776 ZERO_STRUCTP(info_2
);
8778 for ( i
=0; i
<count
&& found
==False
; i
++ )
8780 if ((*queue
)[i
].job
== (int)jobid
)
8785 /* NT treats not found as bad param... yet another bad
8787 result
= WERR_INVALID_PARAM
;
8792 * if the print job does not have a DEVMODE associated with it,
8793 * just use the one for the printer. A NULL devicemode is not
8794 * a failure condition
8797 if ( !(nt_devmode
=print_job_devmode( lp_const_servicename(snum
), jobid
)) )
8798 devmode
= construct_dev_mode(lp_const_servicename(snum
));
8800 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) != NULL
) {
8801 ZERO_STRUCTP( devmode
);
8802 convert_nt_devicemode( devmode
, nt_devmode
);
8806 fill_job_info_2(info_2
, &((*queue
)[i
-1]), i
, snum
, ntprinter
, devmode
);
8808 *needed
+= spoolss_size_job_info_2(info_2
);
8810 if (*needed
> offered
) {
8811 result
= WERR_INSUFFICIENT_BUFFER
;
8815 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8816 result
= WERR_NOMEM
;
8820 smb_io_job_info_2("", buffer
, info_2
, 0);
8825 /* Cleanup allocated memory */
8827 free_job_info_2(info_2
); /* Also frees devmode */
8833 /****************************************************************************
8834 ****************************************************************************/
8836 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8838 POLICY_HND
*handle
= &q_u
->handle
;
8839 uint32 jobid
= q_u
->jobid
;
8840 uint32 level
= q_u
->level
;
8841 RPC_BUFFER
*buffer
= NULL
;
8842 uint32 offered
= q_u
->offered
;
8843 uint32
*needed
= &r_u
->needed
;
8844 WERROR wstatus
= WERR_OK
;
8845 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8848 print_queue_struct
*queue
= NULL
;
8849 print_status_struct prt_status
;
8851 /* that's an [in out] buffer */
8853 if (!q_u
->buffer
&& (offered
!=0)) {
8854 return WERR_INVALID_PARAM
;
8857 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8858 buffer
= r_u
->buffer
;
8860 DEBUG(5,("spoolss_getjob\n"));
8864 if (!get_printer_snum(p
, handle
, &snum
))
8867 wstatus
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8868 if ( !W_ERROR_IS_OK(wstatus
) )
8871 count
= print_queue_status(snum
, &queue
, &prt_status
);
8873 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8874 count
, prt_status
.status
, prt_status
.message
));
8878 wstatus
= getjob_level_1(&queue
, count
, snum
, ntprinter
, jobid
,
8879 buffer
, offered
, needed
);
8882 wstatus
= getjob_level_2(&queue
, count
, snum
, ntprinter
, jobid
,
8883 buffer
, offered
, needed
);
8886 wstatus
= WERR_UNKNOWN_LEVEL
;
8891 free_a_printer( &ntprinter
, 2 );
8896 /********************************************************************
8897 spoolss_getprinterdataex
8899 From MSDN documentation of GetPrinterDataEx: pass request
8900 to GetPrinterData if key is "PrinterDriverData".
8901 ********************************************************************/
8903 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8905 POLICY_HND
*handle
= &q_u
->handle
;
8906 uint32 in_size
= q_u
->size
;
8907 uint32
*type
= &r_u
->type
;
8908 uint32
*out_size
= &r_u
->size
;
8909 uint8
**data
= &r_u
->data
;
8910 uint32
*needed
= &r_u
->needed
;
8911 fstring keyname
, valuename
;
8913 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8915 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8917 WERROR status
= WERR_OK
;
8919 DEBUG(4,("_spoolss_getprinterdataex\n"));
8921 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8922 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8924 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8925 keyname
, valuename
));
8927 /* in case of problem, return some default values */
8931 *out_size
= in_size
;
8934 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8935 status
= WERR_BADFID
;
8939 /* Is the handle to a printer or to the server? */
8941 if (Printer
->printer_type
== SPLHND_SERVER
) {
8942 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8943 status
= WERR_INVALID_PARAM
;
8947 if ( !get_printer_snum(p
,handle
, &snum
) )
8950 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8951 if ( !W_ERROR_IS_OK(status
) )
8954 /* check to see if the keyname is valid */
8955 if ( !strlen(keyname
) ) {
8956 status
= WERR_INVALID_PARAM
;
8960 if ( lookup_printerkey( printer
->info_2
->data
, keyname
) == -1 ) {
8961 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8962 free_a_printer( &printer
, 2 );
8963 status
= WERR_BADFILE
;
8967 /* When given a new keyname, we should just create it */
8969 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8971 if (*needed
> *out_size
)
8972 status
= WERR_MORE_DATA
;
8975 if ( !W_ERROR_IS_OK(status
) )
8977 DEBUG(5, ("error: allocating %d\n", *out_size
));
8979 /* reply this param doesn't exist */
8983 if( (*data
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8984 status
= WERR_NOMEM
;
8994 free_a_printer( &printer
, 2 );
8999 /********************************************************************
9000 * spoolss_setprinterdataex
9001 ********************************************************************/
9003 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
9005 POLICY_HND
*handle
= &q_u
->handle
;
9006 uint32 type
= q_u
->type
;
9007 uint8
*data
= q_u
->data
;
9008 uint32 real_len
= q_u
->real_len
;
9010 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9012 WERROR status
= WERR_OK
;
9013 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9018 DEBUG(4,("_spoolss_setprinterdataex\n"));
9020 /* From MSDN documentation of SetPrinterDataEx: pass request to
9021 SetPrinterData if key is "PrinterDriverData" */
9024 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9028 if ( Printer
->printer_type
== SPLHND_SERVER
) {
9029 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9030 return WERR_INVALID_PARAM
;
9033 if ( !get_printer_snum(p
,handle
, &snum
) )
9037 * Access check : NT returns "access denied" if you make a
9038 * SetPrinterData call without the necessary privildge.
9039 * we were originally returning OK if nothing changed
9040 * which made Win2k issue **a lot** of SetPrinterData
9041 * when connecting to a printer --jerry
9044 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
9046 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9047 return WERR_ACCESS_DENIED
;
9050 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9051 if (!W_ERROR_IS_OK(status
))
9054 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
9055 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
9057 /* check for OID in valuename */
9059 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
9065 /* save the registry data */
9067 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
9069 if ( W_ERROR_IS_OK(status
) )
9071 /* save the OID if one was specified */
9073 fstrcat( keyname
, "\\" );
9074 fstrcat( keyname
, SPOOL_OID_KEY
);
9077 * I'm not checking the status here on purpose. Don't know
9078 * if this is right, but I'm returning the status from the
9079 * previous set_printer_dataex() call. I have no idea if
9080 * this is right. --jerry
9083 set_printer_dataex( printer
, keyname
, valuename
,
9084 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
9087 status
= mod_a_printer(printer
, 2);
9090 free_a_printer(&printer
, 2);
9096 /********************************************************************
9097 * spoolss_deleteprinterdataex
9098 ********************************************************************/
9100 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
9102 POLICY_HND
*handle
= &q_u
->handle
;
9103 UNISTR2
*value
= &q_u
->valuename
;
9104 UNISTR2
*key
= &q_u
->keyname
;
9106 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9108 WERROR status
= WERR_OK
;
9109 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
9110 pstring valuename
, keyname
;
9112 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9115 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9119 if (!get_printer_snum(p
, handle
, &snum
))
9122 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9123 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9124 return WERR_ACCESS_DENIED
;
9127 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9128 if (!W_ERROR_IS_OK(status
))
9131 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
9132 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
9134 status
= delete_printer_dataex( printer
, keyname
, valuename
);
9136 if ( W_ERROR_IS_OK(status
) )
9137 mod_a_printer( printer
, 2 );
9139 free_a_printer(&printer
, 2);
9144 /********************************************************************
9145 * spoolss_enumprinterkey
9146 ********************************************************************/
9149 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
9152 fstring
*keynames
= NULL
;
9153 uint16
*enumkeys
= NULL
;
9156 POLICY_HND
*handle
= &q_u
->handle
;
9157 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9158 NT_PRINTER_DATA
*data
;
9159 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9161 WERROR status
= WERR_BADFILE
;
9164 DEBUG(4,("_spoolss_enumprinterkey\n"));
9167 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9171 if ( !get_printer_snum(p
,handle
, &snum
) )
9174 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9175 if (!W_ERROR_IS_OK(status
))
9178 /* get the list of subkey names */
9180 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
9181 data
= printer
->info_2
->data
;
9183 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
9185 if ( num_keys
== -1 ) {
9186 status
= WERR_BADFILE
;
9190 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
9192 r_u
->needed
= printerkey_len
*2;
9194 if ( q_u
->size
< r_u
->needed
) {
9195 status
= WERR_MORE_DATA
;
9199 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
9200 status
= WERR_NOMEM
;
9206 if ( q_u
->size
< r_u
->needed
)
9207 status
= WERR_MORE_DATA
;
9210 free_a_printer( &printer
, 2 );
9211 SAFE_FREE( keynames
);
9216 /********************************************************************
9217 * spoolss_deleteprinterkey
9218 ********************************************************************/
9220 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
9222 POLICY_HND
*handle
= &q_u
->handle
;
9223 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9225 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9229 DEBUG(5,("spoolss_deleteprinterkey\n"));
9232 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9236 /* if keyname == NULL, return error */
9238 if ( !q_u
->keyname
.buffer
)
9239 return WERR_INVALID_PARAM
;
9241 if (!get_printer_snum(p
, handle
, &snum
))
9244 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9245 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9246 return WERR_ACCESS_DENIED
;
9249 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9250 if (!W_ERROR_IS_OK(status
))
9253 /* delete the key and all subneys */
9255 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
9257 status
= delete_all_printer_data( printer
->info_2
, key
);
9259 if ( W_ERROR_IS_OK(status
) )
9260 status
= mod_a_printer(printer
, 2);
9262 free_a_printer( &printer
, 2 );
9268 /********************************************************************
9269 * spoolss_enumprinterdataex
9270 ********************************************************************/
9272 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9274 POLICY_HND
*handle
= &q_u
->handle
;
9275 uint32 in_size
= q_u
->size
;
9278 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9279 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9280 NT_PRINTER_DATA
*p_data
;
9282 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9287 REGISTRY_VALUE
*val
;
9292 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9295 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9300 * first check for a keyname of NULL or "". Win2k seems to send
9301 * this a lot and we should send back WERR_INVALID_PARAM
9302 * no need to spend time looking up the printer in this case.
9306 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9307 if ( !strlen(key
) ) {
9308 result
= WERR_INVALID_PARAM
;
9312 /* get the printer off of disk */
9314 if (!get_printer_snum(p
,handle
, &snum
))
9317 ZERO_STRUCT(printer
);
9318 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9319 if (!W_ERROR_IS_OK(result
))
9322 /* now look for a match on the key name */
9324 p_data
= printer
->info_2
->data
;
9326 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9327 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9329 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9330 result
= WERR_INVALID_PARAM
;
9337 /* allocate the memory for the array of pointers -- if necessary */
9339 num_entries
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
9342 if ( (enum_values
=TALLOC_ARRAY(p
->mem_ctx
, PRINTER_ENUM_VALUES
, num_entries
)) == NULL
)
9344 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9345 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9346 result
= WERR_NOMEM
;
9350 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9354 * loop through all params and build the array to pass
9355 * back to the client
9358 for ( i
=0; i
<num_entries
; i
++ )
9360 /* lookup the registry value */
9362 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
9363 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9367 value_name
= regval_name( val
);
9368 init_unistr( &enum_values
[i
].valuename
, value_name
);
9369 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9370 enum_values
[i
].type
= regval_type( val
);
9372 data_len
= regval_size( val
);
9374 if ( !(enum_values
[i
].data
= TALLOC_MEMDUP(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9376 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9378 result
= WERR_NOMEM
;
9382 enum_values
[i
].data_len
= data_len
;
9384 /* keep track of the size of the array in bytes */
9386 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9389 /* housekeeping information in the reply */
9391 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9392 * the hand marshalled container size is a multiple
9393 * of 4 bytes for RPC alignment.
9397 needed
+= 4-(needed
% 4);
9400 r_u
->needed
= needed
;
9401 r_u
->returned
= num_entries
;
9403 if (needed
> in_size
) {
9404 result
= WERR_MORE_DATA
;
9408 /* copy data into the reply */
9410 r_u
->ctr
.size
= r_u
->needed
;
9412 r_u
->ctr
.size_of_array
= r_u
->returned
;
9413 r_u
->ctr
.values
= enum_values
;
9419 free_a_printer(&printer
, 2);
9424 /****************************************************************************
9425 ****************************************************************************/
9427 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9429 init_unistr(&info
->name
, name
);
9432 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9433 UNISTR2
*environment
,
9440 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9441 WERROR result
= WERR_OK
;
9443 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9445 if (!get_short_archi(long_archi
))
9446 return WERR_INVALID_ENVIRONMENT
;
9448 if((info
=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1
)) == NULL
)
9451 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9453 fill_printprocessordirectory_1(info
, path
);
9455 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9457 if (*needed
> offered
) {
9458 result
= WERR_INSUFFICIENT_BUFFER
;
9462 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
9463 result
= WERR_INSUFFICIENT_BUFFER
;
9467 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9475 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9477 uint32 level
= q_u
->level
;
9478 RPC_BUFFER
*buffer
= NULL
;
9479 uint32 offered
= q_u
->offered
;
9480 uint32
*needed
= &r_u
->needed
;
9483 /* that's an [in out] buffer */
9485 if (!q_u
->buffer
&& (offered
!=0)) {
9486 return WERR_INVALID_PARAM
;
9489 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
9490 buffer
= r_u
->buffer
;
9492 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9498 result
= getprintprocessordirectory_level_1
9499 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9502 result
= WERR_UNKNOWN_LEVEL
;
9508 /*******************************************************************
9509 Streams the monitor UI DLL name in UNICODE
9510 *******************************************************************/
9512 static WERROR
xcvtcp_monitorui( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9513 RPC_BUFFER
*out
, uint32
*needed
)
9515 const char *dllname
= "tcpmonui.dll";
9517 *needed
= (strlen(dllname
)+1) * 2;
9519 if ( rpcbuf_get_size(out
) < *needed
) {
9520 return WERR_INSUFFICIENT_BUFFER
;
9523 if ( !make_monitorui_buf( out
, dllname
) ) {
9530 /*******************************************************************
9531 Create a new TCP/IP port
9532 *******************************************************************/
9534 static WERROR
xcvtcp_addport( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9535 RPC_BUFFER
*out
, uint32
*needed
)
9537 NT_PORT_DATA_1 port1
;
9540 ZERO_STRUCT( port1
);
9542 /* convert to our internal port data structure */
9544 if ( !convert_port_data_1( &port1
, in
) ) {
9548 /* create the device URI and call the add_port_hook() */
9550 switch ( port1
.protocol
) {
9551 case PORT_PROTOCOL_DIRECT
:
9552 pstr_sprintf( device_uri
, "socket://%s:%d/", port1
.hostaddr
, port1
.port
);
9555 case PORT_PROTOCOL_LPR
:
9556 pstr_sprintf( device_uri
, "lpr://%s/%s", port1
.hostaddr
, port1
.queue
);
9560 return WERR_UNKNOWN_PORT
;
9563 return add_port_hook( token
, port1
.name
, device_uri
);
9566 /*******************************************************************
9567 *******************************************************************/
9569 struct xcv_api_table xcvtcp_cmds
[] = {
9570 { "MonitorUI", xcvtcp_monitorui
},
9571 { "AddPort", xcvtcp_addport
},
9575 static WERROR
process_xcvtcp_command( NT_USER_TOKEN
*token
, const char *command
,
9576 RPC_BUFFER
*inbuf
, RPC_BUFFER
*outbuf
,
9581 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9583 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9584 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9585 return xcvtcp_cmds
[i
].fn( token
, inbuf
, outbuf
, needed
);
9588 return WERR_BADFUNC
;
9591 /*******************************************************************
9592 *******************************************************************/
9593 #if 0 /* don't support management using the "Local Port" monitor */
9595 static WERROR
xcvlocal_monitorui( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9596 RPC_BUFFER
*out
, uint32
*needed
)
9598 const char *dllname
= "localui.dll";
9600 *needed
= (strlen(dllname
)+1) * 2;
9602 if ( rpcbuf_get_size(out
) < *needed
) {
9603 return WERR_INSUFFICIENT_BUFFER
;
9606 if ( !make_monitorui_buf( out
, dllname
)) {
9613 /*******************************************************************
9614 *******************************************************************/
9616 struct xcv_api_table xcvlocal_cmds
[] = {
9617 { "MonitorUI", xcvlocal_monitorui
},
9621 struct xcv_api_table xcvlocal_cmds
[] = {
9628 /*******************************************************************
9629 *******************************************************************/
9631 static WERROR
process_xcvlocal_command( NT_USER_TOKEN
*token
, const char *command
,
9632 RPC_BUFFER
*inbuf
, RPC_BUFFER
*outbuf
,
9637 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9639 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9640 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9641 return xcvlocal_cmds
[i
].fn( token
, inbuf
, outbuf
, needed
);
9643 return WERR_BADFUNC
;
9646 /*******************************************************************
9647 *******************************************************************/
9649 WERROR
_spoolss_xcvdataport(pipes_struct
*p
, SPOOL_Q_XCVDATAPORT
*q_u
, SPOOL_R_XCVDATAPORT
*r_u
)
9651 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9655 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u
->handle
)));
9659 /* Has to be a handle to the TCP/IP port monitor */
9661 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9662 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9666 /* requires administrative access to the server */
9668 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9669 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9670 return WERR_ACCESS_DENIED
;
9673 /* Get the command name. There's numerous commands supported by the
9674 TCPMON interface. */
9676 rpcstr_pull(command
, q_u
->dataname
.buffer
, sizeof(command
),
9677 q_u
->dataname
.uni_str_len
*2, 0);
9679 /* Allocate the outgoing buffer */
9681 rpcbuf_init( &r_u
->outdata
, q_u
->offered
, p
->mem_ctx
);
9683 switch ( Printer
->printer_type
) {
9684 case SPLHND_PORTMON_TCP
:
9685 return process_xcvtcp_command( p
->pipe_user
.nt_user_token
, command
,
9686 &q_u
->indata
, &r_u
->outdata
, &r_u
->needed
);
9687 case SPLHND_PORTMON_LOCAL
:
9688 return process_xcvlocal_command( p
->pipe_user
.nt_user_token
, command
,
9689 &q_u
->indata
, &r_u
->outdata
, &r_u
->needed
);
9692 return WERR_INVALID_PRINT_MONITOR
;