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
));
514 /* This call doesn't fill in the location or comment from
515 * a CUPS server for efficiency with large numbers of printers.
518 result
= get_a_printer_search( NULL
, &printer
, 2, sname
);
519 if ( !W_ERROR_IS_OK(result
) ) {
520 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
521 sname
, dos_errstr(result
)));
525 /* printername is always returned as \\server\printername */
526 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
527 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
528 printer
->info_2
->printername
));
529 free_a_printer( &printer
, 2);
535 if ( strequal(printername
, aprinter
) ) {
536 free_a_printer( &printer
, 2);
541 DEBUGADD(10, ("printername: %s\n", printername
));
543 free_a_printer( &printer
, 2);
546 free_a_printer( &printer
, 2);
549 DEBUGADD(4,("Printer not found\n"));
553 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
555 fstrcpy(Printer
->sharename
, sname
);
560 /****************************************************************************
561 Find first available printer slot. creates a printer handle for you.
562 ****************************************************************************/
564 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
566 Printer_entry
*new_printer
;
568 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
570 if((new_printer
=SMB_MALLOC_P(Printer_entry
)) == NULL
)
573 ZERO_STRUCTP(new_printer
);
575 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
576 SAFE_FREE(new_printer
);
580 /* Add to the internal list. */
581 DLIST_ADD(printers_list
, new_printer
);
583 new_printer
->notify
.option
=NULL
;
585 if ( !(new_printer
->ctx
= talloc_init("Printer Entry [%p]", hnd
)) ) {
586 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
587 close_printer_handle(p
, hnd
);
591 if (!set_printer_hnd_printertype(new_printer
, name
)) {
592 close_printer_handle(p
, hnd
);
596 if (!set_printer_hnd_name(new_printer
, name
)) {
597 close_printer_handle(p
, hnd
);
601 new_printer
->access_granted
= access_granted
;
603 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
608 /***************************************************************************
609 check to see if the client motify handle is monitoring the notification
610 given by (notify_type, notify_field).
611 **************************************************************************/
613 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
619 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
622 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
626 * Flags should always be zero when the change notify
627 * is registered by the client's spooler. A user Win32 app
628 * might use the flags though instead of the NOTIFY_OPTION_INFO
637 return is_monitoring_event_flags(
638 p
->notify
.flags
, notify_type
, notify_field
);
640 for (i
= 0; i
< option
->count
; i
++) {
642 /* Check match for notify_type */
644 if (option
->ctr
.type
[i
].type
!= notify_type
)
647 /* Check match for field */
649 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
650 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
656 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
657 p
->servername
, p
->sharename
, notify_type
, notify_field
));
662 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
664 static void notify_one_value(struct spoolss_notify_msg
*msg
,
665 SPOOL_NOTIFY_INFO_DATA
*data
,
668 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
669 data
->notify_data
.value
[1] = 0;
672 static void notify_string(struct spoolss_notify_msg
*msg
,
673 SPOOL_NOTIFY_INFO_DATA
*data
,
678 /* The length of the message includes the trailing \0 */
680 init_unistr2(&unistr
, msg
->notify
.data
, UNI_STR_TERMINATE
);
682 data
->notify_data
.data
.length
= msg
->len
* 2;
683 data
->notify_data
.data
.string
= TALLOC_ARRAY(mem_ctx
, uint16
, msg
->len
);
685 if (!data
->notify_data
.data
.string
) {
686 data
->notify_data
.data
.length
= 0;
690 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
693 static void notify_system_time(struct spoolss_notify_msg
*msg
,
694 SPOOL_NOTIFY_INFO_DATA
*data
,
700 if (msg
->len
!= sizeof(time_t)) {
701 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
706 if (!prs_init(&ps
, RPC_MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
707 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
711 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
712 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
717 if (!spoolss_io_system_time("", &ps
, 0, &systime
)) {
722 data
->notify_data
.data
.length
= prs_offset(&ps
);
723 if (prs_offset(&ps
)) {
724 data
->notify_data
.data
.string
= (uint16
*)
725 TALLOC(mem_ctx
, prs_offset(&ps
));
726 if (!data
->notify_data
.data
.string
) {
730 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
732 data
->notify_data
.data
.string
= NULL
;
738 struct notify2_message_table
{
740 void (*fn
)(struct spoolss_notify_msg
*msg
,
741 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
744 static struct notify2_message_table printer_notify_table
[] = {
745 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
746 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
747 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
748 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
749 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
750 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
751 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
752 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
753 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
754 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
755 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
756 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
757 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
758 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
759 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
760 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
761 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
762 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
763 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
766 static struct notify2_message_table job_notify_table
[] = {
767 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
768 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
769 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
770 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
771 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
772 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
773 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
774 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
775 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
776 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
777 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
778 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
779 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
780 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
781 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
782 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
783 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
784 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
785 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
786 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
787 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
788 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
789 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
790 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
794 /***********************************************************************
795 Allocate talloc context for container object
796 **********************************************************************/
798 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
803 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
808 /***********************************************************************
809 release all allocated memory and zero out structure
810 **********************************************************************/
812 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
818 talloc_destroy(ctr
->ctx
);
825 /***********************************************************************
826 **********************************************************************/
828 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
836 /***********************************************************************
837 **********************************************************************/
839 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
841 if ( !ctr
|| !ctr
->msg_groups
)
844 if ( idx
>= ctr
->num_groups
)
847 return &ctr
->msg_groups
[idx
];
851 /***********************************************************************
852 How many groups of change messages do we have ?
853 **********************************************************************/
855 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
860 return ctr
->num_groups
;
863 /***********************************************************************
864 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
865 **********************************************************************/
867 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
869 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
870 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
871 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
877 /* loop over all groups looking for a matching printer name */
879 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
880 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
884 /* add a new group? */
886 if ( i
== ctr
->num_groups
) {
889 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
890 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
893 ctr
->msg_groups
= groups
;
895 /* clear the new entry and set the printer name */
897 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
898 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
901 /* add the change messages; 'i' is the correct index now regardless */
903 msg_grp
= &ctr
->msg_groups
[i
];
907 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
908 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
911 msg_grp
->msgs
= msg_list
;
913 new_slot
= msg_grp
->num_msgs
-1;
914 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
916 /* need to allocate own copy of data */
919 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
920 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
922 return ctr
->num_groups
;
925 /***********************************************************************
926 Send a change notication message on all handles which have a call
928 **********************************************************************/
930 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
933 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
934 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
935 SPOOLSS_NOTIFY_MSG
*messages
;
936 int sending_msg_count
;
939 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
943 messages
= msg_group
->msgs
;
946 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
950 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
952 /* loop over all printers */
954 for (p
= printers_list
; p
; p
= p
->next
) {
955 SPOOL_NOTIFY_INFO_DATA
*data
;
960 /* Is there notification on this handle? */
962 if ( !p
->notify
.client_connected
)
965 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
967 /* For this printer? Print servers always receive
970 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
971 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
974 DEBUG(10,("Our printer\n"));
976 /* allocate the max entries possible */
978 data
= TALLOC_ARRAY( mem_ctx
, SPOOL_NOTIFY_INFO_DATA
, msg_group
->num_msgs
);
985 /* build the array of change notifications */
987 sending_msg_count
= 0;
989 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
990 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
992 /* Are we monitoring this event? */
994 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1000 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1001 msg
->type
, msg
->field
, p
->sharename
));
1004 * if the is a printer notification handle and not a job notification
1005 * type, then set the id to 0. Other wise just use what was specified
1008 * When registering change notification on a print server handle
1009 * we always need to send back the id (snum) matching the printer
1010 * for which the change took place. For change notify registered
1011 * on a printer handle, this does not matter and the id should be 0.
1016 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1022 /* Convert unix jobid to smb jobid */
1024 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1025 id
= sysjob_to_jobid(msg
->id
);
1028 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1033 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1036 case PRINTER_NOTIFY_TYPE
:
1037 if ( printer_notify_table
[msg
->field
].fn
)
1038 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1041 case JOB_NOTIFY_TYPE
:
1042 if ( job_notify_table
[msg
->field
].fn
)
1043 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1047 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1054 if ( sending_msg_count
) {
1055 rpccli_spoolss_rrpcn( notify_cli_pipe
, mem_ctx
, &p
->notify
.client_hnd
,
1056 data_len
, data
, p
->notify
.change
, 0 );
1061 DEBUG(8,("send_notify2_changes: Exit...\n"));
1065 /***********************************************************************
1066 **********************************************************************/
1068 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1071 uint32 tv_sec
, tv_usec
;
1074 /* Unpack message */
1076 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1079 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddddd",
1081 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1084 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1085 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1087 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1088 &msg
->len
, &msg
->notify
.data
);
1090 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1091 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1093 tv
->tv_sec
= tv_sec
;
1094 tv
->tv_usec
= tv_usec
;
1097 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1098 msg
->notify
.value
[1]));
1100 dump_data(3, msg
->notify
.data
, msg
->len
);
1105 /********************************************************************
1106 Receive a notify2 message list
1107 ********************************************************************/
1109 static void receive_notify2_message_list(int msg_type
, struct process_id src
,
1110 void *msg
, size_t len
,
1113 size_t msg_count
, i
;
1114 char *buf
= (char *)msg
;
1117 SPOOLSS_NOTIFY_MSG notify
;
1118 SPOOLSS_NOTIFY_MSG_CTR messages
;
1122 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1126 msg_count
= IVAL(buf
, 0);
1129 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1131 if (msg_count
== 0) {
1132 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1136 /* initialize the container */
1138 ZERO_STRUCT( messages
);
1139 notify_msg_ctr_init( &messages
);
1142 * build message groups for each printer identified
1143 * in a change_notify msg. Remember that a PCN message
1144 * includes the handle returned for the srv_spoolss_replyopenprinter()
1145 * call. Therefore messages are grouped according to printer handle.
1148 for ( i
=0; i
<msg_count
; i
++ ) {
1149 struct timeval msg_tv
;
1151 if (msg_ptr
+ 4 - buf
> len
) {
1152 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1156 msg_len
= IVAL(msg_ptr
,0);
1159 if (msg_ptr
+ msg_len
- buf
> len
) {
1160 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1164 /* unpack messages */
1166 ZERO_STRUCT( notify
);
1167 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1170 /* add to correct list in container */
1172 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1174 /* free memory that might have been allocated by notify2_unpack_msg() */
1176 if ( notify
.len
!= 0 )
1177 SAFE_FREE( notify
.notify
.data
);
1180 /* process each group of messages */
1182 num_groups
= notify_msg_ctr_numgroups( &messages
);
1183 for ( i
=0; i
<num_groups
; i
++ )
1184 send_notify2_changes( &messages
, i
);
1189 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1191 notify_msg_ctr_destroy( &messages
);
1196 /********************************************************************
1197 Send a message to ourself about new driver being installed
1198 so we can upgrade the information for each printer bound to this
1200 ********************************************************************/
1202 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1204 int len
= strlen(drivername
);
1209 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1212 message_send_pid(pid_to_procid(sys_getpid()),
1213 MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1218 /**********************************************************************
1219 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1220 over all printers, upgrading ones as necessary
1221 **********************************************************************/
1223 void do_drv_upgrade_printer(int msg_type
, struct process_id src
,
1224 void *buf
, size_t len
, void *private_data
)
1228 int n_services
= lp_numservices();
1230 len
= MIN(len
,sizeof(drivername
)-1);
1231 strncpy(drivername
, (const char *)buf
, len
);
1233 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1235 /* Iterate the printer list */
1237 for (snum
=0; snum
<n_services
; snum
++)
1239 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1242 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1244 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1245 if (!W_ERROR_IS_OK(result
))
1248 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1250 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1252 /* all we care about currently is the change_id */
1254 result
= mod_a_printer(printer
, 2);
1255 if (!W_ERROR_IS_OK(result
)) {
1256 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1257 dos_errstr(result
)));
1261 free_a_printer(&printer
, 2);
1268 /********************************************************************
1269 Update the cache for all printq's with a registered client
1271 ********************************************************************/
1273 void update_monitored_printq_cache( void )
1275 Printer_entry
*printer
= printers_list
;
1278 /* loop through all printers and update the cache where
1279 client_connected == True */
1282 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1283 && printer
->notify
.client_connected
)
1285 snum
= print_queue_snum(printer
->sharename
);
1286 print_queue_status( snum
, NULL
, NULL
);
1289 printer
= printer
->next
;
1294 /********************************************************************
1295 Send a message to ourself about new driver being installed
1296 so we can upgrade the information for each printer bound to this
1298 ********************************************************************/
1300 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1302 int len
= strlen(drivername
);
1307 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1310 message_send_pid(pid_to_procid(sys_getpid()),
1311 MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1316 /**********************************************************************
1317 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1318 over all printers, resetting printer data as neessary
1319 **********************************************************************/
1321 void reset_all_printerdata(int msg_type
, struct process_id src
,
1322 void *buf
, size_t len
, void *private_data
)
1326 int n_services
= lp_numservices();
1328 len
= MIN( len
, sizeof(drivername
)-1 );
1329 strncpy( drivername
, (const char *)buf
, len
);
1331 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1333 /* Iterate the printer list */
1335 for ( snum
=0; snum
<n_services
; snum
++ )
1337 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1340 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1342 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1343 if ( !W_ERROR_IS_OK(result
) )
1347 * if the printer is bound to the driver,
1348 * then reset to the new driver initdata
1351 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1353 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1355 if ( !set_driver_init(printer
, 2) ) {
1356 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1357 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1360 result
= mod_a_printer( printer
, 2 );
1361 if ( !W_ERROR_IS_OK(result
) ) {
1362 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1363 get_dos_error_msg(result
)));
1367 free_a_printer( &printer
, 2 );
1376 /********************************************************************
1377 Copy routines used by convert_to_openprinterex()
1378 *******************************************************************/
1380 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1388 DEBUG (8,("dup_devmode\n"));
1390 /* bulk copy first */
1392 d
= (DEVICEMODE
*)TALLOC_MEMDUP(ctx
, devmode
, sizeof(DEVICEMODE
));
1396 /* dup the pointer members separately */
1398 len
= unistrlen(devmode
->devicename
.buffer
);
1400 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1401 if (!d
->devicename
.buffer
) {
1404 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1409 len
= unistrlen(devmode
->formname
.buffer
);
1411 d
->formname
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1412 if (!d
->formname
.buffer
) {
1415 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1419 if (devmode
->driverextra
) {
1420 d
->dev_private
= (uint8
*)TALLOC_MEMDUP(ctx
, devmode
->dev_private
,
1421 devmode
->driverextra
);
1422 if (!d
->dev_private
) {
1426 d
->dev_private
= NULL
;
1431 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1433 if (!new_ctr
|| !ctr
)
1436 DEBUG(8,("copy_devmode_ctr\n"));
1438 new_ctr
->size
= ctr
->size
;
1439 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1441 if(ctr
->devmode_ptr
)
1442 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1445 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1447 if (!new_def
|| !def
)
1450 DEBUG(8,("copy_printer_defaults\n"));
1452 new_def
->datatype_ptr
= def
->datatype_ptr
;
1454 if (def
->datatype_ptr
)
1455 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1457 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1459 new_def
->access_required
= def
->access_required
;
1462 /********************************************************************
1463 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1464 * SPOOL_Q_OPEN_PRINTER_EX structure
1465 ********************************************************************/
1467 static WERROR
convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1469 if (!q_u_ex
|| !q_u
)
1472 DEBUG(8,("convert_to_openprinterex\n"));
1474 if ( q_u
->printername
) {
1475 q_u_ex
->printername
= TALLOC_ZERO_P( ctx
, UNISTR2
);
1476 if (q_u_ex
->printername
== NULL
)
1478 copy_unistr2(q_u_ex
->printername
, q_u
->printername
);
1481 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1486 /********************************************************************
1487 * spoolss_open_printer
1489 * called from the spoolss dispatcher
1490 ********************************************************************/
1492 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1494 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1495 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1500 ZERO_STRUCT(q_u_ex
);
1501 ZERO_STRUCT(r_u_ex
);
1503 /* convert the OpenPrinter() call to OpenPrinterEx() */
1505 r_u_ex
.status
= convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1506 if (!W_ERROR_IS_OK(r_u_ex
.status
))
1507 return r_u_ex
.status
;
1509 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1511 /* convert back to OpenPrinter() */
1513 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1518 /********************************************************************
1519 ********************************************************************/
1521 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1523 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1524 POLICY_HND
*handle
= &r_u
->handle
;
1528 struct current_user user
;
1529 Printer_entry
*Printer
=NULL
;
1531 if ( !q_u
->printername
)
1532 return WERR_INVALID_PRINTER_NAME
;
1534 /* some sanity check because you can open a printer or a print server */
1535 /* aka: \\server\printer or \\server */
1537 unistr2_to_ascii(name
, q_u
->printername
, sizeof(name
)-1);
1539 DEBUGADD(3,("checking name: %s\n",name
));
1541 if (!open_printer_hnd(p
, handle
, name
, 0))
1542 return WERR_INVALID_PRINTER_NAME
;
1544 Printer
=find_printer_index_by_hnd(p
, handle
);
1546 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1547 "handle we created for printer %s\n", name
));
1548 close_printer_handle(p
,handle
);
1549 return WERR_INVALID_PRINTER_NAME
;
1552 get_current_user(&user
, p
);
1555 * First case: the user is opening the print server:
1557 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1558 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1560 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1561 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1562 * or if the user is listed in the smb.conf printer admin parameter.
1564 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1565 * client view printer folder, but does not show the MSAPW.
1567 * Note: this test needs code to check access rights here too. Jeremy
1568 * could you look at this?
1570 * Second case: the user is opening a printer:
1571 * NT doesn't let us connect to a printer if the connecting user
1572 * doesn't have print permission.
1574 * Third case: user is opening a Port Monitor
1575 * access checks same as opening a handle to the print server.
1578 switch (Printer
->printer_type
)
1581 case SPLHND_PORTMON_TCP
:
1582 case SPLHND_PORTMON_LOCAL
:
1583 /* Printserver handles use global struct... */
1587 /* Map standard access rights to object specific access rights */
1589 se_map_standard(&printer_default
->access_required
,
1590 &printserver_std_mapping
);
1592 /* Deny any object specific bits that don't apply to print
1593 servers (i.e printer and job specific bits) */
1595 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1597 if (printer_default
->access_required
&
1598 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1599 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1600 close_printer_handle(p
, handle
);
1601 return WERR_ACCESS_DENIED
;
1604 /* Allow admin access */
1606 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1608 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1610 if (!lp_ms_add_printer_wizard()) {
1611 close_printer_handle(p
, handle
);
1612 return WERR_ACCESS_DENIED
;
1615 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1616 and not a printer admin, then fail */
1618 if ((user
.ut
.uid
!= 0) &&
1619 !user_has_privileges(user
.nt_user_token
,
1621 !token_contains_name_in_list(
1622 uidtoname(user
.ut
.uid
), NULL
,
1624 lp_printer_admin(snum
))) {
1625 close_printer_handle(p
, handle
);
1626 return WERR_ACCESS_DENIED
;
1629 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1633 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1636 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1637 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1639 /* We fall through to return WERR_OK */
1642 case SPLHND_PRINTER
:
1643 /* NT doesn't let us connect to a printer if the connecting user
1644 doesn't have print permission. */
1646 if (!get_printer_snum(p
, handle
, &snum
)) {
1647 close_printer_handle(p
, handle
);
1651 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1653 /* map an empty access mask to the minimum access mask */
1654 if (printer_default
->access_required
== 0x0)
1655 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1658 * If we are not serving the printer driver for this printer,
1659 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1660 * will keep NT clients happy --jerry
1663 if (lp_use_client_driver(snum
)
1664 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1666 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1669 /* check smb.conf parameters and the the sec_desc */
1671 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1672 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1673 return WERR_ACCESS_DENIED
;
1676 if (!user_ok_token(uidtoname(user
.ut
.uid
), user
.nt_user_token
,
1678 !print_access_check(&user
, snum
,
1679 printer_default
->access_required
)) {
1680 DEBUG(3, ("access DENIED for printer open\n"));
1681 close_printer_handle(p
, handle
);
1682 return WERR_ACCESS_DENIED
;
1685 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1686 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1687 close_printer_handle(p
, handle
);
1688 return WERR_ACCESS_DENIED
;
1691 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1692 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1694 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1696 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1697 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1702 /* sanity check to prevent programmer error */
1706 Printer
->access_granted
= printer_default
->access_required
;
1709 * If the client sent a devmode in the OpenPrinter() call, then
1710 * save it here in case we get a job submission on this handle
1713 if ( (Printer
->printer_type
!= SPLHND_SERVER
)
1714 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1716 convert_devicemode( Printer
->sharename
, q_u
->printer_default
.devmode_cont
.devmode
,
1717 &Printer
->nt_devmode
);
1720 #if 0 /* JERRY -- I'm doubtful this is really effective */
1721 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1722 optimization in Windows 2000 clients --jerry */
1724 if ( (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1725 && (RA_WIN2K
== get_remote_arch()) )
1727 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1728 sys_usleep( 500000 );
1735 /****************************************************************************
1736 ****************************************************************************/
1738 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1739 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1745 /* allocate memory if needed. Messy because
1746 convert_printer_info is used to update an existing
1747 printer or build a new one */
1749 if ( !printer
->info_2
) {
1750 printer
->info_2
= TALLOC_ZERO_P( printer
, NT_PRINTER_INFO_LEVEL_2
);
1751 if ( !printer
->info_2
) {
1752 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1757 ret
= uni_2_asc_printer_info_2(uni
->info_2
, printer
->info_2
);
1758 printer
->info_2
->setuptime
= time(NULL
);
1766 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1767 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1773 printer
->info_3
=NULL
;
1774 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1778 printer
->info_6
=NULL
;
1779 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1789 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1790 NT_DEVICEMODE
**pp_nt_devmode
)
1792 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1795 * Ensure nt_devmode is a valid pointer
1796 * as we will be overwriting it.
1799 if (nt_devmode
== NULL
) {
1800 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1801 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1805 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1806 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1808 nt_devmode
->specversion
=devmode
->specversion
;
1809 nt_devmode
->driverversion
=devmode
->driverversion
;
1810 nt_devmode
->size
=devmode
->size
;
1811 nt_devmode
->fields
=devmode
->fields
;
1812 nt_devmode
->orientation
=devmode
->orientation
;
1813 nt_devmode
->papersize
=devmode
->papersize
;
1814 nt_devmode
->paperlength
=devmode
->paperlength
;
1815 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1816 nt_devmode
->scale
=devmode
->scale
;
1817 nt_devmode
->copies
=devmode
->copies
;
1818 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1819 nt_devmode
->printquality
=devmode
->printquality
;
1820 nt_devmode
->color
=devmode
->color
;
1821 nt_devmode
->duplex
=devmode
->duplex
;
1822 nt_devmode
->yresolution
=devmode
->yresolution
;
1823 nt_devmode
->ttoption
=devmode
->ttoption
;
1824 nt_devmode
->collate
=devmode
->collate
;
1826 nt_devmode
->logpixels
=devmode
->logpixels
;
1827 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1828 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1829 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1830 nt_devmode
->displayflags
=devmode
->displayflags
;
1831 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1832 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1833 nt_devmode
->icmintent
=devmode
->icmintent
;
1834 nt_devmode
->mediatype
=devmode
->mediatype
;
1835 nt_devmode
->dithertype
=devmode
->dithertype
;
1836 nt_devmode
->reserved1
=devmode
->reserved1
;
1837 nt_devmode
->reserved2
=devmode
->reserved2
;
1838 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1839 nt_devmode
->panningheight
=devmode
->panningheight
;
1842 * Only change private and driverextra if the incoming devmode
1843 * has a new one. JRA.
1846 if ((devmode
->driverextra
!= 0) && (devmode
->dev_private
!= NULL
)) {
1847 SAFE_FREE(nt_devmode
->nt_dev_private
);
1848 nt_devmode
->driverextra
=devmode
->driverextra
;
1849 if((nt_devmode
->nt_dev_private
=SMB_MALLOC_ARRAY(uint8
, nt_devmode
->driverextra
)) == NULL
)
1851 memcpy(nt_devmode
->nt_dev_private
, devmode
->dev_private
, nt_devmode
->driverextra
);
1854 *pp_nt_devmode
= nt_devmode
;
1859 /********************************************************************
1860 * _spoolss_enddocprinter_internal.
1861 ********************************************************************/
1863 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1865 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1869 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1873 if (!get_printer_snum(p
, handle
, &snum
))
1876 Printer
->document_started
=False
;
1877 print_job_end(snum
, Printer
->jobid
,NORMAL_CLOSE
);
1878 /* error codes unhandled so far ... */
1883 /********************************************************************
1884 * api_spoolss_closeprinter
1885 ********************************************************************/
1887 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1889 POLICY_HND
*handle
= &q_u
->handle
;
1891 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1893 if (Printer
&& Printer
->document_started
)
1894 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1896 if (!close_printer_handle(p
, handle
))
1899 /* clear the returned printer handle. Observed behavior
1900 from Win2k server. Don't think this really matters.
1901 Previous code just copied the value of the closed
1904 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1909 /********************************************************************
1910 * api_spoolss_deleteprinter
1912 ********************************************************************/
1914 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1916 POLICY_HND
*handle
= &q_u
->handle
;
1917 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1920 if (Printer
&& Printer
->document_started
)
1921 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1923 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1925 result
= delete_printer_handle(p
, handle
);
1927 update_c_setprinter(False
);
1932 /*******************************************************************
1933 * static function to lookup the version id corresponding to an
1934 * long architecture string
1935 ******************************************************************/
1937 static int get_version_id (char * arch
)
1940 struct table_node archi_table
[]= {
1942 {"Windows 4.0", "WIN40", 0 },
1943 {"Windows NT x86", "W32X86", 2 },
1944 {"Windows NT R4000", "W32MIPS", 2 },
1945 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1946 {"Windows NT PowerPC", "W32PPC", 2 },
1947 {"Windows IA64", "IA64", 3 },
1948 {"Windows x64", "x64", 3 },
1952 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1954 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1955 return (archi_table
[i
].version
);
1961 /********************************************************************
1962 * _spoolss_deleteprinterdriver
1963 ********************************************************************/
1965 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1969 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1970 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1972 struct current_user user
;
1974 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1975 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1977 get_current_user(&user
, p
);
1979 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1980 and not a printer admin, then fail */
1982 if ( (user
.ut
.uid
!= 0)
1983 && !user_has_privileges(user
.nt_user_token
, &se_printop
)
1984 && !token_contains_name_in_list( uidtoname(user
.ut
.uid
),
1985 NULL
, user
.nt_user_token
, lp_printer_admin(-1)) )
1987 return WERR_ACCESS_DENIED
;
1990 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1991 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1993 /* check that we have a valid driver name first */
1995 if ((version
=get_version_id(arch
)) == -1)
1996 return WERR_INVALID_ENVIRONMENT
;
1999 ZERO_STRUCT(info_win2k
);
2001 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
2003 /* try for Win2k driver if "Windows NT x86" */
2005 if ( version
== 2 ) {
2007 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2008 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2012 /* otherwise it was a failure */
2014 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2020 if (printer_driver_in_use(info
.info_3
)) {
2021 status
= WERR_PRINTER_DRIVER_IN_USE
;
2027 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2029 /* if we get to here, we now have 2 driver info structures to remove */
2030 /* remove the Win2k driver first*/
2032 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
2033 free_a_printer_driver( info_win2k
, 3 );
2035 /* this should not have failed---if it did, report to client */
2036 if ( !W_ERROR_IS_OK(status_win2k
) )
2038 status
= status_win2k
;
2044 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
2046 /* if at least one of the deletes succeeded return OK */
2048 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2052 free_a_printer_driver( info
, 3 );
2057 /********************************************************************
2058 * spoolss_deleteprinterdriverex
2059 ********************************************************************/
2061 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
2065 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2066 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2068 uint32 flags
= q_u
->delete_flags
;
2070 struct current_user user
;
2072 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2073 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2075 get_current_user(&user
, p
);
2077 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2078 and not a printer admin, then fail */
2080 if ( (user
.ut
.uid
!= 0)
2081 && !user_has_privileges(user
.nt_user_token
, &se_printop
)
2082 && !token_contains_name_in_list( uidtoname(user
.ut
.uid
),
2083 NULL
, user
.nt_user_token
, lp_printer_admin(-1)) )
2085 return WERR_ACCESS_DENIED
;
2088 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2089 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2091 /* check that we have a valid driver name first */
2092 if ((version
=get_version_id(arch
)) == -1) {
2093 /* this is what NT returns */
2094 return WERR_INVALID_ENVIRONMENT
;
2097 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2098 version
= q_u
->version
;
2101 ZERO_STRUCT(info_win2k
);
2103 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2105 if ( !W_ERROR_IS_OK(status
) )
2108 * if the client asked for a specific version,
2109 * or this is something other than Windows NT x86,
2113 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2116 /* try for Win2k driver if "Windows NT x86" */
2119 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2120 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2125 if ( printer_driver_in_use(info
.info_3
) ) {
2126 status
= WERR_PRINTER_DRIVER_IN_USE
;
2131 * we have a couple of cases to consider.
2132 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2133 * then the delete should fail if **any** files overlap with
2135 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2136 * non-overlapping files
2137 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2138 * is set, the do not delete any files
2139 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2142 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2144 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2146 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2147 /* no idea of the correct error here */
2148 status
= WERR_ACCESS_DENIED
;
2153 /* also check for W32X86/3 if necessary; maybe we already have? */
2155 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2156 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2159 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2160 /* no idea of the correct error here */
2161 free_a_printer_driver( info_win2k
, 3 );
2162 status
= WERR_ACCESS_DENIED
;
2166 /* if we get to here, we now have 2 driver info structures to remove */
2167 /* remove the Win2k driver first*/
2169 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2170 free_a_printer_driver( info_win2k
, 3 );
2172 /* this should not have failed---if it did, report to client */
2174 if ( !W_ERROR_IS_OK(status_win2k
) )
2179 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2181 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2184 free_a_printer_driver( info
, 3 );
2190 /****************************************************************************
2191 Internal routine for retreiving printerdata
2192 ***************************************************************************/
2194 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2195 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2196 uint32
*needed
, uint32 in_size
)
2198 REGISTRY_VALUE
*val
;
2202 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2203 return WERR_BADFILE
;
2205 *type
= regval_type( val
);
2207 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2209 size
= regval_size( val
);
2211 /* copy the min(in_size, len) */
2214 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2216 /* special case for 0 length values */
2218 if ( (*data
= (uint8
*)TALLOC_MEMDUP(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2222 if ( (*data
= (uint8
*)TALLOC_ZERO(ctx
, in_size
)) == NULL
)
2231 DEBUG(5,("get_printer_dataex: copy done\n"));
2236 /****************************************************************************
2237 Internal routine for removing printerdata
2238 ***************************************************************************/
2240 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2242 return delete_printer_data( printer
->info_2
, key
, value
);
2245 /****************************************************************************
2246 Internal routine for storing printerdata
2247 ***************************************************************************/
2249 WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2250 uint32 type
, uint8
*data
, int real_len
)
2252 /* the registry objects enforce uniqueness based on value name */
2254 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2257 /********************************************************************
2258 GetPrinterData on a printer server Handle.
2259 ********************************************************************/
2261 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2265 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2267 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2269 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2271 SIVAL(*data
, 0, 0x00);
2276 if (!StrCaseCmp(value
, "BeepEnabled")) {
2278 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2280 SIVAL(*data
, 0, 0x00);
2285 if (!StrCaseCmp(value
, "EventLog")) {
2287 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2289 /* formally was 0x1b */
2290 SIVAL(*data
, 0, 0x0);
2295 if (!StrCaseCmp(value
, "NetPopup")) {
2297 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2299 SIVAL(*data
, 0, 0x00);
2304 if (!StrCaseCmp(value
, "MajorVersion")) {
2306 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2309 /* Windows NT 4.0 seems to not allow uploading of drivers
2310 to a server that reports 0x3 as the MajorVersion.
2311 need to investigate more how Win2k gets around this .
2314 if ( RA_WINNT
== get_remote_arch() )
2323 if (!StrCaseCmp(value
, "MinorVersion")) {
2325 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2333 * uint32 size = 0x114
2335 * uint32 minor = [0|1]
2336 * uint32 build = [2195|2600]
2337 * extra unicode string = e.g. "Service Pack 3"
2339 if (!StrCaseCmp(value
, "OSVersion")) {
2343 if ( !(*data
= TALLOC_ZERO_ARRAY(ctx
, uint8
, (*needed
> in_size
) ? *needed
:in_size
)) )
2346 SIVAL(*data
, 0, *needed
); /* size */
2347 SIVAL(*data
, 4, 5); /* Windows 2000 == 5.0 */
2349 SIVAL(*data
, 12, 2195); /* build */
2351 /* leave extra string empty */
2357 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2358 const char *string
="C:\\PRINTERS";
2360 *needed
= 2*(strlen(string
)+1);
2361 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2363 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2365 /* it's done by hand ready to go on the wire */
2366 for (i
=0; i
<strlen(string
); i
++) {
2367 (*data
)[2*i
]=string
[i
];
2368 (*data
)[2*i
+1]='\0';
2373 if (!StrCaseCmp(value
, "Architecture")) {
2374 const char *string
="Windows NT x86";
2376 *needed
= 2*(strlen(string
)+1);
2377 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2379 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2380 for (i
=0; i
<strlen(string
); i
++) {
2381 (*data
)[2*i
]=string
[i
];
2382 (*data
)[2*i
+1]='\0';
2387 if (!StrCaseCmp(value
, "DsPresent")) {
2389 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2392 /* only show the publish check box if we are a
2393 memeber of a AD domain */
2395 if ( lp_security() == SEC_ADS
)
2396 SIVAL(*data
, 0, 0x01);
2398 SIVAL(*data
, 0, 0x00);
2404 if (!StrCaseCmp(value
, "DNSMachineName")) {
2407 if (!get_mydnsfullname(hostname
))
2408 return WERR_BADFILE
;
2410 *needed
= 2*(strlen(hostname
)+1);
2411 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2413 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2414 for (i
=0; i
<strlen(hostname
); i
++) {
2415 (*data
)[2*i
]=hostname
[i
];
2416 (*data
)[2*i
+1]='\0';
2422 return WERR_BADFILE
;
2425 /********************************************************************
2426 * spoolss_getprinterdata
2427 ********************************************************************/
2429 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2431 POLICY_HND
*handle
= &q_u
->handle
;
2432 UNISTR2
*valuename
= &q_u
->valuename
;
2433 uint32 in_size
= q_u
->size
;
2434 uint32
*type
= &r_u
->type
;
2435 uint32
*out_size
= &r_u
->size
;
2436 uint8
**data
= &r_u
->data
;
2437 uint32
*needed
= &r_u
->needed
;
2440 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2441 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2445 * Reminder: when it's a string, the length is in BYTES
2446 * even if UNICODE is negociated.
2451 *out_size
= in_size
;
2453 /* in case of problem, return some default values */
2458 DEBUG(4,("_spoolss_getprinterdata\n"));
2461 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2462 status
= WERR_BADFID
;
2466 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2468 if ( Printer
->printer_type
== SPLHND_SERVER
)
2469 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2472 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2473 status
= WERR_BADFID
;
2477 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2478 if ( !W_ERROR_IS_OK(status
) )
2481 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2483 if ( strequal(value
, "ChangeId") ) {
2485 *needed
= sizeof(uint32
);
2486 if ( (*data
= (uint8
*)TALLOC(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2487 status
= WERR_NOMEM
;
2490 SIVAL( *data
, 0, printer
->info_2
->changeid
);
2494 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2497 if (*needed
> *out_size
)
2498 status
= WERR_MORE_DATA
;
2501 if ( !W_ERROR_IS_OK(status
) )
2503 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2505 /* reply this param doesn't exist */
2508 if((*data
=(uint8
*)TALLOC_ZERO_ARRAY(p
->mem_ctx
, uint8
, *out_size
)) == NULL
) {
2510 free_a_printer( &printer
, 2 );
2518 /* cleanup & exit */
2521 free_a_printer( &printer
, 2 );
2526 /*********************************************************
2527 Connect to the client machine.
2528 **********************************************************/
2530 static BOOL
spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2531 struct in_addr
*client_ip
, const char *remote_machine
)
2534 struct cli_state
*the_cli
;
2535 struct in_addr rm_addr
;
2537 if ( is_zero_ip(*client_ip
) ) {
2538 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20) ) {
2539 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2543 if ( ismyip( rm_addr
)) {
2544 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2548 rm_addr
.s_addr
= client_ip
->s_addr
;
2549 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2550 inet_ntoa(*client_ip
) ));
2553 /* setup the connection */
2555 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2556 &rm_addr
, 0, "IPC$", "IPC",
2560 0, lp_client_signing(), NULL
);
2562 if ( !NT_STATUS_IS_OK( ret
) ) {
2563 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2568 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2569 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2570 cli_shutdown(the_cli
);
2575 * Ok - we have an anonymous connection to the IPC$ share.
2576 * Now start the NT Domain stuff :-).
2579 if ( !(*pp_pipe
= cli_rpc_pipe_open_noauth(the_cli
, PI_SPOOLSS
, &ret
)) ) {
2580 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2581 remote_machine
, nt_errstr(ret
)));
2582 cli_shutdown(the_cli
);
2586 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2588 (*pp_pipe
)->cli
= the_cli
;
2593 /***************************************************************************
2594 Connect to the client.
2595 ****************************************************************************/
2597 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2598 uint32 localprinter
, uint32 type
,
2599 POLICY_HND
*handle
, struct in_addr
*client_ip
)
2604 * If it's the first connection, contact the client
2605 * and connect to the IPC$ share anonymously
2607 if (smb_connections
==0) {
2608 fstring unix_printer
;
2610 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2612 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ip
, unix_printer
))
2615 message_register(MSG_PRINTER_NOTIFY2
,
2616 receive_notify2_message_list
, NULL
);
2617 /* Tell the connections db we're now interested in printer
2618 * notify messages. */
2619 register_message_flags( True
, FLAG_MSG_PRINT_NOTIFY
);
2623 * Tell the specific printing tdb we want messages for this printer
2624 * by registering our PID.
2627 if (!print_notify_register_pid(snum
))
2628 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2632 result
= rpccli_spoolss_reply_open_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, printer
, localprinter
,
2635 if (!W_ERROR_IS_OK(result
))
2636 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2637 dos_errstr(result
)));
2639 return (W_ERROR_IS_OK(result
));
2642 /********************************************************************
2644 * ReplyFindFirstPrinterChangeNotifyEx
2646 * before replying OK: status=0 a rpc call is made to the workstation
2647 * asking ReplyOpenPrinter
2649 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2650 * called from api_spoolss_rffpcnex
2651 ********************************************************************/
2653 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2655 POLICY_HND
*handle
= &q_u
->handle
;
2656 uint32 flags
= q_u
->flags
;
2657 uint32 options
= q_u
->options
;
2658 UNISTR2
*localmachine
= &q_u
->localmachine
;
2659 uint32 printerlocal
= q_u
->printerlocal
;
2661 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2662 struct in_addr client_ip
;
2664 /* store the notify value in the printer struct */
2666 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2669 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2673 Printer
->notify
.flags
=flags
;
2674 Printer
->notify
.options
=options
;
2675 Printer
->notify
.printerlocal
=printerlocal
;
2677 if (Printer
->notify
.option
)
2678 free_spool_notify_option(&Printer
->notify
.option
);
2680 Printer
->notify
.option
=dup_spool_notify_option(option
);
2682 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2683 sizeof(Printer
->notify
.localmachine
)-1);
2685 /* Connect to the client machine and send a ReplyOpenPrinter */
2687 if ( Printer
->printer_type
== SPLHND_SERVER
)
2689 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2690 !get_printer_snum(p
, handle
, &snum
) )
2693 client_ip
.s_addr
= inet_addr(p
->conn
->client_address
);
2695 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2696 Printer
->notify
.printerlocal
, 1,
2697 &Printer
->notify
.client_hnd
, &client_ip
))
2698 return WERR_SERVER_UNAVAILABLE
;
2700 Printer
->notify
.client_connected
=True
;
2705 /*******************************************************************
2706 * fill a notify_info_data with the servername
2707 ********************************************************************/
2709 void spoolss_notify_server_name(int snum
,
2710 SPOOL_NOTIFY_INFO_DATA
*data
,
2711 print_queue_struct
*queue
,
2712 NT_PRINTER_INFO_LEVEL
*printer
,
2713 TALLOC_CTX
*mem_ctx
)
2718 len
= rpcstr_push(temp
, printer
->info_2
->servername
, sizeof(temp
)-2, STR_TERMINATE
);
2720 data
->notify_data
.data
.length
= len
;
2722 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2723 if (!data
->notify_data
.data
.string
) {
2724 data
->notify_data
.data
.length
= 0;
2728 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2730 data
->notify_data
.data
.string
= NULL
;
2734 /*******************************************************************
2735 * fill a notify_info_data with the printername (not including the servername).
2736 ********************************************************************/
2738 void spoolss_notify_printer_name(int snum
,
2739 SPOOL_NOTIFY_INFO_DATA
*data
,
2740 print_queue_struct
*queue
,
2741 NT_PRINTER_INFO_LEVEL
*printer
,
2742 TALLOC_CTX
*mem_ctx
)
2747 /* the notify name should not contain the \\server\ part */
2748 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2751 p
= printer
->info_2
->printername
;
2756 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2758 data
->notify_data
.data
.length
= len
;
2760 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2761 if (!data
->notify_data
.data
.string
) {
2762 data
->notify_data
.data
.length
= 0;
2765 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2767 data
->notify_data
.data
.string
= NULL
;
2771 /*******************************************************************
2772 * fill a notify_info_data with the servicename
2773 ********************************************************************/
2775 void spoolss_notify_share_name(int snum
,
2776 SPOOL_NOTIFY_INFO_DATA
*data
,
2777 print_queue_struct
*queue
,
2778 NT_PRINTER_INFO_LEVEL
*printer
,
2779 TALLOC_CTX
*mem_ctx
)
2784 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2786 data
->notify_data
.data
.length
= len
;
2788 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2789 if (!data
->notify_data
.data
.string
) {
2790 data
->notify_data
.data
.length
= 0;
2793 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2795 data
->notify_data
.data
.string
= NULL
;
2800 /*******************************************************************
2801 * fill a notify_info_data with the port name
2802 ********************************************************************/
2804 void spoolss_notify_port_name(int snum
,
2805 SPOOL_NOTIFY_INFO_DATA
*data
,
2806 print_queue_struct
*queue
,
2807 NT_PRINTER_INFO_LEVEL
*printer
,
2808 TALLOC_CTX
*mem_ctx
)
2813 /* even if it's strange, that's consistant in all the code */
2815 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2817 data
->notify_data
.data
.length
= len
;
2819 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2821 if (!data
->notify_data
.data
.string
) {
2822 data
->notify_data
.data
.length
= 0;
2826 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2828 data
->notify_data
.data
.string
= NULL
;
2832 /*******************************************************************
2833 * fill a notify_info_data with the printername
2834 * but it doesn't exist, have to see what to do
2835 ********************************************************************/
2837 void spoolss_notify_driver_name(int snum
,
2838 SPOOL_NOTIFY_INFO_DATA
*data
,
2839 print_queue_struct
*queue
,
2840 NT_PRINTER_INFO_LEVEL
*printer
,
2841 TALLOC_CTX
*mem_ctx
)
2846 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2848 data
->notify_data
.data
.length
= len
;
2850 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2852 if (!data
->notify_data
.data
.string
) {
2853 data
->notify_data
.data
.length
= 0;
2857 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2859 data
->notify_data
.data
.string
= NULL
;
2863 /*******************************************************************
2864 * fill a notify_info_data with the comment
2865 ********************************************************************/
2867 void spoolss_notify_comment(int snum
,
2868 SPOOL_NOTIFY_INFO_DATA
*data
,
2869 print_queue_struct
*queue
,
2870 NT_PRINTER_INFO_LEVEL
*printer
,
2871 TALLOC_CTX
*mem_ctx
)
2876 if (*printer
->info_2
->comment
== '\0')
2877 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2879 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2881 data
->notify_data
.data
.length
= len
;
2883 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2885 if (!data
->notify_data
.data
.string
) {
2886 data
->notify_data
.data
.length
= 0;
2890 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2892 data
->notify_data
.data
.string
= NULL
;
2896 /*******************************************************************
2897 * fill a notify_info_data with the comment
2898 * location = "Room 1, floor 2, building 3"
2899 ********************************************************************/
2901 void spoolss_notify_location(int snum
,
2902 SPOOL_NOTIFY_INFO_DATA
*data
,
2903 print_queue_struct
*queue
,
2904 NT_PRINTER_INFO_LEVEL
*printer
,
2905 TALLOC_CTX
*mem_ctx
)
2910 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2912 data
->notify_data
.data
.length
= len
;
2914 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2916 if (!data
->notify_data
.data
.string
) {
2917 data
->notify_data
.data
.length
= 0;
2921 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2923 data
->notify_data
.data
.string
= NULL
;
2927 /*******************************************************************
2928 * fill a notify_info_data with the device mode
2929 * jfm:xxxx don't to it for know but that's a real problem !!!
2930 ********************************************************************/
2932 static void spoolss_notify_devmode(int snum
,
2933 SPOOL_NOTIFY_INFO_DATA
*data
,
2934 print_queue_struct
*queue
,
2935 NT_PRINTER_INFO_LEVEL
*printer
,
2936 TALLOC_CTX
*mem_ctx
)
2938 /* for a dummy implementation we have to zero the fields */
2939 data
->notify_data
.data
.length
= 0;
2940 data
->notify_data
.data
.string
= NULL
;
2943 /*******************************************************************
2944 * fill a notify_info_data with the separator file name
2945 ********************************************************************/
2947 void spoolss_notify_sepfile(int snum
,
2948 SPOOL_NOTIFY_INFO_DATA
*data
,
2949 print_queue_struct
*queue
,
2950 NT_PRINTER_INFO_LEVEL
*printer
,
2951 TALLOC_CTX
*mem_ctx
)
2956 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2958 data
->notify_data
.data
.length
= len
;
2960 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2962 if (!data
->notify_data
.data
.string
) {
2963 data
->notify_data
.data
.length
= 0;
2967 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2969 data
->notify_data
.data
.string
= NULL
;
2973 /*******************************************************************
2974 * fill a notify_info_data with the print processor
2975 * jfm:xxxx return always winprint to indicate we don't do anything to it
2976 ********************************************************************/
2978 void spoolss_notify_print_processor(int snum
,
2979 SPOOL_NOTIFY_INFO_DATA
*data
,
2980 print_queue_struct
*queue
,
2981 NT_PRINTER_INFO_LEVEL
*printer
,
2982 TALLOC_CTX
*mem_ctx
)
2987 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
2989 data
->notify_data
.data
.length
= len
;
2991 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2993 if (!data
->notify_data
.data
.string
) {
2994 data
->notify_data
.data
.length
= 0;
2998 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3000 data
->notify_data
.data
.string
= NULL
;
3004 /*******************************************************************
3005 * fill a notify_info_data with the print processor options
3006 * jfm:xxxx send an empty string
3007 ********************************************************************/
3009 void spoolss_notify_parameters(int snum
,
3010 SPOOL_NOTIFY_INFO_DATA
*data
,
3011 print_queue_struct
*queue
,
3012 NT_PRINTER_INFO_LEVEL
*printer
,
3013 TALLOC_CTX
*mem_ctx
)
3018 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
3020 data
->notify_data
.data
.length
= len
;
3022 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3024 if (!data
->notify_data
.data
.string
) {
3025 data
->notify_data
.data
.length
= 0;
3029 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3031 data
->notify_data
.data
.string
= NULL
;
3035 /*******************************************************************
3036 * fill a notify_info_data with the data type
3037 * jfm:xxxx always send RAW as data type
3038 ********************************************************************/
3040 void spoolss_notify_datatype(int snum
,
3041 SPOOL_NOTIFY_INFO_DATA
*data
,
3042 print_queue_struct
*queue
,
3043 NT_PRINTER_INFO_LEVEL
*printer
,
3044 TALLOC_CTX
*mem_ctx
)
3049 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
3051 data
->notify_data
.data
.length
= len
;
3053 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3055 if (!data
->notify_data
.data
.string
) {
3056 data
->notify_data
.data
.length
= 0;
3060 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3062 data
->notify_data
.data
.string
= NULL
;
3066 /*******************************************************************
3067 * fill a notify_info_data with the security descriptor
3068 * jfm:xxxx send an null pointer to say no security desc
3069 * have to implement security before !
3070 ********************************************************************/
3072 static void spoolss_notify_security_desc(int snum
,
3073 SPOOL_NOTIFY_INFO_DATA
*data
,
3074 print_queue_struct
*queue
,
3075 NT_PRINTER_INFO_LEVEL
*printer
,
3076 TALLOC_CTX
*mem_ctx
)
3078 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
3079 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
3082 /*******************************************************************
3083 * fill a notify_info_data with the attributes
3084 * jfm:xxxx a samba printer is always shared
3085 ********************************************************************/
3087 void spoolss_notify_attributes(int snum
,
3088 SPOOL_NOTIFY_INFO_DATA
*data
,
3089 print_queue_struct
*queue
,
3090 NT_PRINTER_INFO_LEVEL
*printer
,
3091 TALLOC_CTX
*mem_ctx
)
3093 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
3094 data
->notify_data
.value
[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the priority
3099 ********************************************************************/
3101 static void spoolss_notify_priority(int snum
,
3102 SPOOL_NOTIFY_INFO_DATA
*data
,
3103 print_queue_struct
*queue
,
3104 NT_PRINTER_INFO_LEVEL
*printer
,
3105 TALLOC_CTX
*mem_ctx
)
3107 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
3108 data
->notify_data
.value
[1] = 0;
3111 /*******************************************************************
3112 * fill a notify_info_data with the default priority
3113 ********************************************************************/
3115 static void spoolss_notify_default_priority(int snum
,
3116 SPOOL_NOTIFY_INFO_DATA
*data
,
3117 print_queue_struct
*queue
,
3118 NT_PRINTER_INFO_LEVEL
*printer
,
3119 TALLOC_CTX
*mem_ctx
)
3121 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
3122 data
->notify_data
.value
[1] = 0;
3125 /*******************************************************************
3126 * fill a notify_info_data with the start time
3127 ********************************************************************/
3129 static void spoolss_notify_start_time(int snum
,
3130 SPOOL_NOTIFY_INFO_DATA
*data
,
3131 print_queue_struct
*queue
,
3132 NT_PRINTER_INFO_LEVEL
*printer
,
3133 TALLOC_CTX
*mem_ctx
)
3135 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
3136 data
->notify_data
.value
[1] = 0;
3139 /*******************************************************************
3140 * fill a notify_info_data with the until time
3141 ********************************************************************/
3143 static void spoolss_notify_until_time(int snum
,
3144 SPOOL_NOTIFY_INFO_DATA
*data
,
3145 print_queue_struct
*queue
,
3146 NT_PRINTER_INFO_LEVEL
*printer
,
3147 TALLOC_CTX
*mem_ctx
)
3149 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3150 data
->notify_data
.value
[1] = 0;
3153 /*******************************************************************
3154 * fill a notify_info_data with the status
3155 ********************************************************************/
3157 static void spoolss_notify_status(int snum
,
3158 SPOOL_NOTIFY_INFO_DATA
*data
,
3159 print_queue_struct
*queue
,
3160 NT_PRINTER_INFO_LEVEL
*printer
,
3161 TALLOC_CTX
*mem_ctx
)
3163 print_status_struct status
;
3165 print_queue_length(snum
, &status
);
3166 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3167 data
->notify_data
.value
[1] = 0;
3170 /*******************************************************************
3171 * fill a notify_info_data with the number of jobs queued
3172 ********************************************************************/
3174 void spoolss_notify_cjobs(int snum
,
3175 SPOOL_NOTIFY_INFO_DATA
*data
,
3176 print_queue_struct
*queue
,
3177 NT_PRINTER_INFO_LEVEL
*printer
,
3178 TALLOC_CTX
*mem_ctx
)
3180 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3181 data
->notify_data
.value
[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with the average ppm
3186 ********************************************************************/
3188 static void spoolss_notify_average_ppm(int snum
,
3189 SPOOL_NOTIFY_INFO_DATA
*data
,
3190 print_queue_struct
*queue
,
3191 NT_PRINTER_INFO_LEVEL
*printer
,
3192 TALLOC_CTX
*mem_ctx
)
3194 /* always respond 8 pages per minutes */
3195 /* a little hard ! */
3196 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3197 data
->notify_data
.value
[1] = 0;
3200 /*******************************************************************
3201 * fill a notify_info_data with username
3202 ********************************************************************/
3204 static void spoolss_notify_username(int snum
,
3205 SPOOL_NOTIFY_INFO_DATA
*data
,
3206 print_queue_struct
*queue
,
3207 NT_PRINTER_INFO_LEVEL
*printer
,
3208 TALLOC_CTX
*mem_ctx
)
3213 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3215 data
->notify_data
.data
.length
= len
;
3217 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3219 if (!data
->notify_data
.data
.string
) {
3220 data
->notify_data
.data
.length
= 0;
3224 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3226 data
->notify_data
.data
.string
= NULL
;
3230 /*******************************************************************
3231 * fill a notify_info_data with job status
3232 ********************************************************************/
3234 static void spoolss_notify_job_status(int snum
,
3235 SPOOL_NOTIFY_INFO_DATA
*data
,
3236 print_queue_struct
*queue
,
3237 NT_PRINTER_INFO_LEVEL
*printer
,
3238 TALLOC_CTX
*mem_ctx
)
3240 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3241 data
->notify_data
.value
[1] = 0;
3244 /*******************************************************************
3245 * fill a notify_info_data with job name
3246 ********************************************************************/
3248 static void spoolss_notify_job_name(int snum
,
3249 SPOOL_NOTIFY_INFO_DATA
*data
,
3250 print_queue_struct
*queue
,
3251 NT_PRINTER_INFO_LEVEL
*printer
,
3252 TALLOC_CTX
*mem_ctx
)
3257 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3259 data
->notify_data
.data
.length
= len
;
3261 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3263 if (!data
->notify_data
.data
.string
) {
3264 data
->notify_data
.data
.length
= 0;
3268 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3270 data
->notify_data
.data
.string
= NULL
;
3274 /*******************************************************************
3275 * fill a notify_info_data with job status
3276 ********************************************************************/
3278 static void spoolss_notify_job_status_string(int snum
,
3279 SPOOL_NOTIFY_INFO_DATA
*data
,
3280 print_queue_struct
*queue
,
3281 NT_PRINTER_INFO_LEVEL
*printer
,
3282 TALLOC_CTX
*mem_ctx
)
3285 * Now we're returning job status codes we just return a "" here. JRA.
3292 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3295 switch (queue
->status
) {
3300 p
= ""; /* NT provides the paused string */
3309 #endif /* NO LONGER NEEDED. */
3311 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3313 data
->notify_data
.data
.length
= len
;
3315 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3317 if (!data
->notify_data
.data
.string
) {
3318 data
->notify_data
.data
.length
= 0;
3322 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3324 data
->notify_data
.data
.string
= NULL
;
3328 /*******************************************************************
3329 * fill a notify_info_data with job time
3330 ********************************************************************/
3332 static void spoolss_notify_job_time(int snum
,
3333 SPOOL_NOTIFY_INFO_DATA
*data
,
3334 print_queue_struct
*queue
,
3335 NT_PRINTER_INFO_LEVEL
*printer
,
3336 TALLOC_CTX
*mem_ctx
)
3338 data
->notify_data
.value
[0]=0x0;
3339 data
->notify_data
.value
[1]=0;
3342 /*******************************************************************
3343 * fill a notify_info_data with job size
3344 ********************************************************************/
3346 static void spoolss_notify_job_size(int snum
,
3347 SPOOL_NOTIFY_INFO_DATA
*data
,
3348 print_queue_struct
*queue
,
3349 NT_PRINTER_INFO_LEVEL
*printer
,
3350 TALLOC_CTX
*mem_ctx
)
3352 data
->notify_data
.value
[0]=queue
->size
;
3353 data
->notify_data
.value
[1]=0;
3356 /*******************************************************************
3357 * fill a notify_info_data with page info
3358 ********************************************************************/
3359 static void spoolss_notify_total_pages(int snum
,
3360 SPOOL_NOTIFY_INFO_DATA
*data
,
3361 print_queue_struct
*queue
,
3362 NT_PRINTER_INFO_LEVEL
*printer
,
3363 TALLOC_CTX
*mem_ctx
)
3365 data
->notify_data
.value
[0]=queue
->page_count
;
3366 data
->notify_data
.value
[1]=0;
3369 /*******************************************************************
3370 * fill a notify_info_data with pages printed info.
3371 ********************************************************************/
3372 static void spoolss_notify_pages_printed(int snum
,
3373 SPOOL_NOTIFY_INFO_DATA
*data
,
3374 print_queue_struct
*queue
,
3375 NT_PRINTER_INFO_LEVEL
*printer
,
3376 TALLOC_CTX
*mem_ctx
)
3378 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3379 data
->notify_data
.value
[1]=0;
3382 /*******************************************************************
3383 Fill a notify_info_data with job position.
3384 ********************************************************************/
3386 static void spoolss_notify_job_position(int snum
,
3387 SPOOL_NOTIFY_INFO_DATA
*data
,
3388 print_queue_struct
*queue
,
3389 NT_PRINTER_INFO_LEVEL
*printer
,
3390 TALLOC_CTX
*mem_ctx
)
3392 data
->notify_data
.value
[0]=queue
->job
;
3393 data
->notify_data
.value
[1]=0;
3396 /*******************************************************************
3397 Fill a notify_info_data with submitted time.
3398 ********************************************************************/
3400 static void spoolss_notify_submitted_time(int snum
,
3401 SPOOL_NOTIFY_INFO_DATA
*data
,
3402 print_queue_struct
*queue
,
3403 NT_PRINTER_INFO_LEVEL
*printer
,
3404 TALLOC_CTX
*mem_ctx
)
3411 t
=gmtime(&queue
->time
);
3413 len
= sizeof(SYSTEMTIME
);
3415 data
->notify_data
.data
.length
= len
;
3416 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3418 if (!data
->notify_data
.data
.string
) {
3419 data
->notify_data
.data
.length
= 0;
3423 make_systemtime(&st
, t
);
3426 * Systemtime must be linearized as a set of UINT16's.
3427 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3430 p
= (char *)data
->notify_data
.data
.string
;
3431 SSVAL(p
, 0, st
.year
);
3432 SSVAL(p
, 2, st
.month
);
3433 SSVAL(p
, 4, st
.dayofweek
);
3434 SSVAL(p
, 6, st
.day
);
3435 SSVAL(p
, 8, st
.hour
);
3436 SSVAL(p
, 10, st
.minute
);
3437 SSVAL(p
, 12, st
.second
);
3438 SSVAL(p
, 14, st
.milliseconds
);
3441 struct s_notify_info_data_table
3447 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3448 print_queue_struct
*queue
,
3449 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3452 /* A table describing the various print notification constants and
3453 whether the notification data is a pointer to a variable sized
3454 buffer, a one value uint32 or a two value uint32. */
3456 static const struct s_notify_info_data_table notify_info_data_table
[] =
3458 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3459 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3460 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3461 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3462 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3463 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3464 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3465 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3466 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3467 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3468 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3469 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3470 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3471 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3472 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3473 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3474 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3475 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3476 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3477 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3478 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3479 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3480 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3481 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3482 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3483 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3484 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3485 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3486 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3487 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3488 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3489 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3490 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3491 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3492 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3493 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3494 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3495 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3496 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3497 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3498 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3499 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3500 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3501 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3502 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3503 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3504 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3505 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3506 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3507 { PRINT_TABLE_END
, 0x0, NULL
, 0x0, NULL
},
3510 /*******************************************************************
3511 Return the size of info_data structure.
3512 ********************************************************************/
3514 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3518 for (i
= 0; i
< (sizeof(notify_info_data_table
)/sizeof(struct s_notify_info_data_table
)); i
++) {
3519 if ( (notify_info_data_table
[i
].type
== type
)
3520 && (notify_info_data_table
[i
].field
== field
) ) {
3521 switch(notify_info_data_table
[i
].size
) {
3522 case NOTIFY_ONE_VALUE
:
3523 case NOTIFY_TWO_VALUE
:
3528 /* The only pointer notify data I have seen on
3529 the wire is the submitted time and this has
3530 the notify size set to 4. -tpot */
3532 case NOTIFY_POINTER
:
3535 case NOTIFY_SECDESC
:
3541 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3546 /*******************************************************************
3547 Return the type of notify_info_data.
3548 ********************************************************************/
3550 static uint32
type_of_notify_info_data(uint16 type
, uint16 field
)
3554 for (i
= 0; i
< (sizeof(notify_info_data_table
)/sizeof(struct s_notify_info_data_table
)); i
++) {
3555 if (notify_info_data_table
[i
].type
== type
&&
3556 notify_info_data_table
[i
].field
== field
)
3557 return notify_info_data_table
[i
].size
;
3563 /****************************************************************************
3564 ****************************************************************************/
3566 static BOOL
search_notify(uint16 type
, uint16 field
, int *value
)
3570 for (i
= 0; notify_info_data_table
[i
].type
!= PRINT_TABLE_END
; i
++) {
3571 if (notify_info_data_table
[i
].type
== type
&&
3572 notify_info_data_table
[i
].field
== field
&&
3573 notify_info_data_table
[i
].fn
!= NULL
) {
3582 /****************************************************************************
3583 ****************************************************************************/
3585 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3587 info_data
->type
= type
;
3588 info_data
->field
= field
;
3589 info_data
->reserved
= 0;
3591 info_data
->size
= size_of_notify_info_data(type
, field
);
3592 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3597 /*******************************************************************
3599 * fill a notify_info struct with info asked
3601 ********************************************************************/
3603 static BOOL
construct_notify_printer_info(Printer_entry
*print_hnd
, SPOOL_NOTIFY_INFO
*info
, int
3604 snum
, SPOOL_NOTIFY_OPTION_TYPE
3605 *option_type
, uint32 id
,
3606 TALLOC_CTX
*mem_ctx
)
3612 SPOOL_NOTIFY_INFO_DATA
*current_data
;
3613 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3614 print_queue_struct
*queue
=NULL
;
3616 type
=option_type
->type
;
3618 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3619 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3620 option_type
->count
, lp_servicename(snum
)));
3622 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3625 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3626 field
= option_type
->fields
[field_num
];
3628 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3630 if (!search_notify(type
, field
, &j
) )
3633 if((info
->data
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3634 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3635 free_a_printer(&printer
, 2);
3639 current_data
= &info
->data
[info
->count
];
3641 construct_info_data(current_data
, type
, field
, id
);
3643 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3644 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3646 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3652 free_a_printer(&printer
, 2);
3656 /*******************************************************************
3658 * fill a notify_info struct with info asked
3660 ********************************************************************/
3662 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3663 SPOOL_NOTIFY_INFO
*info
,
3664 NT_PRINTER_INFO_LEVEL
*printer
,
3665 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3666 *option_type
, uint32 id
,
3667 TALLOC_CTX
*mem_ctx
)
3673 SPOOL_NOTIFY_INFO_DATA
*current_data
;
3675 DEBUG(4,("construct_notify_jobs_info\n"));
3677 type
= option_type
->type
;
3679 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3680 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3681 option_type
->count
));
3683 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3684 field
= option_type
->fields
[field_num
];
3686 if (!search_notify(type
, field
, &j
) )
3689 if((info
->data
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3690 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3694 current_data
=&(info
->data
[info
->count
]);
3696 construct_info_data(current_data
, type
, field
, id
);
3697 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3706 * JFM: The enumeration is not that simple, it's even non obvious.
3708 * let's take an example: I want to monitor the PRINTER SERVER for
3709 * the printer's name and the number of jobs currently queued.
3710 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3711 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3713 * I have 3 printers on the back of my server.
3715 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3718 * 1 printer 1 name 1
3719 * 2 printer 1 cjob 1
3720 * 3 printer 2 name 2
3721 * 4 printer 2 cjob 2
3722 * 5 printer 3 name 3
3723 * 6 printer 3 name 3
3725 * that's the print server case, the printer case is even worse.
3728 /*******************************************************************
3730 * enumerate all printers on the printserver
3731 * fill a notify_info struct with info asked
3733 ********************************************************************/
3735 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3736 SPOOL_NOTIFY_INFO
*info
,
3737 TALLOC_CTX
*mem_ctx
)
3740 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3741 int n_services
=lp_numservices();
3743 SPOOL_NOTIFY_OPTION
*option
;
3744 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3746 DEBUG(4,("printserver_notify_info\n"));
3751 option
=Printer
->notify
.option
;
3756 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3757 sending a ffpcn() request first */
3762 for (i
=0; i
<option
->count
; i
++) {
3763 option_type
=&(option
->ctr
.type
[i
]);
3765 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3768 for (snum
=0; snum
<n_services
; snum
++)
3770 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3771 construct_notify_printer_info ( Printer
, info
, snum
, option_type
, snum
, mem_ctx
);
3777 * Debugging information, don't delete.
3780 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3781 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3782 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3784 for (i
=0; i
<info
->count
; i
++) {
3785 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3786 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3787 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3794 /*******************************************************************
3796 * fill a notify_info struct with info asked
3798 ********************************************************************/
3800 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3801 TALLOC_CTX
*mem_ctx
)
3804 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3807 SPOOL_NOTIFY_OPTION
*option
;
3808 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3810 print_queue_struct
*queue
=NULL
;
3811 print_status_struct status
;
3813 DEBUG(4,("printer_notify_info\n"));
3818 option
=Printer
->notify
.option
;
3824 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3825 sending a ffpcn() request first */
3830 get_printer_snum(p
, hnd
, &snum
);
3832 for (i
=0; i
<option
->count
; i
++) {
3833 option_type
=&option
->ctr
.type
[i
];
3835 switch ( option_type
->type
) {
3836 case PRINTER_NOTIFY_TYPE
:
3837 if(construct_notify_printer_info(Printer
, info
, snum
,
3843 case JOB_NOTIFY_TYPE
: {
3844 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3846 count
= print_queue_status(snum
, &queue
, &status
);
3848 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3851 for (j
=0; j
<count
; j
++) {
3852 construct_notify_jobs_info(&queue
[j
], info
,
3859 free_a_printer(&printer
, 2);
3869 * Debugging information, don't delete.
3872 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3873 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3874 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3876 for (i=0; i<info->count; i++) {
3877 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3878 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3879 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3885 /********************************************************************
3887 ********************************************************************/
3889 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3891 POLICY_HND
*handle
= &q_u
->handle
;
3892 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3894 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3895 WERROR result
= WERR_BADFID
;
3897 /* we always have a NOTIFY_INFO struct */
3901 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3902 OUR_HANDLE(handle
)));
3906 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3909 * We are now using the change value, and
3910 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3911 * I don't have a global notification system, I'm sending back all the
3912 * informations even when _NOTHING_ has changed.
3915 /* We need to keep track of the change value to send back in
3916 RRPCN replies otherwise our updates are ignored. */
3918 Printer
->notify
.fnpcn
= True
;
3920 if (Printer
->notify
.client_connected
) {
3921 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3922 Printer
->notify
.change
= q_u
->change
;
3925 /* just ignore the SPOOL_NOTIFY_OPTION */
3927 switch (Printer
->printer_type
) {
3929 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3932 case SPLHND_PRINTER
:
3933 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3937 Printer
->notify
.fnpcn
= False
;
3943 /********************************************************************
3944 * construct_printer_info_0
3945 * fill a printer_info_0 struct
3946 ********************************************************************/
3948 static BOOL
construct_printer_info_0(Printer_entry
*print_hnd
, PRINTER_INFO_0
*printer
, int snum
)
3952 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3953 counter_printer_0
*session_counter
;
3954 uint32 global_counter
;
3957 print_status_struct status
;
3959 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3962 count
= print_queue_length(snum
, &status
);
3964 /* check if we already have a counter for this printer */
3965 for(session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3966 if (session_counter
->snum
== snum
)
3970 /* it's the first time, add it to the list */
3971 if (session_counter
==NULL
) {
3972 if((session_counter
=SMB_MALLOC_P(counter_printer_0
)) == NULL
) {
3973 free_a_printer(&ntprinter
, 2);
3976 ZERO_STRUCTP(session_counter
);
3977 session_counter
->snum
=snum
;
3978 session_counter
->counter
=0;
3979 DLIST_ADD(counter_list
, session_counter
);
3983 session_counter
->counter
++;
3986 * the global_counter should be stored in a TDB as it's common to all the clients
3987 * and should be zeroed on samba startup
3989 global_counter
=session_counter
->counter
;
3991 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3993 init_unistr(&printer
->printername
, chaine
);
3995 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_server_name(print_hnd
));
3996 init_unistr(&printer
->servername
, chaine
);
3998 printer
->cjobs
= count
;
3999 printer
->total_jobs
= 0;
4000 printer
->total_bytes
= 0;
4002 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
4003 t
=gmtime(&setuptime
);
4005 printer
->year
= t
->tm_year
+1900;
4006 printer
->month
= t
->tm_mon
+1;
4007 printer
->dayofweek
= t
->tm_wday
;
4008 printer
->day
= t
->tm_mday
;
4009 printer
->hour
= t
->tm_hour
;
4010 printer
->minute
= t
->tm_min
;
4011 printer
->second
= t
->tm_sec
;
4012 printer
->milliseconds
= 0;
4014 printer
->global_counter
= global_counter
;
4015 printer
->total_pages
= 0;
4017 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4018 printer
->major_version
= 0x0005; /* NT 5 */
4019 printer
->build_version
= 0x0893; /* build 2195 */
4021 printer
->unknown7
= 0x1;
4022 printer
->unknown8
= 0x0;
4023 printer
->unknown9
= 0x0;
4024 printer
->session_counter
= session_counter
->counter
;
4025 printer
->unknown11
= 0x0;
4026 printer
->printer_errors
= 0x0; /* number of print failure */
4027 printer
->unknown13
= 0x0;
4028 printer
->unknown14
= 0x1;
4029 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
4030 printer
->unknown16
= 0x0;
4031 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
4032 printer
->unknown18
= 0x0;
4033 printer
->status
= nt_printq_status(status
.status
);
4034 printer
->unknown20
= 0x0;
4035 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4036 printer
->unknown22
= 0x0;
4037 printer
->unknown23
= 0x6; /* 6 ???*/
4038 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
4039 printer
->unknown25
= 0;
4040 printer
->unknown26
= 0;
4041 printer
->unknown27
= 0;
4042 printer
->unknown28
= 0;
4043 printer
->unknown29
= 0;
4045 free_a_printer(&ntprinter
,2);
4049 /********************************************************************
4050 * construct_printer_info_1
4051 * fill a printer_info_1 struct
4052 ********************************************************************/
4053 static BOOL
construct_printer_info_1(Printer_entry
*print_hnd
, uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
4057 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4059 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4062 printer
->flags
=flags
;
4064 if (*ntprinter
->info_2
->comment
== '\0') {
4065 init_unistr(&printer
->comment
, lp_comment(snum
));
4066 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4067 ntprinter
->info_2
->drivername
, lp_comment(snum
));
4070 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4071 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4072 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
4075 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
4077 init_unistr(&printer
->description
, chaine
);
4078 init_unistr(&printer
->name
, chaine2
);
4080 free_a_printer(&ntprinter
,2);
4085 /****************************************************************************
4086 Free a DEVMODE struct.
4087 ****************************************************************************/
4089 static void free_dev_mode(DEVICEMODE
*dev
)
4094 SAFE_FREE(dev
->dev_private
);
4099 /****************************************************************************
4100 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4101 should be valid upon entry
4102 ****************************************************************************/
4104 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
4106 if ( !devmode
|| !ntdevmode
)
4109 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
4111 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
4113 devmode
->specversion
= ntdevmode
->specversion
;
4114 devmode
->driverversion
= ntdevmode
->driverversion
;
4115 devmode
->size
= ntdevmode
->size
;
4116 devmode
->driverextra
= ntdevmode
->driverextra
;
4117 devmode
->fields
= ntdevmode
->fields
;
4119 devmode
->orientation
= ntdevmode
->orientation
;
4120 devmode
->papersize
= ntdevmode
->papersize
;
4121 devmode
->paperlength
= ntdevmode
->paperlength
;
4122 devmode
->paperwidth
= ntdevmode
->paperwidth
;
4123 devmode
->scale
= ntdevmode
->scale
;
4124 devmode
->copies
= ntdevmode
->copies
;
4125 devmode
->defaultsource
= ntdevmode
->defaultsource
;
4126 devmode
->printquality
= ntdevmode
->printquality
;
4127 devmode
->color
= ntdevmode
->color
;
4128 devmode
->duplex
= ntdevmode
->duplex
;
4129 devmode
->yresolution
= ntdevmode
->yresolution
;
4130 devmode
->ttoption
= ntdevmode
->ttoption
;
4131 devmode
->collate
= ntdevmode
->collate
;
4132 devmode
->icmmethod
= ntdevmode
->icmmethod
;
4133 devmode
->icmintent
= ntdevmode
->icmintent
;
4134 devmode
->mediatype
= ntdevmode
->mediatype
;
4135 devmode
->dithertype
= ntdevmode
->dithertype
;
4137 if (ntdevmode
->nt_dev_private
!= NULL
) {
4138 if ((devmode
->dev_private
=(uint8
*)memdup(ntdevmode
->nt_dev_private
, ntdevmode
->driverextra
)) == NULL
)
4145 /****************************************************************************
4146 Create a DEVMODE struct. Returns malloced memory.
4147 ****************************************************************************/
4149 DEVICEMODE
*construct_dev_mode(const char *servicename
)
4151 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4152 DEVICEMODE
*devmode
= NULL
;
4154 DEBUG(7,("construct_dev_mode\n"));
4156 DEBUGADD(8,("getting printer characteristics\n"));
4158 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
4161 if ( !printer
->info_2
->devmode
) {
4162 DEBUG(5, ("BONG! There was no device mode!\n"));
4166 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) == NULL
) {
4167 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4171 ZERO_STRUCTP(devmode
);
4173 DEBUGADD(8,("loading DEVICEMODE\n"));
4175 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4176 free_dev_mode( devmode
);
4181 free_a_printer(&printer
,2);
4186 /********************************************************************
4187 * construct_printer_info_2
4188 * fill a printer_info_2 struct
4189 ********************************************************************/
4191 static BOOL
construct_printer_info_2(Printer_entry
*print_hnd
, PRINTER_INFO_2
*printer
, int snum
)
4194 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4196 print_status_struct status
;
4198 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4201 count
= print_queue_length(snum
, &status
);
4203 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4204 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4205 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4206 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4207 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4209 if (*ntprinter
->info_2
->comment
== '\0')
4210 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4212 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4214 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4215 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4216 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4217 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4218 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4220 printer
->attributes
= ntprinter
->info_2
->attributes
;
4222 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4223 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4224 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4225 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4226 printer
->status
= nt_printq_status(status
.status
); /* status */
4227 printer
->cjobs
= count
; /* jobs */
4228 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4230 if ( !(printer
->devmode
= construct_dev_mode(
4231 lp_const_servicename(snum
))) )
4232 DEBUG(8, ("Returning NULL Devicemode!\n"));
4234 printer
->secdesc
= NULL
;
4236 if ( ntprinter
->info_2
->secdesc_buf
4237 && ntprinter
->info_2
->secdesc_buf
->len
!= 0 )
4239 /* don't use talloc_steal() here unless you do a deep steal of all
4240 the SEC_DESC members */
4242 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4243 ntprinter
->info_2
->secdesc_buf
->sec
);
4246 free_a_printer(&ntprinter
, 2);
4251 /********************************************************************
4252 * construct_printer_info_3
4253 * fill a printer_info_3 struct
4254 ********************************************************************/
4256 static BOOL
construct_printer_info_3(Printer_entry
*print_hnd
, PRINTER_INFO_3
**pp_printer
, int snum
)
4258 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4259 PRINTER_INFO_3
*printer
= NULL
;
4261 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4265 if ((printer
= SMB_MALLOC_P(PRINTER_INFO_3
)) == NULL
) {
4266 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4267 free_a_printer(&ntprinter
, 2);
4271 ZERO_STRUCTP(printer
);
4273 /* These are the components of the SD we are returning. */
4275 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4276 /* don't use talloc_steal() here unless you do a deep steal of all
4277 the SEC_DESC members */
4279 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4280 ntprinter
->info_2
->secdesc_buf
->sec
);
4283 free_a_printer(&ntprinter
, 2);
4285 *pp_printer
= printer
;
4289 /********************************************************************
4290 * construct_printer_info_4
4291 * fill a printer_info_4 struct
4292 ********************************************************************/
4294 static BOOL
construct_printer_info_4(Printer_entry
*print_hnd
, PRINTER_INFO_4
*printer
, int snum
)
4296 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4298 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4301 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4302 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4303 printer
->attributes
= ntprinter
->info_2
->attributes
;
4305 free_a_printer(&ntprinter
, 2);
4309 /********************************************************************
4310 * construct_printer_info_5
4311 * fill a printer_info_5 struct
4312 ********************************************************************/
4314 static BOOL
construct_printer_info_5(Printer_entry
*print_hnd
, PRINTER_INFO_5
*printer
, int snum
)
4316 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4318 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4321 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4322 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4323 printer
->attributes
= ntprinter
->info_2
->attributes
;
4325 /* these two are not used by NT+ according to MSDN */
4327 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4328 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4330 free_a_printer(&ntprinter
, 2);
4335 /********************************************************************
4336 * construct_printer_info_7
4337 * fill a printer_info_7 struct
4338 ********************************************************************/
4340 static BOOL
construct_printer_info_7(Printer_entry
*print_hnd
, PRINTER_INFO_7
*printer
, int snum
)
4342 char *guid_str
= NULL
;
4345 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4346 asprintf(&guid_str
, "{%s}", smb_uuid_string_static(guid
));
4347 strupper_m(guid_str
);
4348 init_unistr(&printer
->guid
, guid_str
);
4349 printer
->action
= SPOOL_DS_PUBLISH
;
4351 init_unistr(&printer
->guid
, "");
4352 printer
->action
= SPOOL_DS_UNPUBLISH
;
4358 /********************************************************************
4359 Spoolss_enumprinters.
4360 ********************************************************************/
4362 static WERROR
enum_all_printers_info_1(uint32 flags
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4366 int n_services
=lp_numservices();
4367 PRINTER_INFO_1
*printers
=NULL
;
4368 PRINTER_INFO_1 current_prt
;
4369 WERROR result
= WERR_OK
;
4371 DEBUG(4,("enum_all_printers_info_1\n"));
4373 for (snum
=0; snum
<n_services
; snum
++) {
4374 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4375 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4377 if (construct_printer_info_1(NULL
, flags
, ¤t_prt
, snum
)) {
4378 if((printers
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_1
, *returned
+1)) == NULL
) {
4379 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4383 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4385 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4391 /* check the required size. */
4392 for (i
=0; i
<*returned
; i
++)
4393 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4395 if (*needed
> offered
) {
4396 result
= WERR_INSUFFICIENT_BUFFER
;
4400 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4401 result
= WERR_NOMEM
;
4405 /* fill the buffer with the structures */
4406 for (i
=0; i
<*returned
; i
++)
4407 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4412 SAFE_FREE(printers
);
4414 if ( !W_ERROR_IS_OK(result
) )
4420 /********************************************************************
4421 enum_all_printers_info_1_local.
4422 *********************************************************************/
4424 static WERROR
enum_all_printers_info_1_local(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4426 DEBUG(4,("enum_all_printers_info_1_local\n"));
4428 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4431 /********************************************************************
4432 enum_all_printers_info_1_name.
4433 *********************************************************************/
4435 static WERROR
enum_all_printers_info_1_name(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4439 DEBUG(4,("enum_all_printers_info_1_name\n"));
4441 if ((name
[0] == '\\') && (name
[1] == '\\'))
4444 if (is_myname_or_ipaddr(s
)) {
4445 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4448 return WERR_INVALID_NAME
;
4451 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4452 /********************************************************************
4453 enum_all_printers_info_1_remote.
4454 *********************************************************************/
4456 static WERROR
enum_all_printers_info_1_remote(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4458 PRINTER_INFO_1
*printer
;
4459 fstring printername
;
4462 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4463 WERROR result
= WERR_OK
;
4465 /* JFM: currently it's more a place holder than anything else.
4466 * In the spooler world there is a notion of server registration.
4467 * the print servers are registered on the PDC (in the same domain)
4469 * We should have a TDB here. The registration is done thru an
4470 * undocumented RPC call.
4473 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4478 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", name
);
4479 slprintf(desc
, sizeof(desc
)-1,"%s", name
);
4480 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4482 init_unistr(&printer
->description
, desc
);
4483 init_unistr(&printer
->name
, printername
);
4484 init_unistr(&printer
->comment
, comment
);
4485 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4487 /* check the required size. */
4488 *needed
+= spoolss_size_printer_info_1(printer
);
4490 if (*needed
> offered
) {
4491 result
= WERR_INSUFFICIENT_BUFFER
;
4495 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4496 result
= WERR_NOMEM
;
4500 /* fill the buffer with the structures */
4501 smb_io_printer_info_1("", buffer
, printer
, 0);
4507 if ( !W_ERROR_IS_OK(result
) )
4515 /********************************************************************
4516 enum_all_printers_info_1_network.
4517 *********************************************************************/
4519 static WERROR
enum_all_printers_info_1_network(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4523 DEBUG(4,("enum_all_printers_info_1_network\n"));
4525 /* If we respond to a enum_printers level 1 on our name with flags
4526 set to PRINTER_ENUM_REMOTE with a list of printers then these
4527 printers incorrectly appear in the APW browse list.
4528 Specifically the printers for the server appear at the workgroup
4529 level where all the other servers in the domain are
4530 listed. Windows responds to this call with a
4531 WERR_CAN_NOT_COMPLETE so we should do the same. */
4533 if (name
[0] == '\\' && name
[1] == '\\')
4536 if (is_myname_or_ipaddr(s
))
4537 return WERR_CAN_NOT_COMPLETE
;
4539 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4542 /********************************************************************
4543 * api_spoolss_enumprinters
4545 * called from api_spoolss_enumprinters (see this to understand)
4546 ********************************************************************/
4548 static WERROR
enum_all_printers_info_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4552 int n_services
=lp_numservices();
4553 PRINTER_INFO_2
*printers
=NULL
;
4554 PRINTER_INFO_2 current_prt
;
4555 WERROR result
= WERR_OK
;
4559 for (snum
=0; snum
<n_services
; snum
++) {
4560 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4561 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4563 if (construct_printer_info_2(NULL
, ¤t_prt
, snum
)) {
4564 if ( !(printers
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_2
, *returned
+1)) ) {
4565 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4570 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
+ 1));
4572 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4579 /* check the required size. */
4580 for (i
=0; i
<*returned
; i
++)
4581 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4583 if (*needed
> offered
) {
4584 result
= WERR_INSUFFICIENT_BUFFER
;
4588 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4589 result
= WERR_NOMEM
;
4593 /* fill the buffer with the structures */
4594 for (i
=0; i
<*returned
; i
++)
4595 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4600 for (i
=0; i
<*returned
; i
++)
4601 free_devmode(printers
[i
].devmode
);
4603 SAFE_FREE(printers
);
4605 if ( !W_ERROR_IS_OK(result
) )
4611 /********************************************************************
4612 * handle enumeration of printers at level 1
4613 ********************************************************************/
4615 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4616 RPC_BUFFER
*buffer
, uint32 offered
,
4617 uint32
*needed
, uint32
*returned
)
4619 /* Not all the flags are equals */
4621 if (flags
& PRINTER_ENUM_LOCAL
)
4622 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4624 if (flags
& PRINTER_ENUM_NAME
)
4625 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4627 #if 0 /* JERRY - disabled for now */
4628 if (flags
& PRINTER_ENUM_REMOTE
)
4629 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4632 if (flags
& PRINTER_ENUM_NETWORK
)
4633 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4635 return WERR_OK
; /* NT4sp5 does that */
4638 /********************************************************************
4639 * handle enumeration of printers at level 2
4640 ********************************************************************/
4642 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4643 RPC_BUFFER
*buffer
, uint32 offered
,
4644 uint32
*needed
, uint32
*returned
)
4646 char *s
= servername
;
4648 if (flags
& PRINTER_ENUM_LOCAL
) {
4649 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4652 if (flags
& PRINTER_ENUM_NAME
) {
4653 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4655 if (is_myname_or_ipaddr(s
))
4656 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4658 return WERR_INVALID_NAME
;
4661 if (flags
& PRINTER_ENUM_REMOTE
)
4662 return WERR_UNKNOWN_LEVEL
;
4667 /********************************************************************
4668 * handle enumeration of printers at level 5
4669 ********************************************************************/
4671 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4672 RPC_BUFFER
*buffer
, uint32 offered
,
4673 uint32
*needed
, uint32
*returned
)
4675 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4679 /********************************************************************
4680 * api_spoolss_enumprinters
4682 * called from api_spoolss_enumprinters (see this to understand)
4683 ********************************************************************/
4685 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4687 uint32 flags
= q_u
->flags
;
4688 UNISTR2
*servername
= &q_u
->servername
;
4689 uint32 level
= q_u
->level
;
4690 RPC_BUFFER
*buffer
= NULL
;
4691 uint32 offered
= q_u
->offered
;
4692 uint32
*needed
= &r_u
->needed
;
4693 uint32
*returned
= &r_u
->returned
;
4697 /* that's an [in out] buffer */
4699 if (!q_u
->buffer
&& (offered
!=0)) {
4700 return WERR_INVALID_PARAM
;
4703 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
4704 buffer
= r_u
->buffer
;
4706 DEBUG(4,("_spoolss_enumprinters\n"));
4713 * flags==PRINTER_ENUM_NAME
4714 * if name=="" then enumerates all printers
4715 * if name!="" then enumerate the printer
4716 * flags==PRINTER_ENUM_REMOTE
4717 * name is NULL, enumerate printers
4718 * Level 2: name!="" enumerates printers, name can't be NULL
4719 * Level 3: doesn't exist
4720 * Level 4: does a local registry lookup
4721 * Level 5: same as Level 2
4724 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4729 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4731 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4733 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4738 return WERR_UNKNOWN_LEVEL
;
4741 /****************************************************************************
4742 ****************************************************************************/
4744 static WERROR
getprinter_level_0(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4746 PRINTER_INFO_0
*printer
=NULL
;
4747 WERROR result
= WERR_OK
;
4749 if((printer
=SMB_MALLOC_P(PRINTER_INFO_0
)) == NULL
)
4752 construct_printer_info_0(print_hnd
, printer
, snum
);
4754 /* check the required size. */
4755 *needed
+= spoolss_size_printer_info_0(printer
);
4757 if (*needed
> offered
) {
4758 result
= WERR_INSUFFICIENT_BUFFER
;
4762 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4763 result
= WERR_NOMEM
;
4767 /* fill the buffer with the structures */
4768 smb_io_printer_info_0("", buffer
, printer
, 0);
4778 /****************************************************************************
4779 ****************************************************************************/
4781 static WERROR
getprinter_level_1(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4783 PRINTER_INFO_1
*printer
=NULL
;
4784 WERROR result
= WERR_OK
;
4786 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4789 construct_printer_info_1(print_hnd
, PRINTER_ENUM_ICON8
, printer
, snum
);
4791 /* check the required size. */
4792 *needed
+= spoolss_size_printer_info_1(printer
);
4794 if (*needed
> offered
) {
4795 result
= WERR_INSUFFICIENT_BUFFER
;
4799 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4800 result
= WERR_NOMEM
;
4804 /* fill the buffer with the structures */
4805 smb_io_printer_info_1("", buffer
, printer
, 0);
4814 /****************************************************************************
4815 ****************************************************************************/
4817 static WERROR
getprinter_level_2(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4819 PRINTER_INFO_2
*printer
=NULL
;
4820 WERROR result
= WERR_OK
;
4822 if((printer
=SMB_MALLOC_P(PRINTER_INFO_2
))==NULL
)
4825 construct_printer_info_2(print_hnd
, printer
, snum
);
4827 /* check the required size. */
4828 *needed
+= spoolss_size_printer_info_2(printer
);
4830 if (*needed
> offered
) {
4831 result
= WERR_INSUFFICIENT_BUFFER
;
4835 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4836 result
= WERR_NOMEM
;
4840 /* fill the buffer with the structures */
4841 if (!smb_io_printer_info_2("", buffer
, printer
, 0))
4842 result
= WERR_NOMEM
;
4846 free_printer_info_2(printer
);
4851 /****************************************************************************
4852 ****************************************************************************/
4854 static WERROR
getprinter_level_3(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4856 PRINTER_INFO_3
*printer
=NULL
;
4857 WERROR result
= WERR_OK
;
4859 if (!construct_printer_info_3(print_hnd
, &printer
, snum
))
4862 /* check the required size. */
4863 *needed
+= spoolss_size_printer_info_3(printer
);
4865 if (*needed
> offered
) {
4866 result
= WERR_INSUFFICIENT_BUFFER
;
4870 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4871 result
= WERR_NOMEM
;
4875 /* fill the buffer with the structures */
4876 smb_io_printer_info_3("", buffer
, printer
, 0);
4880 free_printer_info_3(printer
);
4885 /****************************************************************************
4886 ****************************************************************************/
4888 static WERROR
getprinter_level_4(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4890 PRINTER_INFO_4
*printer
=NULL
;
4891 WERROR result
= WERR_OK
;
4893 if((printer
=SMB_MALLOC_P(PRINTER_INFO_4
))==NULL
)
4896 if (!construct_printer_info_4(print_hnd
, printer
, snum
)) {
4901 /* check the required size. */
4902 *needed
+= spoolss_size_printer_info_4(printer
);
4904 if (*needed
> offered
) {
4905 result
= WERR_INSUFFICIENT_BUFFER
;
4909 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4910 result
= WERR_NOMEM
;
4914 /* fill the buffer with the structures */
4915 smb_io_printer_info_4("", buffer
, printer
, 0);
4919 free_printer_info_4(printer
);
4924 /****************************************************************************
4925 ****************************************************************************/
4927 static WERROR
getprinter_level_5(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4929 PRINTER_INFO_5
*printer
=NULL
;
4930 WERROR result
= WERR_OK
;
4932 if((printer
=SMB_MALLOC_P(PRINTER_INFO_5
))==NULL
)
4935 if (!construct_printer_info_5(print_hnd
, printer
, snum
)) {
4936 free_printer_info_5(printer
);
4940 /* check the required size. */
4941 *needed
+= spoolss_size_printer_info_5(printer
);
4943 if (*needed
> offered
) {
4944 result
= WERR_INSUFFICIENT_BUFFER
;
4948 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4949 result
= WERR_NOMEM
;
4953 /* fill the buffer with the structures */
4954 smb_io_printer_info_5("", buffer
, printer
, 0);
4958 free_printer_info_5(printer
);
4963 static WERROR
getprinter_level_7(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4965 PRINTER_INFO_7
*printer
=NULL
;
4966 WERROR result
= WERR_OK
;
4968 if((printer
=SMB_MALLOC_P(PRINTER_INFO_7
))==NULL
)
4971 if (!construct_printer_info_7(print_hnd
, printer
, snum
))
4974 /* check the required size. */
4975 *needed
+= spoolss_size_printer_info_7(printer
);
4977 if (*needed
> offered
) {
4978 result
= WERR_INSUFFICIENT_BUFFER
;
4982 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4983 result
= WERR_NOMEM
;
4988 /* fill the buffer with the structures */
4989 smb_io_printer_info_7("", buffer
, printer
, 0);
4993 free_printer_info_7(printer
);
4998 /****************************************************************************
4999 ****************************************************************************/
5001 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
5003 POLICY_HND
*handle
= &q_u
->handle
;
5004 uint32 level
= q_u
->level
;
5005 RPC_BUFFER
*buffer
= NULL
;
5006 uint32 offered
= q_u
->offered
;
5007 uint32
*needed
= &r_u
->needed
;
5008 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
5012 /* that's an [in out] buffer */
5014 if (!q_u
->buffer
&& (offered
!=0)) {
5015 return WERR_INVALID_PARAM
;
5018 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5019 buffer
= r_u
->buffer
;
5023 if (!get_printer_snum(p
, handle
, &snum
))
5028 return getprinter_level_0(Printer
, snum
, buffer
, offered
, needed
);
5030 return getprinter_level_1(Printer
, snum
, buffer
, offered
, needed
);
5032 return getprinter_level_2(Printer
, snum
, buffer
, offered
, needed
);
5034 return getprinter_level_3(Printer
, snum
, buffer
, offered
, needed
);
5036 return getprinter_level_4(Printer
, snum
, buffer
, offered
, needed
);
5038 return getprinter_level_5(Printer
, snum
, buffer
, offered
, needed
);
5040 return getprinter_level_7(Printer
, snum
, buffer
, offered
, needed
);
5042 return WERR_UNKNOWN_LEVEL
;
5045 /********************************************************************
5046 * fill a DRIVER_INFO_1 struct
5047 ********************************************************************/
5049 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
5051 init_unistr( &info
->name
, driver
.info_3
->name
);
5054 /********************************************************************
5055 * construct_printer_driver_info_1
5056 ********************************************************************/
5058 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5060 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5061 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
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_1(info
, driver
, servername
, architecture
);
5075 free_a_printer(&printer
,2);
5080 /********************************************************************
5081 * construct_printer_driver_info_2
5082 * fill a printer_info_2 struct
5083 ********************************************************************/
5085 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5089 info
->version
=driver
.info_3
->cversion
;
5091 init_unistr( &info
->name
, driver
.info_3
->name
);
5092 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5095 if (strlen(driver
.info_3
->driverpath
)) {
5096 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5097 init_unistr( &info
->driverpath
, temp
);
5099 init_unistr( &info
->driverpath
, "" );
5101 if (strlen(driver
.info_3
->datafile
)) {
5102 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5103 init_unistr( &info
->datafile
, temp
);
5105 init_unistr( &info
->datafile
, "" );
5107 if (strlen(driver
.info_3
->configfile
)) {
5108 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5109 init_unistr( &info
->configfile
, temp
);
5111 init_unistr( &info
->configfile
, "" );
5114 /********************************************************************
5115 * construct_printer_driver_info_2
5116 * fill a printer_info_2 struct
5117 ********************************************************************/
5119 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5121 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5122 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5124 ZERO_STRUCT(printer
);
5125 ZERO_STRUCT(driver
);
5127 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5128 return WERR_INVALID_PRINTER_NAME
;
5130 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5131 free_a_printer(&printer
, 2);
5132 return WERR_UNKNOWN_PRINTER_DRIVER
;
5135 fill_printer_driver_info_2(info
, driver
, servername
);
5137 free_a_printer(&printer
,2);
5142 /********************************************************************
5143 * copy a strings array and convert to UNICODE
5145 * convert an array of ascii string to a UNICODE string
5146 ********************************************************************/
5148 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
5155 DEBUG(6,("init_unistr_array\n"));
5166 v
= ""; /* hack to handle null lists */
5169 /* hack to allow this to be used in places other than when generating
5170 the list of dependent files */
5173 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
5177 DEBUGADD(6,("%d:%s:%lu\n", i
, line
, (unsigned long)strlen(line
)));
5179 /* add one extra unit16 for the second terminating NULL */
5181 if ( (*uni_array
=SMB_REALLOC_ARRAY(*uni_array
, uint16
, j
+1+strlen(line
)+2)) == NULL
) {
5182 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5189 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
5194 /* special case for ""; we need to add both NULL's here */
5196 (*uni_array
)[j
++]=0x0000;
5197 (*uni_array
)[j
]=0x0000;
5200 DEBUGADD(6,("last one:done\n"));
5202 /* return size of array in uint16's */
5207 /********************************************************************
5208 * construct_printer_info_3
5209 * fill a printer_info_3 struct
5210 ********************************************************************/
5212 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5218 info
->version
=driver
.info_3
->cversion
;
5220 init_unistr( &info
->name
, driver
.info_3
->name
);
5221 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5223 if (strlen(driver
.info_3
->driverpath
)) {
5224 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5225 init_unistr( &info
->driverpath
, temp
);
5227 init_unistr( &info
->driverpath
, "" );
5229 if (strlen(driver
.info_3
->datafile
)) {
5230 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5231 init_unistr( &info
->datafile
, temp
);
5233 init_unistr( &info
->datafile
, "" );
5235 if (strlen(driver
.info_3
->configfile
)) {
5236 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5237 init_unistr( &info
->configfile
, temp
);
5239 init_unistr( &info
->configfile
, "" );
5241 if (strlen(driver
.info_3
->helpfile
)) {
5242 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5243 init_unistr( &info
->helpfile
, temp
);
5245 init_unistr( &info
->helpfile
, "" );
5247 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5248 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5250 info
->dependentfiles
=NULL
;
5251 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5254 /********************************************************************
5255 * construct_printer_info_3
5256 * fill a printer_info_3 struct
5257 ********************************************************************/
5259 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5261 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5262 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5264 ZERO_STRUCT(driver
);
5266 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5267 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5268 if (!W_ERROR_IS_OK(status
))
5269 return WERR_INVALID_PRINTER_NAME
;
5271 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5272 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5277 * I put this code in during testing. Helpful when commenting out the
5278 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5279 * as win2k always queries the driver using an infor level of 6.
5280 * I've left it in (but ifdef'd out) because I'll probably
5281 * use it in experimentation again in the future. --jerry 22/01/2002
5284 if (!W_ERROR_IS_OK(status
)) {
5286 * Is this a W2k client ?
5289 /* Yes - try again with a WinNT driver. */
5291 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5292 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5296 if (!W_ERROR_IS_OK(status
)) {
5297 free_a_printer(&printer
,2);
5298 return WERR_UNKNOWN_PRINTER_DRIVER
;
5306 fill_printer_driver_info_3(info
, driver
, servername
);
5308 free_a_printer(&printer
,2);
5313 /********************************************************************
5314 * construct_printer_info_6
5315 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5316 ********************************************************************/
5318 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5324 memset(&nullstr
, '\0', sizeof(fstring
));
5326 info
->version
=driver
.info_3
->cversion
;
5328 init_unistr( &info
->name
, driver
.info_3
->name
);
5329 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5331 if (strlen(driver
.info_3
->driverpath
)) {
5332 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5333 init_unistr( &info
->driverpath
, temp
);
5335 init_unistr( &info
->driverpath
, "" );
5337 if (strlen(driver
.info_3
->datafile
)) {
5338 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5339 init_unistr( &info
->datafile
, temp
);
5341 init_unistr( &info
->datafile
, "" );
5343 if (strlen(driver
.info_3
->configfile
)) {
5344 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5345 init_unistr( &info
->configfile
, temp
);
5347 init_unistr( &info
->configfile
, "" );
5349 if (strlen(driver
.info_3
->helpfile
)) {
5350 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5351 init_unistr( &info
->helpfile
, temp
);
5353 init_unistr( &info
->helpfile
, "" );
5355 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5356 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5358 info
->dependentfiles
= NULL
;
5359 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5361 info
->previousdrivernames
=NULL
;
5362 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5364 info
->driver_date
=0;
5367 info
->driver_version_low
=0;
5368 info
->driver_version_high
=0;
5370 init_unistr( &info
->mfgname
, "");
5371 init_unistr( &info
->oem_url
, "");
5372 init_unistr( &info
->hardware_id
, "");
5373 init_unistr( &info
->provider
, "");
5376 /********************************************************************
5377 * construct_printer_info_6
5378 * fill a printer_info_6 struct
5379 ********************************************************************/
5381 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5382 fstring servername
, fstring architecture
, uint32 version
)
5384 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5385 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5388 ZERO_STRUCT(driver
);
5390 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5392 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5394 if (!W_ERROR_IS_OK(status
))
5395 return WERR_INVALID_PRINTER_NAME
;
5397 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5399 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5401 if (!W_ERROR_IS_OK(status
))
5404 * Is this a W2k client ?
5408 free_a_printer(&printer
,2);
5409 return WERR_UNKNOWN_PRINTER_DRIVER
;
5412 /* Yes - try again with a WinNT driver. */
5414 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5415 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5416 if (!W_ERROR_IS_OK(status
)) {
5417 free_a_printer(&printer
,2);
5418 return WERR_UNKNOWN_PRINTER_DRIVER
;
5422 fill_printer_driver_info_6(info
, driver
, servername
);
5424 free_a_printer(&printer
,2);
5425 free_a_printer_driver(driver
, 3);
5430 /****************************************************************************
5431 ****************************************************************************/
5433 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5435 SAFE_FREE(info
->dependentfiles
);
5438 /****************************************************************************
5439 ****************************************************************************/
5441 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5443 SAFE_FREE(info
->dependentfiles
);
5446 /****************************************************************************
5447 ****************************************************************************/
5449 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5451 DRIVER_INFO_1
*info
=NULL
;
5454 if((info
=SMB_MALLOC_P(DRIVER_INFO_1
)) == NULL
)
5457 result
= construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5458 if (!W_ERROR_IS_OK(result
))
5461 /* check the required size. */
5462 *needed
+= spoolss_size_printer_driver_info_1(info
);
5464 if (*needed
> offered
) {
5465 result
= WERR_INSUFFICIENT_BUFFER
;
5469 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5470 result
= WERR_NOMEM
;
5474 /* fill the buffer with the structures */
5475 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5484 /****************************************************************************
5485 ****************************************************************************/
5487 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5489 DRIVER_INFO_2
*info
=NULL
;
5492 if((info
=SMB_MALLOC_P(DRIVER_INFO_2
)) == NULL
)
5495 result
= construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5496 if (!W_ERROR_IS_OK(result
))
5499 /* check the required size. */
5500 *needed
+= spoolss_size_printer_driver_info_2(info
);
5502 if (*needed
> offered
) {
5503 result
= WERR_INSUFFICIENT_BUFFER
;
5507 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5508 result
= WERR_NOMEM
;
5512 /* fill the buffer with the structures */
5513 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5522 /****************************************************************************
5523 ****************************************************************************/
5525 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5532 result
= construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5533 if (!W_ERROR_IS_OK(result
))
5536 /* check the required size. */
5537 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5539 if (*needed
> offered
) {
5540 result
= WERR_INSUFFICIENT_BUFFER
;
5544 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5545 result
= WERR_NOMEM
;
5549 /* fill the buffer with the structures */
5550 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5553 free_printer_driver_info_3(&info
);
5558 /****************************************************************************
5559 ****************************************************************************/
5561 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5568 result
= construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5569 if (!W_ERROR_IS_OK(result
))
5572 /* check the required size. */
5573 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5575 if (*needed
> offered
) {
5576 result
= WERR_INSUFFICIENT_BUFFER
;
5580 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5581 result
= WERR_NOMEM
;
5585 /* fill the buffer with the structures */
5586 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5589 free_printer_driver_info_6(&info
);
5594 /****************************************************************************
5595 ****************************************************************************/
5597 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5599 POLICY_HND
*handle
= &q_u
->handle
;
5600 UNISTR2
*uni_arch
= &q_u
->architecture
;
5601 uint32 level
= q_u
->level
;
5602 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5603 RPC_BUFFER
*buffer
= NULL
;
5604 uint32 offered
= q_u
->offered
;
5605 uint32
*needed
= &r_u
->needed
;
5606 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5607 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5608 Printer_entry
*printer
;
5611 fstring architecture
;
5614 /* that's an [in out] buffer */
5616 if (!q_u
->buffer
&& (offered
!=0)) {
5617 return WERR_INVALID_PARAM
;
5620 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5621 buffer
= r_u
->buffer
;
5623 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5625 if ( !(printer
= find_printer_index_by_hnd( p
, handle
)) ) {
5626 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5627 return WERR_INVALID_PRINTER_NAME
;
5631 *servermajorversion
= 0;
5632 *serverminorversion
= 0;
5634 fstrcpy(servername
, get_server_name( printer
));
5635 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5637 if (!get_printer_snum(p
, handle
, &snum
))
5642 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5644 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5646 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5648 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5651 /* apparently this call is the equivalent of
5652 EnumPrinterDataEx() for the DsDriver key */
5657 return WERR_UNKNOWN_LEVEL
;
5660 /****************************************************************************
5661 ****************************************************************************/
5663 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5665 POLICY_HND
*handle
= &q_u
->handle
;
5667 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5670 DEBUG(3,("Error in startpageprinter printer handle\n"));
5674 Printer
->page_started
=True
;
5678 /****************************************************************************
5679 ****************************************************************************/
5681 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5683 POLICY_HND
*handle
= &q_u
->handle
;
5686 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5689 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5693 if (!get_printer_snum(p
, handle
, &snum
))
5696 Printer
->page_started
=False
;
5697 print_job_endpage(snum
, Printer
->jobid
);
5702 /********************************************************************
5703 * api_spoolss_getprinter
5704 * called from the spoolss dispatcher
5706 ********************************************************************/
5708 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5710 POLICY_HND
*handle
= &q_u
->handle
;
5711 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5712 uint32
*jobid
= &r_u
->jobid
;
5714 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5718 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5719 struct current_user user
;
5722 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5726 get_current_user(&user
, p
);
5729 * a nice thing with NT is it doesn't listen to what you tell it.
5730 * when asked to send _only_ RAW datas, it tries to send datas
5733 * So I add checks like in NT Server ...
5736 if (info_1
->p_datatype
!= 0) {
5737 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5738 if (strcmp(datatype
, "RAW") != 0) {
5740 return WERR_INVALID_DATATYPE
;
5744 /* get the share number of the printer */
5745 if (!get_printer_snum(p
, handle
, &snum
)) {
5749 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5751 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5753 /* An error occured in print_job_start() so return an appropriate
5756 if (Printer
->jobid
== -1) {
5757 return map_werror_from_unix(errno
);
5760 Printer
->document_started
=True
;
5761 (*jobid
) = Printer
->jobid
;
5766 /********************************************************************
5767 * api_spoolss_getprinter
5768 * called from the spoolss dispatcher
5770 ********************************************************************/
5772 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5774 POLICY_HND
*handle
= &q_u
->handle
;
5776 return _spoolss_enddocprinter_internal(p
, handle
);
5779 /****************************************************************************
5780 ****************************************************************************/
5782 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5784 POLICY_HND
*handle
= &q_u
->handle
;
5785 uint32 buffer_size
= q_u
->buffer_size
;
5786 uint8
*buffer
= q_u
->buffer
;
5787 uint32
*buffer_written
= &q_u
->buffer_size2
;
5789 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5792 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5793 r_u
->buffer_written
= q_u
->buffer_size2
;
5797 if (!get_printer_snum(p
, handle
, &snum
))
5800 (*buffer_written
) = (uint32
)print_job_write(snum
, Printer
->jobid
, (const char *)buffer
,
5801 (SMB_OFF_T
)-1, (size_t)buffer_size
);
5802 if (*buffer_written
== (uint32
)-1) {
5803 r_u
->buffer_written
= 0;
5804 if (errno
== ENOSPC
)
5805 return WERR_NO_SPOOL_SPACE
;
5807 return WERR_ACCESS_DENIED
;
5810 r_u
->buffer_written
= q_u
->buffer_size2
;
5815 /********************************************************************
5816 * api_spoolss_getprinter
5817 * called from the spoolss dispatcher
5819 ********************************************************************/
5821 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5824 struct current_user user
;
5826 WERROR errcode
= WERR_BADFUNC
;
5827 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5829 get_current_user(&user
, p
);
5832 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5836 if (!get_printer_snum(p
, handle
, &snum
))
5840 case PRINTER_CONTROL_PAUSE
:
5841 if (print_queue_pause(&user
, snum
, &errcode
)) {
5845 case PRINTER_CONTROL_RESUME
:
5846 case PRINTER_CONTROL_UNPAUSE
:
5847 if (print_queue_resume(&user
, snum
, &errcode
)) {
5851 case PRINTER_CONTROL_PURGE
:
5852 if (print_queue_purge(&user
, snum
, &errcode
)) {
5857 return WERR_UNKNOWN_LEVEL
;
5863 /********************************************************************
5864 * api_spoolss_abortprinter
5865 * From MSDN: "Deletes printer's spool file if printer is configured
5867 ********************************************************************/
5869 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5871 POLICY_HND
*handle
= &q_u
->handle
;
5872 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5874 struct current_user user
;
5875 WERROR errcode
= WERR_OK
;
5878 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5882 if (!get_printer_snum(p
, handle
, &snum
))
5885 get_current_user( &user
, p
);
5887 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5892 /********************************************************************
5893 * called by spoolss_api_setprinter
5894 * when updating a printer description
5895 ********************************************************************/
5897 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5898 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5899 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5901 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5905 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5907 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5908 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5909 OUR_HANDLE(handle
)));
5911 result
= WERR_BADFID
;
5916 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5917 result
= WERR_INVALID_PARAM
;
5921 /* Check the user has permissions to change the security
5922 descriptor. By experimentation with two NT machines, the user
5923 requires Full Access to the printer to change security
5926 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5927 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5928 result
= WERR_ACCESS_DENIED
;
5932 /* NT seems to like setting the security descriptor even though
5933 nothing may have actually changed. */
5935 nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
);
5937 if (DEBUGLEVEL
>= 10) {
5941 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5942 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5943 PRINTERNAME(snum
), the_acl
->num_aces
));
5945 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5948 sid_to_string(sid_str
, &the_acl
->aces
[i
].trustee
);
5950 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5951 the_acl
->aces
[i
].access_mask
));
5954 the_acl
= secdesc_ctr
->sec
->dacl
;
5957 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5958 PRINTERNAME(snum
), the_acl
->num_aces
));
5960 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5963 sid_to_string(sid_str
, &the_acl
->aces
[i
].trustee
);
5965 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5966 the_acl
->aces
[i
].access_mask
));
5969 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5973 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5974 if (!new_secdesc_ctr
) {
5975 result
= WERR_NOMEM
;
5979 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5984 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5991 /********************************************************************
5992 Canonicalize printer info from a client
5994 ATTN: It does not matter what we set the servername to hear
5995 since we do the necessary work in get_a_printer() to set it to
5996 the correct value based on what the client sent in the
5997 _spoolss_open_printer_ex().
5998 ********************************************************************/
6000 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
6002 fstring printername
;
6005 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6006 "portname=%s drivername=%s comment=%s location=%s\n",
6007 info
->servername
, info
->printername
, info
->sharename
,
6008 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
6010 /* we force some elements to "correct" values */
6011 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
6012 fstrcpy(info
->sharename
, lp_servicename(snum
));
6014 /* check to see if we allow printername != sharename */
6016 if ( lp_force_printername(snum
) ) {
6017 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
6018 global_myname(), info
->sharename
);
6021 /* make sure printername is in \\server\printername format */
6023 fstrcpy( printername
, info
->printername
);
6025 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
6026 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
6030 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
6031 global_myname(), p
);
6034 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
6035 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
6042 /****************************************************************************
6043 ****************************************************************************/
6045 WERROR
add_port_hook(NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
6047 char *cmd
= lp_addport_cmd();
6051 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
6052 BOOL is_print_op
= False
;
6055 return WERR_ACCESS_DENIED
;
6058 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
6061 is_print_op
= user_has_privileges( token
, &se_printop
);
6063 DEBUG(10,("Running [%s]\n", command
));
6065 /********* BEGIN SePrintOperatorPrivilege **********/
6070 ret
= smbrun(command
, &fd
);
6075 /********* END SePrintOperatorPrivilege **********/
6077 DEBUGADD(10,("returned [%d]\n", ret
));
6082 return WERR_ACCESS_DENIED
;
6088 /****************************************************************************
6089 ****************************************************************************/
6091 BOOL
add_printer_hook(NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
6093 char *cmd
= lp_addprinter_cmd();
6099 fstring remote_machine
= "%m";
6100 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
6101 BOOL is_print_op
= False
;
6103 standard_sub_basic(current_user_info
.smb_name
,
6104 current_user_info
.domain
,
6105 remote_machine
,sizeof(remote_machine
));
6107 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6108 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
6109 printer
->info_2
->portname
, printer
->info_2
->drivername
,
6110 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
6113 is_print_op
= user_has_privileges( token
, &se_printop
);
6115 DEBUG(10,("Running [%s]\n", command
));
6117 /********* BEGIN SePrintOperatorPrivilege **********/
6122 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6123 /* Tell everyone we updated smb.conf. */
6124 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
6130 /********* END SePrintOperatorPrivilege **********/
6132 DEBUGADD(10,("returned [%d]\n", ret
));
6140 /* reload our services immediately */
6141 reload_services( False
);
6144 /* Get lines and convert them back to dos-codepage */
6145 qlines
= fd_lines_load(fd
, &numlines
, 0);
6146 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6149 /* Set the portname to what the script says the portname should be. */
6150 /* but don't require anything to be return from the script exit a good error code */
6153 /* Set the portname to what the script says the portname should be. */
6154 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
6155 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6158 file_lines_free(qlines
);
6163 /********************************************************************
6164 * Called by spoolss_api_setprinter
6165 * when updating a printer description.
6166 ********************************************************************/
6168 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
6169 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6170 DEVICEMODE
*devmode
)
6173 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6174 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6179 DEBUG(8,("update_printer\n"));
6184 result
= WERR_BADFID
;
6188 if (!get_printer_snum(p
, handle
, &snum
)) {
6189 result
= WERR_BADFID
;
6193 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6194 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6195 result
= WERR_BADFID
;
6199 DEBUGADD(8,("Converting info_2 struct\n"));
6202 * convert_printer_info converts the incoming
6203 * info from the client and overwrites the info
6204 * just read from the tdb in the pointer 'printer'.
6207 if (!convert_printer_info(info
, printer
, level
)) {
6208 result
= WERR_NOMEM
;
6213 /* we have a valid devmode
6214 convert it and link it*/
6216 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6217 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6218 &printer
->info_2
->devmode
)) {
6219 result
= WERR_NOMEM
;
6224 /* Do sanity check on the requested changes for Samba */
6226 if (!check_printer_ok(printer
->info_2
, snum
)) {
6227 result
= WERR_INVALID_PARAM
;
6231 /* FIXME!!! If the driver has changed we really should verify that
6232 it is installed before doing much else --jerry */
6234 /* Check calling user has permission to update printer description */
6236 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6237 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6238 result
= WERR_ACCESS_DENIED
;
6242 /* Call addprinter hook */
6243 /* Check changes to see if this is really needed */
6245 if ( *lp_addprinter_cmd()
6246 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6247 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6248 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6249 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6251 /* add_printer_hook() will call reload_services() */
6253 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
6254 result
= WERR_ACCESS_DENIED
;
6260 * When a *new* driver is bound to a printer, the drivername is used to
6261 * lookup previously saved driver initialization info, which is then
6262 * bound to the printer, simulating what happens in the Windows arch.
6264 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6266 if (!set_driver_init(printer
, 2))
6268 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6269 printer
->info_2
->drivername
));
6272 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6273 printer
->info_2
->drivername
));
6275 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6279 * flag which changes actually occured. This is a small subset of
6280 * all the possible changes. We also have to update things in the
6284 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6285 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6286 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6287 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6289 notify_printer_comment(snum
, printer
->info_2
->comment
);
6292 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6293 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6294 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6295 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6297 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6300 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6303 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6306 pname
= printer
->info_2
->printername
;
6309 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6310 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6311 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6313 notify_printer_printername( snum
, pname
);
6316 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6317 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6318 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6319 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6321 notify_printer_port(snum
, printer
->info_2
->portname
);
6324 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6325 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6326 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6327 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6329 notify_printer_location(snum
, printer
->info_2
->location
);
6332 /* here we need to update some more DsSpooler keys */
6333 /* uNCName, serverName, shortServerName */
6335 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6336 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6337 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6338 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6339 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6341 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6342 global_myname(), printer
->info_2
->sharename
);
6343 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6344 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6345 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6347 /* Update printer info */
6348 result
= mod_a_printer(printer
, 2);
6351 free_a_printer(&printer
, 2);
6352 free_a_printer(&old_printer
, 2);
6358 /****************************************************************************
6359 ****************************************************************************/
6360 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6361 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6364 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6366 Printer_entry
*Printer
;
6368 if ( lp_security() != SEC_ADS
) {
6369 return WERR_UNKNOWN_LEVEL
;
6372 Printer
= find_printer_index_by_hnd(p
, handle
);
6374 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6379 if (!get_printer_snum(p
, handle
, &snum
))
6382 nt_printer_publish(Printer
, snum
, info7
->action
);
6386 return WERR_UNKNOWN_LEVEL
;
6389 /****************************************************************************
6390 ****************************************************************************/
6392 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6394 POLICY_HND
*handle
= &q_u
->handle
;
6395 uint32 level
= q_u
->level
;
6396 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6397 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6398 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6399 uint32 command
= q_u
->command
;
6402 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6405 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6409 /* check the level */
6412 return control_printer(handle
, command
, p
);
6414 result
= update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6415 if (!W_ERROR_IS_OK(result
))
6418 result
= update_printer_sec(handle
, level
, info
, p
, secdesc_ctr
);
6421 return update_printer_sec(handle
, level
, info
, p
,
6424 return publish_or_unpublish_printer(p
, handle
, info
);
6426 return WERR_UNKNOWN_LEVEL
;
6430 /****************************************************************************
6431 ****************************************************************************/
6433 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6435 POLICY_HND
*handle
= &q_u
->handle
;
6436 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6439 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6443 if (Printer
->notify
.client_connected
==True
) {
6446 if ( Printer
->printer_type
== SPLHND_SERVER
)
6448 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
6449 !get_printer_snum(p
, handle
, &snum
) )
6452 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6455 Printer
->notify
.flags
=0;
6456 Printer
->notify
.options
=0;
6457 Printer
->notify
.localmachine
[0]='\0';
6458 Printer
->notify
.printerlocal
=0;
6459 if (Printer
->notify
.option
)
6460 free_spool_notify_option(&Printer
->notify
.option
);
6461 Printer
->notify
.client_connected
=False
;
6466 /****************************************************************************
6467 ****************************************************************************/
6469 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6471 /* that's an [in out] buffer */
6473 if (!q_u
->buffer
&& (q_u
->offered
!=0)) {
6474 return WERR_INVALID_PARAM
;
6477 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6480 return WERR_INVALID_PARAM
; /* this is what a NT server
6481 returns for AddJob. AddJob
6482 must fail on non-local
6486 /****************************************************************************
6487 ****************************************************************************/
6489 static void fill_job_info_1(JOB_INFO_1
*job_info
, const print_queue_struct
*queue
,
6490 int position
, int snum
,
6491 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
6495 t
=gmtime(&queue
->time
);
6497 job_info
->jobid
=queue
->job
;
6498 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6499 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6500 init_unistr(&job_info
->username
, queue
->fs_user
);
6501 init_unistr(&job_info
->document
, queue
->fs_file
);
6502 init_unistr(&job_info
->datatype
, "RAW");
6503 init_unistr(&job_info
->text_status
, "");
6504 job_info
->status
=nt_printj_status(queue
->status
);
6505 job_info
->priority
=queue
->priority
;
6506 job_info
->position
=position
;
6507 job_info
->totalpages
=queue
->page_count
;
6508 job_info
->pagesprinted
=0;
6510 make_systemtime(&job_info
->submitted
, t
);
6513 /****************************************************************************
6514 ****************************************************************************/
6516 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, const print_queue_struct
*queue
,
6517 int position
, int snum
,
6518 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6519 DEVICEMODE
*devmode
)
6523 t
=gmtime(&queue
->time
);
6525 job_info
->jobid
=queue
->job
;
6527 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6529 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6530 init_unistr(&job_info
->username
, queue
->fs_user
);
6531 init_unistr(&job_info
->document
, queue
->fs_file
);
6532 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6533 init_unistr(&job_info
->datatype
, "RAW");
6534 init_unistr(&job_info
->printprocessor
, "winprint");
6535 init_unistr(&job_info
->parameters
, "");
6536 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6537 init_unistr(&job_info
->text_status
, "");
6539 /* and here the security descriptor */
6541 job_info
->status
=nt_printj_status(queue
->status
);
6542 job_info
->priority
=queue
->priority
;
6543 job_info
->position
=position
;
6544 job_info
->starttime
=0;
6545 job_info
->untiltime
=0;
6546 job_info
->totalpages
=queue
->page_count
;
6547 job_info
->size
=queue
->size
;
6548 make_systemtime(&(job_info
->submitted
), t
);
6549 job_info
->timeelapsed
=0;
6550 job_info
->pagesprinted
=0;
6552 job_info
->devmode
= devmode
;
6557 /****************************************************************************
6558 Enumjobs at level 1.
6559 ****************************************************************************/
6561 static WERROR
enumjobs_level1(const print_queue_struct
*queue
, int snum
,
6562 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6563 RPC_BUFFER
*buffer
, uint32 offered
,
6564 uint32
*needed
, uint32
*returned
)
6568 WERROR result
= WERR_OK
;
6570 info
=SMB_MALLOC_ARRAY(JOB_INFO_1
,*returned
);
6576 for (i
=0; i
<*returned
; i
++)
6577 fill_job_info_1( &info
[i
], &queue
[i
], i
, snum
, ntprinter
);
6579 /* check the required size. */
6580 for (i
=0; i
<*returned
; i
++)
6581 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6583 if (*needed
> offered
) {
6584 result
= WERR_INSUFFICIENT_BUFFER
;
6588 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6589 result
= WERR_NOMEM
;
6593 /* fill the buffer with the structures */
6594 for (i
=0; i
<*returned
; i
++)
6595 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6601 if ( !W_ERROR_IS_OK(result
) )
6607 /****************************************************************************
6608 Enumjobs at level 2.
6609 ****************************************************************************/
6611 static WERROR
enumjobs_level2(const print_queue_struct
*queue
, int snum
,
6612 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6613 RPC_BUFFER
*buffer
, uint32 offered
,
6614 uint32
*needed
, uint32
*returned
)
6616 JOB_INFO_2
*info
= NULL
;
6618 WERROR result
= WERR_OK
;
6619 DEVICEMODE
*devmode
= NULL
;
6621 if ( !(info
= SMB_MALLOC_ARRAY(JOB_INFO_2
,*returned
)) ) {
6626 /* this should not be a failure condition if the devmode is NULL */
6628 devmode
= construct_dev_mode(lp_const_servicename(snum
));
6630 for (i
=0; i
<*returned
; i
++)
6631 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
, devmode
);
6633 /* check the required size. */
6634 for (i
=0; i
<*returned
; i
++)
6635 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6637 if (*needed
> offered
) {
6638 result
= WERR_INSUFFICIENT_BUFFER
;
6642 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6643 result
= WERR_NOMEM
;
6647 /* fill the buffer with the structures */
6648 for (i
=0; i
<*returned
; i
++)
6649 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6652 free_devmode(devmode
);
6655 if ( !W_ERROR_IS_OK(result
) )
6662 /****************************************************************************
6664 ****************************************************************************/
6666 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6668 POLICY_HND
*handle
= &q_u
->handle
;
6669 uint32 level
= q_u
->level
;
6670 RPC_BUFFER
*buffer
= NULL
;
6671 uint32 offered
= q_u
->offered
;
6672 uint32
*needed
= &r_u
->needed
;
6673 uint32
*returned
= &r_u
->returned
;
6675 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6677 print_status_struct prt_status
;
6678 print_queue_struct
*queue
=NULL
;
6680 /* that's an [in out] buffer */
6682 if (!q_u
->buffer
&& (offered
!=0)) {
6683 return WERR_INVALID_PARAM
;
6686 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6687 buffer
= r_u
->buffer
;
6689 DEBUG(4,("_spoolss_enumjobs\n"));
6694 /* lookup the printer snum and tdb entry */
6696 if (!get_printer_snum(p
, handle
, &snum
))
6699 wret
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6700 if ( !W_ERROR_IS_OK(wret
) )
6703 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6704 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6706 if (*returned
== 0) {
6708 free_a_printer(&ntprinter
, 2);
6714 wret
= enumjobs_level1(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6717 wret
= enumjobs_level2(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6721 wret
= WERR_UNKNOWN_LEVEL
;
6726 free_a_printer( &ntprinter
, 2 );
6730 /****************************************************************************
6731 ****************************************************************************/
6733 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6738 /****************************************************************************
6739 ****************************************************************************/
6741 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6743 POLICY_HND
*handle
= &q_u
->handle
;
6744 uint32 jobid
= q_u
->jobid
;
6745 uint32 command
= q_u
->command
;
6747 struct current_user user
;
6749 WERROR errcode
= WERR_BADFUNC
;
6751 if (!get_printer_snum(p
, handle
, &snum
)) {
6755 if (!print_job_exists(lp_const_servicename(snum
), jobid
)) {
6756 return WERR_INVALID_PRINTER_NAME
;
6759 get_current_user(&user
, p
);
6762 case JOB_CONTROL_CANCEL
:
6763 case JOB_CONTROL_DELETE
:
6764 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6768 case JOB_CONTROL_PAUSE
:
6769 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6773 case JOB_CONTROL_RESTART
:
6774 case JOB_CONTROL_RESUME
:
6775 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6780 return WERR_UNKNOWN_LEVEL
;
6786 /****************************************************************************
6787 Enumerates all printer drivers at level 1.
6788 ****************************************************************************/
6790 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6795 fstring
*list
= NULL
;
6796 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6797 DRIVER_INFO_1
*driver_info_1
=NULL
;
6798 WERROR result
= WERR_OK
;
6802 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6804 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6805 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6807 if(ndrivers
== -1) {
6808 SAFE_FREE(driver_info_1
);
6813 if((driver_info_1
=SMB_REALLOC_ARRAY(driver_info_1
, DRIVER_INFO_1
, *returned
+ndrivers
)) == NULL
) {
6814 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6820 for (i
=0; i
<ndrivers
; i
++) {
6822 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6823 ZERO_STRUCT(driver
);
6824 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6825 architecture
, version
);
6826 if (!W_ERROR_IS_OK(status
)) {
6828 SAFE_FREE(driver_info_1
);
6831 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6832 free_a_printer_driver(driver
, 3);
6835 *returned
+=ndrivers
;
6839 /* check the required size. */
6840 for (i
=0; i
<*returned
; i
++) {
6841 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6842 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6845 if (*needed
> offered
) {
6846 result
= WERR_INSUFFICIENT_BUFFER
;
6850 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6851 result
= WERR_NOMEM
;
6855 /* fill the buffer with the driver structures */
6856 for (i
=0; i
<*returned
; i
++) {
6857 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6858 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6862 SAFE_FREE(driver_info_1
);
6864 if ( !W_ERROR_IS_OK(result
) )
6870 /****************************************************************************
6871 Enumerates all printer drivers at level 2.
6872 ****************************************************************************/
6874 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6879 fstring
*list
= NULL
;
6880 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6881 DRIVER_INFO_2
*driver_info_2
=NULL
;
6882 WERROR result
= WERR_OK
;
6886 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6888 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6889 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6891 if(ndrivers
== -1) {
6892 SAFE_FREE(driver_info_2
);
6897 if((driver_info_2
=SMB_REALLOC_ARRAY(driver_info_2
, DRIVER_INFO_2
, *returned
+ndrivers
)) == NULL
) {
6898 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6904 for (i
=0; i
<ndrivers
; i
++) {
6907 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6908 ZERO_STRUCT(driver
);
6909 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6910 architecture
, version
);
6911 if (!W_ERROR_IS_OK(status
)) {
6913 SAFE_FREE(driver_info_2
);
6916 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6917 free_a_printer_driver(driver
, 3);
6920 *returned
+=ndrivers
;
6924 /* check the required size. */
6925 for (i
=0; i
<*returned
; i
++) {
6926 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6927 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6930 if (*needed
> offered
) {
6931 result
= WERR_INSUFFICIENT_BUFFER
;
6935 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6936 result
= WERR_NOMEM
;
6940 /* fill the buffer with the form structures */
6941 for (i
=0; i
<*returned
; i
++) {
6942 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6943 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6947 SAFE_FREE(driver_info_2
);
6949 if ( !W_ERROR_IS_OK(result
) )
6955 /****************************************************************************
6956 Enumerates all printer drivers at level 3.
6957 ****************************************************************************/
6959 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6964 fstring
*list
= NULL
;
6965 DRIVER_INFO_3
*driver_info_3
=NULL
;
6966 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6967 WERROR result
= WERR_OK
;
6971 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6973 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6974 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6976 if(ndrivers
== -1) {
6977 SAFE_FREE(driver_info_3
);
6982 if((driver_info_3
=SMB_REALLOC_ARRAY(driver_info_3
, DRIVER_INFO_3
, *returned
+ndrivers
)) == NULL
) {
6983 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6989 for (i
=0; i
<ndrivers
; i
++) {
6992 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6993 ZERO_STRUCT(driver
);
6994 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6995 architecture
, version
);
6996 if (!W_ERROR_IS_OK(status
)) {
6998 SAFE_FREE(driver_info_3
);
7001 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
7002 free_a_printer_driver(driver
, 3);
7005 *returned
+=ndrivers
;
7009 /* check the required size. */
7010 for (i
=0; i
<*returned
; i
++) {
7011 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
7012 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
7015 if (*needed
> offered
) {
7016 result
= WERR_INSUFFICIENT_BUFFER
;
7020 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7021 result
= WERR_NOMEM
;
7025 /* fill the buffer with the driver structures */
7026 for (i
=0; i
<*returned
; i
++) {
7027 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
7028 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
7032 for (i
=0; i
<*returned
; i
++) {
7033 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
7036 SAFE_FREE(driver_info_3
);
7038 if ( !W_ERROR_IS_OK(result
) )
7044 /****************************************************************************
7045 Enumerates all printer drivers.
7046 ****************************************************************************/
7048 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
7050 uint32 level
= q_u
->level
;
7051 RPC_BUFFER
*buffer
= NULL
;
7052 uint32 offered
= q_u
->offered
;
7053 uint32
*needed
= &r_u
->needed
;
7054 uint32
*returned
= &r_u
->returned
;
7057 fstring architecture
;
7059 /* that's an [in out] buffer */
7061 if (!q_u
->buffer
&& (offered
!=0)) {
7062 return WERR_INVALID_PARAM
;
7065 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7066 buffer
= r_u
->buffer
;
7068 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7073 unistr2_to_ascii(architecture
, &q_u
->environment
, sizeof(architecture
)-1);
7074 unistr2_to_ascii(servername
, &q_u
->name
, sizeof(servername
)-1);
7076 if ( !is_myname_or_ipaddr( servername
) )
7077 return WERR_UNKNOWN_PRINTER_DRIVER
;
7081 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
7083 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
7085 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
7087 return WERR_UNKNOWN_LEVEL
;
7091 /****************************************************************************
7092 ****************************************************************************/
7094 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
7096 form
->flag
=list
->flag
;
7097 init_unistr(&form
->name
, list
->name
);
7098 form
->width
=list
->width
;
7099 form
->length
=list
->length
;
7100 form
->left
=list
->left
;
7101 form
->top
=list
->top
;
7102 form
->right
=list
->right
;
7103 form
->bottom
=list
->bottom
;
7106 /****************************************************************************
7107 ****************************************************************************/
7109 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
7111 uint32 level
= q_u
->level
;
7112 RPC_BUFFER
*buffer
= NULL
;
7113 uint32 offered
= q_u
->offered
;
7114 uint32
*needed
= &r_u
->needed
;
7115 uint32
*numofforms
= &r_u
->numofforms
;
7116 uint32 numbuiltinforms
;
7118 nt_forms_struct
*list
=NULL
;
7119 nt_forms_struct
*builtinlist
=NULL
;
7124 /* that's an [in out] buffer */
7126 if (!q_u
->buffer
&& (offered
!=0) ) {
7127 return WERR_INVALID_PARAM
;
7130 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7131 buffer
= r_u
->buffer
;
7133 DEBUG(4,("_spoolss_enumforms\n"));
7134 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7135 DEBUGADD(5,("Info level [%d]\n", level
));
7137 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
7138 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
7139 *numofforms
= get_ntforms(&list
);
7140 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
7141 *numofforms
+= numbuiltinforms
;
7143 if (*numofforms
== 0) {
7144 SAFE_FREE(builtinlist
);
7146 return WERR_NO_MORE_ITEMS
;
7151 if ((forms_1
=SMB_MALLOC_ARRAY(FORM_1
, *numofforms
)) == NULL
) {
7152 SAFE_FREE(builtinlist
);
7158 /* construct the list of form structures */
7159 for (i
=0; i
<numbuiltinforms
; i
++) {
7160 DEBUGADD(6,("Filling form number [%d]\n",i
));
7161 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
7164 SAFE_FREE(builtinlist
);
7166 for (; i
<*numofforms
; i
++) {
7167 DEBUGADD(6,("Filling form number [%d]\n",i
));
7168 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
7173 /* check the required size. */
7174 for (i
=0; i
<numbuiltinforms
; i
++) {
7175 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7176 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7178 for (; i
<*numofforms
; i
++) {
7179 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7180 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7183 *needed
=buffer_size
;
7185 if (*needed
> offered
) {
7188 return WERR_INSUFFICIENT_BUFFER
;
7191 if (!rpcbuf_alloc_size(buffer
, buffer_size
)){
7197 /* fill the buffer with the form structures */
7198 for (i
=0; i
<numbuiltinforms
; i
++) {
7199 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7200 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7202 for (; i
<*numofforms
; i
++) {
7203 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7204 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7213 SAFE_FREE(builtinlist
);
7214 return WERR_UNKNOWN_LEVEL
;
7218 /****************************************************************************
7219 ****************************************************************************/
7221 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
7223 uint32 level
= q_u
->level
;
7224 UNISTR2
*uni_formname
= &q_u
->formname
;
7225 RPC_BUFFER
*buffer
= NULL
;
7226 uint32 offered
= q_u
->offered
;
7227 uint32
*needed
= &r_u
->needed
;
7229 nt_forms_struct
*list
=NULL
;
7230 nt_forms_struct builtin_form
;
7235 int numofforms
=0, i
=0;
7237 /* that's an [in out] buffer */
7239 if (!q_u
->buffer
&& (offered
!=0)) {
7240 return WERR_INVALID_PARAM
;
7243 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7244 buffer
= r_u
->buffer
;
7246 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
7248 DEBUG(4,("_spoolss_getform\n"));
7249 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7250 DEBUGADD(5,("Info level [%d]\n", level
));
7252 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
7253 if (!foundBuiltin
) {
7254 numofforms
= get_ntforms(&list
);
7255 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
7257 if (numofforms
== 0)
7264 fill_form_1(&form_1
, &builtin_form
);
7267 /* Check if the requested name is in the list of form structures */
7268 for (i
=0; i
<numofforms
; i
++) {
7270 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
7272 if (strequal(form_name
, list
[i
].name
)) {
7273 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
7274 fill_form_1(&form_1
, &list
[i
]);
7280 if (i
== numofforms
) {
7284 /* check the required size. */
7286 *needed
=spoolss_size_form_1(&form_1
);
7288 if (*needed
> offered
)
7289 return WERR_INSUFFICIENT_BUFFER
;
7291 if (!rpcbuf_alloc_size(buffer
, buffer_size
))
7294 /* fill the buffer with the form structures */
7295 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
7296 smb_io_form_1("", buffer
, &form_1
, 0);
7302 return WERR_UNKNOWN_LEVEL
;
7306 /****************************************************************************
7307 ****************************************************************************/
7309 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
7311 init_unistr(&port
->port_name
, name
);
7314 /****************************************************************************
7315 TODO: This probably needs distinguish between TCP/IP and Local ports
7317 ****************************************************************************/
7319 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
7321 init_unistr(&port
->port_name
, name
);
7322 init_unistr(&port
->monitor_name
, "Local Monitor");
7323 init_unistr(&port
->description
, SPL_LOCAL_PORT
);
7324 port
->port_type
=PORT_TYPE_WRITE
;
7329 /****************************************************************************
7330 wrapper around the enumer ports command
7331 ****************************************************************************/
7333 WERROR
enumports_hook( int *count
, char ***lines
)
7335 char *cmd
= lp_enumports_cmd();
7345 /* if no hook then just fill in the default port */
7348 qlines
= SMB_MALLOC_ARRAY( char*, 2 );
7349 qlines
[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME
);
7354 /* we have a valid enumport command */
7356 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
7358 DEBUG(10,("Running [%s]\n", command
));
7359 ret
= smbrun(command
, &fd
);
7360 DEBUG(10,("Returned [%d]\n", ret
));
7365 return WERR_ACCESS_DENIED
;
7369 qlines
= fd_lines_load(fd
, &numlines
, 0);
7370 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7380 /****************************************************************************
7382 ****************************************************************************/
7384 static WERROR
enumports_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7386 PORT_INFO_1
*ports
=NULL
;
7388 WERROR result
= WERR_OK
;
7389 char **qlines
= NULL
;
7392 result
= enumports_hook( &numlines
, &qlines
);
7393 if (!W_ERROR_IS_OK(result
)) {
7394 file_lines_free(qlines
);
7399 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_1
, numlines
)) == NULL
) {
7400 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7401 dos_errstr(WERR_NOMEM
)));
7402 file_lines_free(qlines
);
7406 for (i
=0; i
<numlines
; i
++) {
7407 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7408 fill_port_1(&ports
[i
], qlines
[i
]);
7411 file_lines_free(qlines
);
7413 *returned
= numlines
;
7415 /* check the required size. */
7416 for (i
=0; i
<*returned
; i
++) {
7417 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7418 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7421 if (*needed
> offered
) {
7422 result
= WERR_INSUFFICIENT_BUFFER
;
7426 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7427 result
= WERR_NOMEM
;
7431 /* fill the buffer with the ports structures */
7432 for (i
=0; i
<*returned
; i
++) {
7433 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7434 smb_io_port_1("", buffer
, &ports
[i
], 0);
7440 if ( !W_ERROR_IS_OK(result
) )
7446 /****************************************************************************
7448 ****************************************************************************/
7450 static WERROR
enumports_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7452 PORT_INFO_2
*ports
=NULL
;
7454 WERROR result
= WERR_OK
;
7455 char **qlines
= NULL
;
7458 result
= enumports_hook( &numlines
, &qlines
);
7459 if ( !W_ERROR_IS_OK(result
)) {
7460 file_lines_free(qlines
);
7465 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_2
, numlines
)) == NULL
) {
7466 file_lines_free(qlines
);
7470 for (i
=0; i
<numlines
; i
++) {
7471 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7472 fill_port_2(&(ports
[i
]), qlines
[i
]);
7476 file_lines_free(qlines
);
7478 *returned
= numlines
;
7480 /* check the required size. */
7481 for (i
=0; i
<*returned
; i
++) {
7482 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7483 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7486 if (*needed
> offered
) {
7487 result
= WERR_INSUFFICIENT_BUFFER
;
7491 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7492 result
= WERR_NOMEM
;
7496 /* fill the buffer with the ports structures */
7497 for (i
=0; i
<*returned
; i
++) {
7498 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7499 smb_io_port_2("", buffer
, &ports
[i
], 0);
7505 if ( !W_ERROR_IS_OK(result
) )
7511 /****************************************************************************
7513 ****************************************************************************/
7515 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7517 uint32 level
= q_u
->level
;
7518 RPC_BUFFER
*buffer
= NULL
;
7519 uint32 offered
= q_u
->offered
;
7520 uint32
*needed
= &r_u
->needed
;
7521 uint32
*returned
= &r_u
->returned
;
7523 /* that's an [in out] buffer */
7525 if (!q_u
->buffer
&& (offered
!=0)) {
7526 return WERR_INVALID_PARAM
;
7529 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7530 buffer
= r_u
->buffer
;
7532 DEBUG(4,("_spoolss_enumports\n"));
7539 return enumports_level_1(buffer
, offered
, needed
, returned
);
7541 return enumports_level_2(buffer
, offered
, needed
, returned
);
7543 return WERR_UNKNOWN_LEVEL
;
7547 /****************************************************************************
7548 ****************************************************************************/
7550 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7551 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7552 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7553 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7556 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7559 WERROR err
= WERR_OK
;
7561 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7562 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7566 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7567 if (!convert_printer_info(info
, printer
, 2)) {
7568 free_a_printer(&printer
, 2);
7572 /* check to see if the printer already exists */
7574 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7575 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7576 printer
->info_2
->sharename
));
7577 free_a_printer(&printer
, 2);
7578 return WERR_PRINTER_ALREADY_EXISTS
;
7581 /* FIXME!!! smbd should check to see if the driver is installed before
7582 trying to add a printer like this --jerry */
7584 if (*lp_addprinter_cmd() ) {
7585 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
7586 free_a_printer(&printer
,2);
7587 return WERR_ACCESS_DENIED
;
7590 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7591 "smb.conf parameter \"addprinter command\" is defined. This"
7592 "parameter must exist for this call to succeed\n",
7593 printer
->info_2
->sharename
));
7596 /* use our primary netbios name since get_a_printer() will convert
7597 it to what the client expects on a case by case basis */
7599 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7600 printer
->info_2
->sharename
);
7603 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7604 free_a_printer(&printer
,2);
7605 return WERR_ACCESS_DENIED
;
7608 /* you must be a printer admin to add a new printer */
7609 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7610 free_a_printer(&printer
,2);
7611 return WERR_ACCESS_DENIED
;
7615 * Do sanity check on the requested changes for Samba.
7618 if (!check_printer_ok(printer
->info_2
, snum
)) {
7619 free_a_printer(&printer
,2);
7620 return WERR_INVALID_PARAM
;
7624 * When a printer is created, the drivername bound to the printer is used
7625 * to lookup previously saved driver initialization info, which is then
7626 * bound to the new printer, simulating what happens in the Windows arch.
7631 set_driver_init(printer
, 2);
7635 /* A valid devmode was included, convert and link it
7637 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7639 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7640 &printer
->info_2
->devmode
))
7644 /* write the ASCII on disk */
7645 err
= mod_a_printer(printer
, 2);
7646 if (!W_ERROR_IS_OK(err
)) {
7647 free_a_printer(&printer
,2);
7651 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7652 /* Handle open failed - remove addition. */
7653 del_a_printer(printer
->info_2
->sharename
);
7654 free_a_printer(&printer
,2);
7655 return WERR_ACCESS_DENIED
;
7658 update_c_setprinter(False
);
7659 free_a_printer(&printer
,2);
7664 /****************************************************************************
7665 ****************************************************************************/
7667 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7669 UNISTR2
*uni_srv_name
= q_u
->server_name
;
7670 uint32 level
= q_u
->level
;
7671 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7672 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7673 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7674 uint32 user_switch
= q_u
->user_switch
;
7675 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7676 POLICY_HND
*handle
= &r_u
->handle
;
7680 /* we don't handle yet */
7681 /* but I know what to do ... */
7682 return WERR_UNKNOWN_LEVEL
;
7684 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7686 user_switch
, user
, handle
);
7688 return WERR_UNKNOWN_LEVEL
;
7692 /****************************************************************************
7693 ****************************************************************************/
7695 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7697 uint32 level
= q_u
->level
;
7698 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7699 WERROR err
= WERR_OK
;
7700 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7701 struct current_user user
;
7702 fstring driver_name
;
7705 ZERO_STRUCT(driver
);
7707 get_current_user(&user
, p
);
7709 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7714 DEBUG(5,("Cleaning driver's information\n"));
7715 err
= clean_up_driver_struct(driver
, level
, &user
);
7716 if (!W_ERROR_IS_OK(err
))
7719 DEBUG(5,("Moving driver to final destination\n"));
7720 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(driver
, level
, &user
, &err
)) ) {
7724 if (add_a_printer_driver(driver
, level
)!=0) {
7725 err
= WERR_ACCESS_DENIED
;
7730 * I think this is where he DrvUpgradePrinter() hook would be
7731 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7732 * server. Right now, we just need to send ourselves a message
7733 * to update each printer bound to this driver. --jerry
7736 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7737 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7742 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7743 * decide if the driver init data should be deleted. The rules are:
7744 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7745 * 2) delete init data only if there is no 2k/Xp driver
7746 * 3) always delete init data
7747 * The generalized rule is always use init data from the highest order driver.
7748 * It is necessary to follow the driver install by an initialization step to
7749 * finish off this process.
7752 version
= driver
.info_3
->cversion
;
7753 else if (level
== 6)
7754 version
= driver
.info_6
->version
;
7759 * 9x printer driver - never delete init data
7762 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7767 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7768 * there is no 2k/Xp driver init data for this driver name.
7772 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7774 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7776 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7778 if (!del_driver_init(driver_name
))
7779 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7782 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7784 free_a_printer_driver(driver1
,3);
7785 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7792 * 2k or Xp printer driver - always delete init data
7795 if (!del_driver_init(driver_name
))
7796 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7800 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7806 free_a_printer_driver(driver
, level
);
7810 /********************************************************************
7811 * spoolss_addprinterdriverex
7812 ********************************************************************/
7814 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7816 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7817 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7820 * we only support the semantics of AddPrinterDriver()
7821 * i.e. only copy files that are newer than existing ones
7824 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7825 return WERR_ACCESS_DENIED
;
7827 ZERO_STRUCT(q_u_local
);
7828 ZERO_STRUCT(r_u_local
);
7830 /* just pass the information off to _spoolss_addprinterdriver() */
7831 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7832 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7833 q_u_local
.level
= q_u
->level
;
7834 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7836 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7839 /****************************************************************************
7840 ****************************************************************************/
7842 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7844 init_unistr(&info
->name
, name
);
7847 /****************************************************************************
7848 ****************************************************************************/
7850 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7856 const char *short_archi
;
7857 DRIVER_DIRECTORY_1
*info
=NULL
;
7858 WERROR result
= WERR_OK
;
7860 unistr2_to_ascii(servername
, name
, sizeof(servername
)-1);
7861 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7863 /* check for beginning double '\'s and that the server
7866 pservername
= servername
;
7867 if ( *pservername
== '\\' && strlen(servername
)>2 ) {
7871 if ( !is_myname_or_ipaddr( pservername
) )
7872 return WERR_INVALID_PARAM
;
7874 if (!(short_archi
= get_short_archi(long_archi
)))
7875 return WERR_INVALID_ENVIRONMENT
;
7877 if((info
=SMB_MALLOC_P(DRIVER_DIRECTORY_1
)) == NULL
)
7880 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", pservername
, short_archi
);
7882 DEBUG(4,("printer driver directory: [%s]\n", path
));
7884 fill_driverdir_1(info
, path
);
7886 *needed
+= spoolss_size_driverdir_info_1(info
);
7888 if (*needed
> offered
) {
7889 result
= WERR_INSUFFICIENT_BUFFER
;
7893 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7894 result
= WERR_NOMEM
;
7898 smb_io_driverdir_1("", buffer
, info
, 0);
7906 /****************************************************************************
7907 ****************************************************************************/
7909 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7911 UNISTR2
*name
= &q_u
->name
;
7912 UNISTR2
*uni_environment
= &q_u
->environment
;
7913 uint32 level
= q_u
->level
;
7914 RPC_BUFFER
*buffer
= NULL
;
7915 uint32 offered
= q_u
->offered
;
7916 uint32
*needed
= &r_u
->needed
;
7918 /* that's an [in out] buffer */
7920 if (!q_u
->buffer
&& (offered
!=0)) {
7921 return WERR_INVALID_PARAM
;
7924 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7925 buffer
= r_u
->buffer
;
7927 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7933 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7935 return WERR_UNKNOWN_LEVEL
;
7939 /****************************************************************************
7940 ****************************************************************************/
7942 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7944 POLICY_HND
*handle
= &q_u
->handle
;
7945 uint32 idx
= q_u
->index
;
7946 uint32 in_value_len
= q_u
->valuesize
;
7947 uint32 in_data_len
= q_u
->datasize
;
7948 uint32
*out_max_value_len
= &r_u
->valuesize
;
7949 uint16
**out_value
= &r_u
->value
;
7950 uint32
*out_value_len
= &r_u
->realvaluesize
;
7951 uint32
*out_type
= &r_u
->type
;
7952 uint32
*out_max_data_len
= &r_u
->datasize
;
7953 uint8
**data_out
= &r_u
->data
;
7954 uint32
*out_data_len
= &r_u
->realdatasize
;
7956 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7958 uint32 biggest_valuesize
;
7959 uint32 biggest_datasize
;
7961 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7964 REGISTRY_VALUE
*val
= NULL
;
7965 NT_PRINTER_DATA
*p_data
;
7966 int i
, key_index
, num_values
;
7971 *out_max_data_len
= 0;
7975 DEBUG(5,("spoolss_enumprinterdata\n"));
7978 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7982 if (!get_printer_snum(p
,handle
, &snum
))
7985 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7986 if (!W_ERROR_IS_OK(result
))
7989 p_data
= printer
->info_2
->data
;
7990 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7995 * The NT machine wants to know the biggest size of value and data
7997 * cf: MSDN EnumPrinterData remark section
8000 if ( !in_value_len
&& !in_data_len
&& (key_index
!= -1) )
8002 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8004 biggest_valuesize
= 0;
8005 biggest_datasize
= 0;
8007 num_values
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
8009 for ( i
=0; i
<num_values
; i
++ )
8011 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
8013 name_length
= strlen(val
->valuename
);
8014 if ( strlen(val
->valuename
) > biggest_valuesize
)
8015 biggest_valuesize
= name_length
;
8017 if ( val
->size
> biggest_datasize
)
8018 biggest_datasize
= val
->size
;
8020 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
8024 /* the value is an UNICODE string but real_value_size is the length
8025 in bytes including the trailing 0 */
8027 *out_value_len
= 2 * (1+biggest_valuesize
);
8028 *out_data_len
= biggest_datasize
;
8030 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
8036 * the value len is wrong in NT sp3
8037 * that's the number of bytes not the number of unicode chars
8040 if ( key_index
!= -1 )
8041 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, idx
);
8046 /* out_value should default to "" or else NT4 has
8047 problems unmarshalling the response */
8049 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
8052 if((*out_value
=(uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
8054 result
= WERR_NOMEM
;
8057 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
8063 /* the data is counted in bytes */
8065 *out_max_data_len
= in_data_len
;
8066 *out_data_len
= in_data_len
;
8068 /* only allocate when given a non-zero data_len */
8070 if ( in_data_len
&& ((*data_out
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
8072 result
= WERR_NOMEM
;
8076 result
= WERR_NO_MORE_ITEMS
;
8082 * - counted in bytes in the request
8083 * - counted in UNICODE chars in the max reply
8084 * - counted in bytes in the real size
8086 * take a pause *before* coding not *during* coding
8090 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
8092 if ( (*out_value
= (uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
8094 result
= WERR_NOMEM
;
8098 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), (size_t)in_value_len
, 0);
8106 *out_type
= regval_type( val
);
8108 /* data - counted in bytes */
8110 *out_max_data_len
= in_data_len
;
8111 if ( in_data_len
&& (*data_out
= (uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
8113 result
= WERR_NOMEM
;
8116 data_len
= regval_size(val
);
8117 if ( *data_out
&& data_len
)
8118 memcpy( *data_out
, regval_data_p(val
), data_len
);
8119 *out_data_len
= data_len
;
8123 free_a_printer(&printer
, 2);
8127 /****************************************************************************
8128 ****************************************************************************/
8130 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
8132 POLICY_HND
*handle
= &q_u
->handle
;
8133 UNISTR2
*value
= &q_u
->value
;
8134 uint32 type
= q_u
->type
;
8135 uint8
*data
= q_u
->data
;
8136 uint32 real_len
= q_u
->real_len
;
8138 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8140 WERROR status
= WERR_OK
;
8141 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8144 DEBUG(5,("spoolss_setprinterdata\n"));
8147 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8151 if ( Printer
->printer_type
== SPLHND_SERVER
) {
8152 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8153 return WERR_INVALID_PARAM
;
8156 if (!get_printer_snum(p
,handle
, &snum
))
8160 * Access check : NT returns "access denied" if you make a
8161 * SetPrinterData call without the necessary privildge.
8162 * we were originally returning OK if nothing changed
8163 * which made Win2k issue **a lot** of SetPrinterData
8164 * when connecting to a printer --jerry
8167 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8169 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8170 status
= WERR_ACCESS_DENIED
;
8174 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8175 if (!W_ERROR_IS_OK(status
))
8178 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8181 * When client side code sets a magic printer data key, detect it and save
8182 * the current printer data and the magic key's data (its the DEVMODE) for
8183 * future printer/driver initializations.
8185 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
8187 /* Set devmode and printer initialization info */
8188 status
= save_driver_init( printer
, 2, data
, real_len
);
8190 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
8194 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
8195 type
, data
, real_len
);
8196 if ( W_ERROR_IS_OK(status
) )
8197 status
= mod_a_printer(printer
, 2);
8201 free_a_printer(&printer
, 2);
8206 /****************************************************************************
8207 ****************************************************************************/
8209 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
8211 POLICY_HND
*handle
= &q_u
->handle
;
8212 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8215 DEBUG(5,("_spoolss_resetprinter\n"));
8218 * All we do is to check to see if the handle and queue is valid.
8219 * This call really doesn't mean anything to us because we only
8220 * support RAW printing. --jerry
8224 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8228 if (!get_printer_snum(p
,handle
, &snum
))
8232 /* blindly return success */
8237 /****************************************************************************
8238 ****************************************************************************/
8240 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
8242 POLICY_HND
*handle
= &q_u
->handle
;
8243 UNISTR2
*value
= &q_u
->valuename
;
8245 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8247 WERROR status
= WERR_OK
;
8248 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8251 DEBUG(5,("spoolss_deleteprinterdata\n"));
8254 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8258 if (!get_printer_snum(p
, handle
, &snum
))
8261 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8262 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8263 return WERR_ACCESS_DENIED
;
8266 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8267 if (!W_ERROR_IS_OK(status
))
8270 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8272 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
8274 if ( W_ERROR_IS_OK(status
) )
8275 mod_a_printer( printer
, 2 );
8277 free_a_printer(&printer
, 2);
8282 /****************************************************************************
8283 ****************************************************************************/
8285 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
8287 POLICY_HND
*handle
= &q_u
->handle
;
8288 FORM
*form
= &q_u
->form
;
8289 nt_forms_struct tmpForm
;
8291 WERROR status
= WERR_OK
;
8292 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8295 nt_forms_struct
*list
=NULL
;
8296 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8298 DEBUG(5,("spoolss_addform\n"));
8301 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8306 /* forms can be added 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_addform: denied by handle permissions.\n"));
8320 status
= WERR_ACCESS_DENIED
;
8324 /* can't add if builtin */
8326 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8327 status
= WERR_ALREADY_EXISTS
;
8331 count
= get_ntforms(&list
);
8333 if(!add_a_form(&list
, form
, &count
)) {
8334 status
= WERR_NOMEM
;
8338 write_ntforms(&list
, count
);
8341 * ChangeID must always be set if this is a printer
8344 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8345 status
= mod_a_printer(printer
, 2);
8349 free_a_printer(&printer
, 2);
8355 /****************************************************************************
8356 ****************************************************************************/
8358 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
8360 POLICY_HND
*handle
= &q_u
->handle
;
8361 UNISTR2
*form_name
= &q_u
->name
;
8362 nt_forms_struct tmpForm
;
8364 nt_forms_struct
*list
=NULL
;
8365 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8367 WERROR status
= WERR_OK
;
8368 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8370 DEBUG(5,("spoolss_deleteform\n"));
8373 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8377 /* forms can be deleted on printer of on the print server handle */
8379 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8381 if (!get_printer_snum(p
,handle
, &snum
))
8384 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8385 if (!W_ERROR_IS_OK(status
))
8389 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8390 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8391 status
= WERR_ACCESS_DENIED
;
8395 /* can't delete if builtin */
8397 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
8398 status
= WERR_INVALID_PARAM
;
8402 count
= get_ntforms(&list
);
8404 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8408 * ChangeID must always be set if this is a printer
8411 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8412 status
= mod_a_printer(printer
, 2);
8416 free_a_printer(&printer
, 2);
8422 /****************************************************************************
8423 ****************************************************************************/
8425 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8427 POLICY_HND
*handle
= &q_u
->handle
;
8428 FORM
*form
= &q_u
->form
;
8429 nt_forms_struct tmpForm
;
8431 WERROR status
= WERR_OK
;
8432 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8435 nt_forms_struct
*list
=NULL
;
8436 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8438 DEBUG(5,("spoolss_setform\n"));
8441 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8445 /* forms can be modified on printer of on the print server handle */
8447 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8449 if (!get_printer_snum(p
,handle
, &snum
))
8452 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8453 if (!W_ERROR_IS_OK(status
))
8457 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8458 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8459 status
= WERR_ACCESS_DENIED
;
8463 /* can't set if builtin */
8464 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8465 status
= WERR_INVALID_PARAM
;
8469 count
= get_ntforms(&list
);
8470 update_a_form(&list
, form
, count
);
8471 write_ntforms(&list
, count
);
8474 * ChangeID must always be set if this is a printer
8477 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8478 status
= mod_a_printer(printer
, 2);
8483 free_a_printer(&printer
, 2);
8489 /****************************************************************************
8490 enumprintprocessors level 1.
8491 ****************************************************************************/
8493 static WERROR
enumprintprocessors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8495 PRINTPROCESSOR_1
*info_1
=NULL
;
8496 WERROR result
= WERR_OK
;
8498 if((info_1
= SMB_MALLOC_P(PRINTPROCESSOR_1
)) == NULL
)
8503 init_unistr(&info_1
->name
, "winprint");
8505 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8507 if (*needed
> offered
) {
8508 result
= WERR_INSUFFICIENT_BUFFER
;
8512 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8513 result
= WERR_NOMEM
;
8517 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8522 if ( !W_ERROR_IS_OK(result
) )
8528 /****************************************************************************
8529 ****************************************************************************/
8531 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8533 uint32 level
= q_u
->level
;
8534 RPC_BUFFER
*buffer
= NULL
;
8535 uint32 offered
= q_u
->offered
;
8536 uint32
*needed
= &r_u
->needed
;
8537 uint32
*returned
= &r_u
->returned
;
8539 /* that's an [in out] buffer */
8541 if (!q_u
->buffer
&& (offered
!=0)) {
8542 return WERR_INVALID_PARAM
;
8545 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8546 buffer
= r_u
->buffer
;
8548 DEBUG(5,("spoolss_enumprintprocessors\n"));
8551 * Enumerate the print processors ...
8553 * Just reply with "winprint", to keep NT happy
8554 * and I can use my nice printer checker.
8562 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8564 return WERR_UNKNOWN_LEVEL
;
8568 /****************************************************************************
8569 enumprintprocdatatypes level 1.
8570 ****************************************************************************/
8572 static WERROR
enumprintprocdatatypes_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8574 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8575 WERROR result
= WERR_OK
;
8577 if((info_1
= SMB_MALLOC_P(PRINTPROCDATATYPE_1
)) == NULL
)
8582 init_unistr(&info_1
->name
, "RAW");
8584 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8586 if (*needed
> offered
) {
8587 result
= WERR_INSUFFICIENT_BUFFER
;
8591 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8592 result
= WERR_NOMEM
;
8596 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8601 if ( !W_ERROR_IS_OK(result
) )
8607 /****************************************************************************
8608 ****************************************************************************/
8610 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8612 uint32 level
= q_u
->level
;
8613 RPC_BUFFER
*buffer
= NULL
;
8614 uint32 offered
= q_u
->offered
;
8615 uint32
*needed
= &r_u
->needed
;
8616 uint32
*returned
= &r_u
->returned
;
8618 /* that's an [in out] buffer */
8620 if (!q_u
->buffer
&& (offered
!=0)) {
8621 return WERR_INVALID_PARAM
;
8624 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8625 buffer
= r_u
->buffer
;
8627 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8634 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8636 return WERR_UNKNOWN_LEVEL
;
8640 /****************************************************************************
8641 enumprintmonitors level 1.
8642 ****************************************************************************/
8644 static WERROR
enumprintmonitors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8646 PRINTMONITOR_1
*info_1
;
8647 WERROR result
= WERR_OK
;
8650 if((info_1
= SMB_MALLOC_ARRAY(PRINTMONITOR_1
, 2)) == NULL
)
8655 init_unistr(&(info_1
[0].name
), SPL_LOCAL_PORT
);
8656 init_unistr(&(info_1
[1].name
), SPL_TCPIP_PORT
);
8658 for ( i
=0; i
<*returned
; i
++ ) {
8659 *needed
+= spoolss_size_printmonitor_info_1(&info_1
[i
]);
8662 if (*needed
> offered
) {
8663 result
= WERR_INSUFFICIENT_BUFFER
;
8667 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8668 result
= WERR_NOMEM
;
8672 for ( i
=0; i
<*returned
; i
++ ) {
8673 smb_io_printmonitor_info_1("", buffer
, &info_1
[i
], 0);
8679 if ( !W_ERROR_IS_OK(result
) )
8685 /****************************************************************************
8686 enumprintmonitors level 2.
8687 ****************************************************************************/
8689 static WERROR
enumprintmonitors_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8691 PRINTMONITOR_2
*info_2
;
8692 WERROR result
= WERR_OK
;
8695 if((info_2
= SMB_MALLOC_ARRAY(PRINTMONITOR_2
, 2)) == NULL
)
8700 init_unistr( &(info_2
[0].name
), SPL_LOCAL_PORT
);
8701 init_unistr( &(info_2
[0].environment
), "Windows NT X86" );
8702 init_unistr( &(info_2
[0].dll_name
), "localmon.dll" );
8704 init_unistr( &(info_2
[1].name
), SPL_TCPIP_PORT
);
8705 init_unistr( &(info_2
[1].environment
), "Windows NT X86" );
8706 init_unistr( &(info_2
[1].dll_name
), "tcpmon.dll" );
8708 for ( i
=0; i
<*returned
; i
++ ) {
8709 *needed
+= spoolss_size_printmonitor_info_2(&info_2
[i
]);
8712 if (*needed
> offered
) {
8713 result
= WERR_INSUFFICIENT_BUFFER
;
8717 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8718 result
= WERR_NOMEM
;
8722 for ( i
=0; i
<*returned
; i
++ ) {
8723 smb_io_printmonitor_info_2("", buffer
, &info_2
[i
], 0);
8729 if ( !W_ERROR_IS_OK(result
) )
8735 /****************************************************************************
8736 ****************************************************************************/
8738 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8740 uint32 level
= q_u
->level
;
8741 RPC_BUFFER
*buffer
= NULL
;
8742 uint32 offered
= q_u
->offered
;
8743 uint32
*needed
= &r_u
->needed
;
8744 uint32
*returned
= &r_u
->returned
;
8746 /* that's an [in out] buffer */
8748 if (!q_u
->buffer
&& (offered
!=0)) {
8749 return WERR_INVALID_PARAM
;
8752 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8753 buffer
= r_u
->buffer
;
8755 DEBUG(5,("spoolss_enumprintmonitors\n"));
8758 * Enumerate the print monitors ...
8760 * Just reply with "Local Port", to keep NT happy
8761 * and I can use my nice printer checker.
8769 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8771 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8773 return WERR_UNKNOWN_LEVEL
;
8777 /****************************************************************************
8778 ****************************************************************************/
8780 static WERROR
getjob_level_1(print_queue_struct
**queue
, int count
, int snum
,
8781 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8782 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8787 JOB_INFO_1
*info_1
=NULL
;
8788 WERROR result
= WERR_OK
;
8790 info_1
=SMB_MALLOC_P(JOB_INFO_1
);
8792 if (info_1
== NULL
) {
8796 for (i
=0; i
<count
&& found
==False
; i
++) {
8797 if ((*queue
)[i
].job
==(int)jobid
)
8803 /* NT treats not found as bad param... yet another bad choice */
8804 return WERR_INVALID_PARAM
;
8807 fill_job_info_1( info_1
, &((*queue
)[i
-1]), i
, snum
, ntprinter
);
8809 *needed
+= spoolss_size_job_info_1(info_1
);
8811 if (*needed
> offered
) {
8812 result
= WERR_INSUFFICIENT_BUFFER
;
8816 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8817 result
= WERR_NOMEM
;
8821 smb_io_job_info_1("", buffer
, info_1
, 0);
8829 /****************************************************************************
8830 ****************************************************************************/
8832 static WERROR
getjob_level_2(print_queue_struct
**queue
, int count
, int snum
,
8833 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8834 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8841 DEVICEMODE
*devmode
= NULL
;
8842 NT_DEVICEMODE
*nt_devmode
= NULL
;
8844 if ( !(info_2
=SMB_MALLOC_P(JOB_INFO_2
)) )
8847 ZERO_STRUCTP(info_2
);
8849 for ( i
=0; i
<count
&& found
==False
; i
++ )
8851 if ((*queue
)[i
].job
== (int)jobid
)
8856 /* NT treats not found as bad param... yet another bad
8858 result
= WERR_INVALID_PARAM
;
8863 * if the print job does not have a DEVMODE associated with it,
8864 * just use the one for the printer. A NULL devicemode is not
8865 * a failure condition
8868 if ( !(nt_devmode
=print_job_devmode( lp_const_servicename(snum
), jobid
)) )
8869 devmode
= construct_dev_mode(lp_const_servicename(snum
));
8871 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) != NULL
) {
8872 ZERO_STRUCTP( devmode
);
8873 convert_nt_devicemode( devmode
, nt_devmode
);
8877 fill_job_info_2(info_2
, &((*queue
)[i
-1]), i
, snum
, ntprinter
, devmode
);
8879 *needed
+= spoolss_size_job_info_2(info_2
);
8881 if (*needed
> offered
) {
8882 result
= WERR_INSUFFICIENT_BUFFER
;
8886 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8887 result
= WERR_NOMEM
;
8891 smb_io_job_info_2("", buffer
, info_2
, 0);
8896 /* Cleanup allocated memory */
8898 free_job_info_2(info_2
); /* Also frees devmode */
8904 /****************************************************************************
8905 ****************************************************************************/
8907 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8909 POLICY_HND
*handle
= &q_u
->handle
;
8910 uint32 jobid
= q_u
->jobid
;
8911 uint32 level
= q_u
->level
;
8912 RPC_BUFFER
*buffer
= NULL
;
8913 uint32 offered
= q_u
->offered
;
8914 uint32
*needed
= &r_u
->needed
;
8915 WERROR wstatus
= WERR_OK
;
8916 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8919 print_queue_struct
*queue
= NULL
;
8920 print_status_struct prt_status
;
8922 /* that's an [in out] buffer */
8924 if (!q_u
->buffer
&& (offered
!=0)) {
8925 return WERR_INVALID_PARAM
;
8928 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8929 buffer
= r_u
->buffer
;
8931 DEBUG(5,("spoolss_getjob\n"));
8935 if (!get_printer_snum(p
, handle
, &snum
))
8938 wstatus
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8939 if ( !W_ERROR_IS_OK(wstatus
) )
8942 count
= print_queue_status(snum
, &queue
, &prt_status
);
8944 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8945 count
, prt_status
.status
, prt_status
.message
));
8949 wstatus
= getjob_level_1(&queue
, count
, snum
, ntprinter
, jobid
,
8950 buffer
, offered
, needed
);
8953 wstatus
= getjob_level_2(&queue
, count
, snum
, ntprinter
, jobid
,
8954 buffer
, offered
, needed
);
8957 wstatus
= WERR_UNKNOWN_LEVEL
;
8962 free_a_printer( &ntprinter
, 2 );
8967 /********************************************************************
8968 spoolss_getprinterdataex
8970 From MSDN documentation of GetPrinterDataEx: pass request
8971 to GetPrinterData if key is "PrinterDriverData".
8972 ********************************************************************/
8974 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8976 POLICY_HND
*handle
= &q_u
->handle
;
8977 uint32 in_size
= q_u
->size
;
8978 uint32
*type
= &r_u
->type
;
8979 uint32
*out_size
= &r_u
->size
;
8980 uint8
**data
= &r_u
->data
;
8981 uint32
*needed
= &r_u
->needed
;
8982 fstring keyname
, valuename
;
8984 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8986 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8988 WERROR status
= WERR_OK
;
8990 DEBUG(4,("_spoolss_getprinterdataex\n"));
8992 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8993 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8995 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8996 keyname
, valuename
));
8998 /* in case of problem, return some default values */
9002 *out_size
= in_size
;
9005 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9006 status
= WERR_BADFID
;
9010 /* Is the handle to a printer or to the server? */
9012 if (Printer
->printer_type
== SPLHND_SERVER
) {
9013 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9014 status
= WERR_INVALID_PARAM
;
9018 if ( !get_printer_snum(p
,handle
, &snum
) )
9021 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9022 if ( !W_ERROR_IS_OK(status
) )
9025 /* check to see if the keyname is valid */
9026 if ( !strlen(keyname
) ) {
9027 status
= WERR_INVALID_PARAM
;
9031 if ( lookup_printerkey( printer
->info_2
->data
, keyname
) == -1 ) {
9032 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
9033 free_a_printer( &printer
, 2 );
9034 status
= WERR_BADFILE
;
9038 /* When given a new keyname, we should just create it */
9040 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
9042 if (*needed
> *out_size
)
9043 status
= WERR_MORE_DATA
;
9046 if ( !W_ERROR_IS_OK(status
) )
9048 DEBUG(5, ("error: allocating %d\n", *out_size
));
9050 /* reply this param doesn't exist */
9054 if( (*data
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
9055 status
= WERR_NOMEM
;
9064 free_a_printer( &printer
, 2 );
9069 /********************************************************************
9070 * spoolss_setprinterdataex
9071 ********************************************************************/
9073 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
9075 POLICY_HND
*handle
= &q_u
->handle
;
9076 uint32 type
= q_u
->type
;
9077 uint8
*data
= q_u
->data
;
9078 uint32 real_len
= q_u
->real_len
;
9080 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9082 WERROR status
= WERR_OK
;
9083 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9088 DEBUG(4,("_spoolss_setprinterdataex\n"));
9090 /* From MSDN documentation of SetPrinterDataEx: pass request to
9091 SetPrinterData if key is "PrinterDriverData" */
9094 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9098 if ( Printer
->printer_type
== SPLHND_SERVER
) {
9099 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9100 return WERR_INVALID_PARAM
;
9103 if ( !get_printer_snum(p
,handle
, &snum
) )
9107 * Access check : NT returns "access denied" if you make a
9108 * SetPrinterData call without the necessary privildge.
9109 * we were originally returning OK if nothing changed
9110 * which made Win2k issue **a lot** of SetPrinterData
9111 * when connecting to a printer --jerry
9114 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
9116 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9117 return WERR_ACCESS_DENIED
;
9120 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9121 if (!W_ERROR_IS_OK(status
))
9124 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
9125 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
9127 /* check for OID in valuename */
9129 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
9135 /* save the registry data */
9137 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
9139 if ( W_ERROR_IS_OK(status
) )
9141 /* save the OID if one was specified */
9143 fstrcat( keyname
, "\\" );
9144 fstrcat( keyname
, SPOOL_OID_KEY
);
9147 * I'm not checking the status here on purpose. Don't know
9148 * if this is right, but I'm returning the status from the
9149 * previous set_printer_dataex() call. I have no idea if
9150 * this is right. --jerry
9153 set_printer_dataex( printer
, keyname
, valuename
,
9154 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
9157 status
= mod_a_printer(printer
, 2);
9160 free_a_printer(&printer
, 2);
9166 /********************************************************************
9167 * spoolss_deleteprinterdataex
9168 ********************************************************************/
9170 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
9172 POLICY_HND
*handle
= &q_u
->handle
;
9173 UNISTR2
*value
= &q_u
->valuename
;
9174 UNISTR2
*key
= &q_u
->keyname
;
9176 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9178 WERROR status
= WERR_OK
;
9179 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
9180 pstring valuename
, keyname
;
9182 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9185 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9189 if (!get_printer_snum(p
, handle
, &snum
))
9192 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9193 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9194 return WERR_ACCESS_DENIED
;
9197 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9198 if (!W_ERROR_IS_OK(status
))
9201 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
9202 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
9204 status
= delete_printer_dataex( printer
, keyname
, valuename
);
9206 if ( W_ERROR_IS_OK(status
) )
9207 mod_a_printer( printer
, 2 );
9209 free_a_printer(&printer
, 2);
9214 /********************************************************************
9215 * spoolss_enumprinterkey
9216 ********************************************************************/
9219 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
9222 fstring
*keynames
= NULL
;
9223 uint16
*enumkeys
= NULL
;
9226 POLICY_HND
*handle
= &q_u
->handle
;
9227 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9228 NT_PRINTER_DATA
*data
;
9229 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9231 WERROR status
= WERR_BADFILE
;
9234 DEBUG(4,("_spoolss_enumprinterkey\n"));
9237 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9241 if ( !get_printer_snum(p
,handle
, &snum
) )
9244 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9245 if (!W_ERROR_IS_OK(status
))
9248 /* get the list of subkey names */
9250 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
9251 data
= printer
->info_2
->data
;
9253 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
9255 if ( num_keys
== -1 ) {
9256 status
= WERR_BADFILE
;
9260 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
9262 r_u
->needed
= printerkey_len
*2;
9264 if ( q_u
->size
< r_u
->needed
) {
9265 status
= WERR_MORE_DATA
;
9269 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
9270 status
= WERR_NOMEM
;
9276 if ( q_u
->size
< r_u
->needed
)
9277 status
= WERR_MORE_DATA
;
9280 free_a_printer( &printer
, 2 );
9281 SAFE_FREE( keynames
);
9286 /********************************************************************
9287 * spoolss_deleteprinterkey
9288 ********************************************************************/
9290 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
9292 POLICY_HND
*handle
= &q_u
->handle
;
9293 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9295 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9299 DEBUG(5,("spoolss_deleteprinterkey\n"));
9302 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9306 /* if keyname == NULL, return error */
9308 if ( !q_u
->keyname
.buffer
)
9309 return WERR_INVALID_PARAM
;
9311 if (!get_printer_snum(p
, handle
, &snum
))
9314 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9315 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9316 return WERR_ACCESS_DENIED
;
9319 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9320 if (!W_ERROR_IS_OK(status
))
9323 /* delete the key and all subneys */
9325 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
9327 status
= delete_all_printer_data( printer
->info_2
, key
);
9329 if ( W_ERROR_IS_OK(status
) )
9330 status
= mod_a_printer(printer
, 2);
9332 free_a_printer( &printer
, 2 );
9338 /********************************************************************
9339 * spoolss_enumprinterdataex
9340 ********************************************************************/
9342 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9344 POLICY_HND
*handle
= &q_u
->handle
;
9345 uint32 in_size
= q_u
->size
;
9348 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9349 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9350 NT_PRINTER_DATA
*p_data
;
9352 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9357 REGISTRY_VALUE
*val
;
9362 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9365 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9370 * first check for a keyname of NULL or "". Win2k seems to send
9371 * this a lot and we should send back WERR_INVALID_PARAM
9372 * no need to spend time looking up the printer in this case.
9376 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9377 if ( !strlen(key
) ) {
9378 result
= WERR_INVALID_PARAM
;
9382 /* get the printer off of disk */
9384 if (!get_printer_snum(p
,handle
, &snum
))
9387 ZERO_STRUCT(printer
);
9388 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9389 if (!W_ERROR_IS_OK(result
))
9392 /* now look for a match on the key name */
9394 p_data
= printer
->info_2
->data
;
9396 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9397 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9399 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9400 result
= WERR_INVALID_PARAM
;
9407 /* allocate the memory for the array of pointers -- if necessary */
9409 num_entries
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
9412 if ( (enum_values
=TALLOC_ARRAY(p
->mem_ctx
, PRINTER_ENUM_VALUES
, num_entries
)) == NULL
)
9414 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9415 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9416 result
= WERR_NOMEM
;
9420 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9424 * loop through all params and build the array to pass
9425 * back to the client
9428 for ( i
=0; i
<num_entries
; i
++ )
9430 /* lookup the registry value */
9432 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
9433 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9437 value_name
= regval_name( val
);
9438 init_unistr( &enum_values
[i
].valuename
, value_name
);
9439 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9440 enum_values
[i
].type
= regval_type( val
);
9442 data_len
= regval_size( val
);
9444 if ( !(enum_values
[i
].data
= TALLOC_MEMDUP(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9446 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9448 result
= WERR_NOMEM
;
9452 enum_values
[i
].data_len
= data_len
;
9454 /* keep track of the size of the array in bytes */
9456 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9459 /* housekeeping information in the reply */
9461 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9462 * the hand marshalled container size is a multiple
9463 * of 4 bytes for RPC alignment.
9467 needed
+= 4-(needed
% 4);
9470 r_u
->needed
= needed
;
9471 r_u
->returned
= num_entries
;
9473 if (needed
> in_size
) {
9474 result
= WERR_MORE_DATA
;
9478 /* copy data into the reply */
9480 r_u
->ctr
.size
= r_u
->needed
;
9482 r_u
->ctr
.size_of_array
= r_u
->returned
;
9483 r_u
->ctr
.values
= enum_values
;
9489 free_a_printer(&printer
, 2);
9494 /****************************************************************************
9495 ****************************************************************************/
9497 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9499 init_unistr(&info
->name
, name
);
9502 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9503 UNISTR2
*environment
,
9510 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9511 WERROR result
= WERR_OK
;
9513 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9515 if (!get_short_archi(long_archi
))
9516 return WERR_INVALID_ENVIRONMENT
;
9518 if((info
=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1
)) == NULL
)
9521 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9523 fill_printprocessordirectory_1(info
, path
);
9525 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9527 if (*needed
> offered
) {
9528 result
= WERR_INSUFFICIENT_BUFFER
;
9532 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
9533 result
= WERR_INSUFFICIENT_BUFFER
;
9537 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9545 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9547 uint32 level
= q_u
->level
;
9548 RPC_BUFFER
*buffer
= NULL
;
9549 uint32 offered
= q_u
->offered
;
9550 uint32
*needed
= &r_u
->needed
;
9553 /* that's an [in out] buffer */
9555 if (!q_u
->buffer
&& (offered
!=0)) {
9556 return WERR_INVALID_PARAM
;
9559 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
9560 buffer
= r_u
->buffer
;
9562 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9568 result
= getprintprocessordirectory_level_1
9569 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9572 result
= WERR_UNKNOWN_LEVEL
;
9578 /*******************************************************************
9579 Streams the monitor UI DLL name in UNICODE
9580 *******************************************************************/
9582 static WERROR
xcvtcp_monitorui( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9583 RPC_BUFFER
*out
, uint32
*needed
)
9585 const char *dllname
= "tcpmonui.dll";
9587 *needed
= (strlen(dllname
)+1) * 2;
9589 if ( rpcbuf_get_size(out
) < *needed
) {
9590 return WERR_INSUFFICIENT_BUFFER
;
9593 if ( !make_monitorui_buf( out
, dllname
) ) {
9600 /*******************************************************************
9601 Create a new TCP/IP port
9602 *******************************************************************/
9604 static WERROR
xcvtcp_addport( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9605 RPC_BUFFER
*out
, uint32
*needed
)
9607 NT_PORT_DATA_1 port1
;
9610 ZERO_STRUCT( port1
);
9612 /* convert to our internal port data structure */
9614 if ( !convert_port_data_1( &port1
, in
) ) {
9618 /* create the device URI and call the add_port_hook() */
9620 switch ( port1
.protocol
) {
9621 case PORT_PROTOCOL_DIRECT
:
9622 pstr_sprintf( device_uri
, "socket://%s:%d/", port1
.hostaddr
, port1
.port
);
9625 case PORT_PROTOCOL_LPR
:
9626 pstr_sprintf( device_uri
, "lpr://%s/%s", port1
.hostaddr
, port1
.queue
);
9630 return WERR_UNKNOWN_PORT
;
9633 return add_port_hook( token
, port1
.name
, device_uri
);
9636 /*******************************************************************
9637 *******************************************************************/
9639 struct xcv_api_table xcvtcp_cmds
[] = {
9640 { "MonitorUI", xcvtcp_monitorui
},
9641 { "AddPort", xcvtcp_addport
},
9645 static WERROR
process_xcvtcp_command( NT_USER_TOKEN
*token
, const char *command
,
9646 RPC_BUFFER
*inbuf
, RPC_BUFFER
*outbuf
,
9651 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9653 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9654 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9655 return xcvtcp_cmds
[i
].fn( token
, inbuf
, outbuf
, needed
);
9658 return WERR_BADFUNC
;
9661 /*******************************************************************
9662 *******************************************************************/
9663 #if 0 /* don't support management using the "Local Port" monitor */
9665 static WERROR
xcvlocal_monitorui( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9666 RPC_BUFFER
*out
, uint32
*needed
)
9668 const char *dllname
= "localui.dll";
9670 *needed
= (strlen(dllname
)+1) * 2;
9672 if ( rpcbuf_get_size(out
) < *needed
) {
9673 return WERR_INSUFFICIENT_BUFFER
;
9676 if ( !make_monitorui_buf( out
, dllname
)) {
9683 /*******************************************************************
9684 *******************************************************************/
9686 struct xcv_api_table xcvlocal_cmds
[] = {
9687 { "MonitorUI", xcvlocal_monitorui
},
9691 struct xcv_api_table xcvlocal_cmds
[] = {
9698 /*******************************************************************
9699 *******************************************************************/
9701 static WERROR
process_xcvlocal_command( NT_USER_TOKEN
*token
, const char *command
,
9702 RPC_BUFFER
*inbuf
, RPC_BUFFER
*outbuf
,
9707 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9709 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9710 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9711 return xcvlocal_cmds
[i
].fn( token
, inbuf
, outbuf
, needed
);
9713 return WERR_BADFUNC
;
9716 /*******************************************************************
9717 *******************************************************************/
9719 WERROR
_spoolss_xcvdataport(pipes_struct
*p
, SPOOL_Q_XCVDATAPORT
*q_u
, SPOOL_R_XCVDATAPORT
*r_u
)
9721 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9725 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u
->handle
)));
9729 /* Has to be a handle to the TCP/IP port monitor */
9731 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9732 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9736 /* requires administrative access to the server */
9738 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9739 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9740 return WERR_ACCESS_DENIED
;
9743 /* Get the command name. There's numerous commands supported by the
9744 TCPMON interface. */
9746 rpcstr_pull(command
, q_u
->dataname
.buffer
, sizeof(command
),
9747 q_u
->dataname
.uni_str_len
*2, 0);
9749 /* Allocate the outgoing buffer */
9751 rpcbuf_init( &r_u
->outdata
, q_u
->offered
, p
->mem_ctx
);
9753 switch ( Printer
->printer_type
) {
9754 case SPLHND_PORTMON_TCP
:
9755 return process_xcvtcp_command( p
->pipe_user
.nt_user_token
, command
,
9756 &q_u
->indata
, &r_u
->outdata
, &r_u
->needed
);
9757 case SPLHND_PORTMON_LOCAL
:
9758 return process_xcvlocal_command( p
->pipe_user
.nt_user_token
, command
,
9759 &q_u
->indata
, &r_u
->outdata
, &r_u
->needed
);
9762 return WERR_INVALID_PRINT_MONITOR
;