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 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
70 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
73 /* API table for Xcv Monitor functions */
75 struct xcv_api_table
{
77 WERROR(*fn
) (NT_USER_TOKEN
*token
, RPC_BUFFER
*in
, RPC_BUFFER
*out
, uint32
*needed
);
81 /* translate between internal status numbers and NT status numbers */
82 static int nt_printj_status(int v
)
88 return JOB_STATUS_PAUSED
;
90 return JOB_STATUS_SPOOLING
;
92 return JOB_STATUS_PRINTING
;
94 return JOB_STATUS_ERROR
;
96 return JOB_STATUS_DELETING
;
98 return JOB_STATUS_OFFLINE
;
100 return JOB_STATUS_PAPEROUT
;
102 return JOB_STATUS_PRINTED
;
104 return JOB_STATUS_DELETED
;
106 return JOB_STATUS_BLOCKED
;
107 case LPQ_USER_INTERVENTION
:
108 return JOB_STATUS_USER_INTERVENTION
;
113 static int nt_printq_status(int v
)
117 return PRINTER_STATUS_PAUSED
;
126 /****************************************************************************
127 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
128 ****************************************************************************/
130 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
135 SAFE_FREE((*pp
)->ctr
.type
);
139 /***************************************************************************
140 Disconnect from the client
141 ****************************************************************************/
143 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
148 * Tell the specific printing tdb we no longer want messages for this printer
149 * by deregistering our PID.
152 if (!print_notify_deregister_pid(snum
))
153 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
155 /* weird if the test succeds !!! */
156 if (smb_connections
==0) {
157 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
161 result
= rpccli_spoolss_reply_close_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, handle
);
163 if (!W_ERROR_IS_OK(result
))
164 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
165 dos_errstr(result
)));
167 /* if it's the last connection, deconnect the IPC$ share */
168 if (smb_connections
==1) {
170 cli_shutdown( notify_cli_pipe
->cli
);
171 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
173 message_deregister(MSG_PRINTER_NOTIFY2
);
175 /* Tell the connections db we're no longer interested in
176 * printer notify messages. */
178 register_message_flags( False
, FLAG_MSG_PRINT_NOTIFY
);
184 /****************************************************************************
185 Functions to free a printer entry datastruct.
186 ****************************************************************************/
188 static void free_printer_entry(void *ptr
)
190 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
192 if (Printer
->notify
.client_connected
==True
) {
195 if ( Printer
->printer_type
== SPLHND_SERVER
) {
197 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
198 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
199 snum
= print_queue_snum(Printer
->sharename
);
201 srv_spoolss_replycloseprinter(snum
,
202 &Printer
->notify
.client_hnd
);
206 Printer
->notify
.flags
=0;
207 Printer
->notify
.options
=0;
208 Printer
->notify
.localmachine
[0]='\0';
209 Printer
->notify
.printerlocal
=0;
210 free_spool_notify_option(&Printer
->notify
.option
);
211 Printer
->notify
.option
=NULL
;
212 Printer
->notify
.client_connected
=False
;
214 free_nt_devicemode( &Printer
->nt_devmode
);
215 free_a_printer( &Printer
->printer_info
, 2 );
217 talloc_destroy( Printer
->ctx
);
219 /* Remove from the internal list. */
220 DLIST_REMOVE(printers_list
, Printer
);
225 /****************************************************************************
226 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
227 ****************************************************************************/
229 static SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
231 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
236 new_sp
= SMB_MALLOC_P(SPOOL_NOTIFY_OPTION
);
243 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
245 if (!new_sp
->ctr
.type
) {
254 /****************************************************************************
255 find printer index by handle
256 ****************************************************************************/
258 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
260 Printer_entry
*find_printer
= NULL
;
262 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
263 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
270 /****************************************************************************
271 Close printer index by handle.
272 ****************************************************************************/
274 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
276 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
279 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
283 close_policy_hnd(p
, hnd
);
288 /****************************************************************************
289 Delete a printer given a handle.
290 ****************************************************************************/
291 WERROR
delete_printer_hook( NT_USER_TOKEN
*token
, const char *sharename
)
293 char *cmd
= lp_deleteprinter_cmd();
296 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
297 BOOL is_print_op
= False
;
299 /* can't fail if we don't try */
304 pstr_sprintf(command
, "%s \"%s\"", cmd
, sharename
);
307 is_print_op
= user_has_privileges( token
, &se_printop
);
309 DEBUG(10,("Running [%s]\n", command
));
311 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
316 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
317 /* Tell everyone we updated smb.conf. */
318 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
324 /********** END SePrintOperatorPrivlege BLOCK **********/
326 DEBUGADD(10,("returned [%d]\n", ret
));
329 return WERR_BADFID
; /* What to return here? */
331 /* go ahead and re-read the services immediately */
332 reload_services( False
);
334 if ( !share_defined( sharename
) )
335 return WERR_ACCESS_DENIED
;
340 /****************************************************************************
341 Delete a printer given a handle.
342 ****************************************************************************/
344 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
346 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
349 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
354 * It turns out that Windows allows delete printer on a handle
355 * opened by an admin user, then used on a pipe handle created
356 * by an anonymous user..... but they're working on security.... riiight !
360 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
361 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
362 return WERR_ACCESS_DENIED
;
365 /* this does not need a become root since the access check has been
366 done on the handle already */
368 if (del_a_printer( Printer
->sharename
) != 0) {
369 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
373 return delete_printer_hook( p
->pipe_user
.nt_user_token
, Printer
->sharename
);
376 /****************************************************************************
377 Return the snum of a printer corresponding to an handle.
378 ****************************************************************************/
380 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
382 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
385 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
389 switch (Printer
->printer_type
) {
391 DEBUG(4,("short name:%s\n", Printer
->sharename
));
392 *number
= print_queue_snum(Printer
->sharename
);
393 return (*number
!= -1);
401 /****************************************************************************
402 Set printer handle type.
403 Check if it's \\server or \\server\printer
404 ****************************************************************************/
406 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
408 DEBUG(3,("Setting printer type=%s\n", handlename
));
410 if ( strlen(handlename
) < 3 ) {
411 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
415 /* it's a print server */
416 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
417 DEBUGADD(4,("Printer is a print server\n"));
418 Printer
->printer_type
= SPLHND_SERVER
;
420 /* it's a printer (set_printer_hnd_name() will handle port monitors */
422 DEBUGADD(4,("Printer is a printer\n"));
423 Printer
->printer_type
= SPLHND_PRINTER
;
429 /****************************************************************************
430 Set printer handle name.. Accept names like \\server, \\server\printer,
431 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
432 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
433 XcvDataPort() interface.
434 ****************************************************************************/
436 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
439 int n_services
=lp_numservices();
440 char *aprinter
, *printername
;
441 const char *servername
;
444 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
447 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
, (unsigned long)strlen(handlename
)));
449 aprinter
= handlename
;
450 if ( *handlename
== '\\' ) {
451 servername
= handlename
+ 2;
452 if ( (aprinter
= strchr_m( handlename
+2, '\\' )) != NULL
) {
461 /* save the servername to fill in replies on this handle */
463 if ( !is_myname_or_ipaddr( servername
) )
466 fstrcpy( Printer
->servername
, servername
);
468 if ( Printer
->printer_type
== SPLHND_SERVER
)
471 if ( Printer
->printer_type
!= SPLHND_PRINTER
)
474 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
476 /* check for the Port Monitor Interface */
478 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
479 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
480 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
483 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
484 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
485 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
489 /* Search all sharenames first as this is easier than pulling
490 the printer_info_2 off of disk. Don't use find_service() since
491 that calls out to map_username() */
493 /* do another loop to look for printernames */
495 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
497 /* no point going on if this is not a printer */
499 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
502 fstrcpy(sname
, lp_servicename(snum
));
503 if ( strequal( aprinter
, sname
) ) {
508 /* no point looking up the printer object if
509 we aren't allowing printername != sharename */
511 if ( lp_force_printername(snum
) )
514 fstrcpy(sname
, lp_servicename(snum
));
517 result
= get_a_printer( NULL
, &printer
, 2, sname
);
518 if ( !W_ERROR_IS_OK(result
) ) {
519 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
520 sname
, dos_errstr(result
)));
524 /* printername is always returned as \\server\printername */
525 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
526 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
527 printer
->info_2
->printername
));
528 free_a_printer( &printer
, 2);
534 if ( strequal(printername
, aprinter
) ) {
535 free_a_printer( &printer
, 2);
540 DEBUGADD(10, ("printername: %s\n", printername
));
542 free_a_printer( &printer
, 2);
545 free_a_printer( &printer
, 2);
548 DEBUGADD(4,("Printer not found\n"));
552 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
554 fstrcpy(Printer
->sharename
, sname
);
559 /****************************************************************************
560 Find first available printer slot. creates a printer handle for you.
561 ****************************************************************************/
563 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
565 Printer_entry
*new_printer
;
567 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
569 if((new_printer
=SMB_MALLOC_P(Printer_entry
)) == NULL
)
572 ZERO_STRUCTP(new_printer
);
574 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
575 SAFE_FREE(new_printer
);
579 /* Add to the internal list. */
580 DLIST_ADD(printers_list
, new_printer
);
582 new_printer
->notify
.option
=NULL
;
584 if ( !(new_printer
->ctx
= talloc_init("Printer Entry [%p]", hnd
)) ) {
585 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
586 close_printer_handle(p
, hnd
);
590 if (!set_printer_hnd_printertype(new_printer
, name
)) {
591 close_printer_handle(p
, hnd
);
595 if (!set_printer_hnd_name(new_printer
, name
)) {
596 close_printer_handle(p
, hnd
);
600 new_printer
->access_granted
= access_granted
;
602 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
607 /***************************************************************************
608 check to see if the client motify handle is monitoring the notification
609 given by (notify_type, notify_field).
610 **************************************************************************/
612 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
618 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
621 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
625 * Flags should always be zero when the change notify
626 * is registered by the client's spooler. A user Win32 app
627 * might use the flags though instead of the NOTIFY_OPTION_INFO
636 return is_monitoring_event_flags(
637 p
->notify
.flags
, notify_type
, notify_field
);
639 for (i
= 0; i
< option
->count
; i
++) {
641 /* Check match for notify_type */
643 if (option
->ctr
.type
[i
].type
!= notify_type
)
646 /* Check match for field */
648 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
649 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
655 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
656 p
->servername
, p
->sharename
, notify_type
, notify_field
));
661 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
663 static void notify_one_value(struct spoolss_notify_msg
*msg
,
664 SPOOL_NOTIFY_INFO_DATA
*data
,
667 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
668 data
->notify_data
.value
[1] = 0;
671 static void notify_string(struct spoolss_notify_msg
*msg
,
672 SPOOL_NOTIFY_INFO_DATA
*data
,
677 /* The length of the message includes the trailing \0 */
679 init_unistr2(&unistr
, msg
->notify
.data
, UNI_STR_TERMINATE
);
681 data
->notify_data
.data
.length
= msg
->len
* 2;
682 data
->notify_data
.data
.string
= TALLOC_ARRAY(mem_ctx
, uint16
, msg
->len
);
684 if (!data
->notify_data
.data
.string
) {
685 data
->notify_data
.data
.length
= 0;
689 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
692 static void notify_system_time(struct spoolss_notify_msg
*msg
,
693 SPOOL_NOTIFY_INFO_DATA
*data
,
699 if (msg
->len
!= sizeof(time_t)) {
700 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
705 if (!prs_init(&ps
, RPC_MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
706 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
710 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
711 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
716 if (!spoolss_io_system_time("", &ps
, 0, &systime
)) {
721 data
->notify_data
.data
.length
= prs_offset(&ps
);
722 data
->notify_data
.data
.string
= TALLOC(mem_ctx
, prs_offset(&ps
));
723 if (!data
->notify_data
.data
.string
) {
728 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
733 struct notify2_message_table
{
735 void (*fn
)(struct spoolss_notify_msg
*msg
,
736 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
739 static struct notify2_message_table printer_notify_table
[] = {
740 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
741 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
742 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
743 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
744 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
745 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
746 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
747 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
748 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
749 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
750 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
751 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
752 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
753 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
754 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
755 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
756 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
757 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
758 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
761 static struct notify2_message_table job_notify_table
[] = {
762 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
763 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
764 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
765 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
766 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
767 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
768 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
769 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
770 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
771 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
772 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
773 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
774 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
775 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
776 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
777 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
778 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
779 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
780 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
781 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
782 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
783 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
784 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
785 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
789 /***********************************************************************
790 Allocate talloc context for container object
791 **********************************************************************/
793 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
798 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
803 /***********************************************************************
804 release all allocated memory and zero out structure
805 **********************************************************************/
807 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
813 talloc_destroy(ctr
->ctx
);
820 /***********************************************************************
821 **********************************************************************/
823 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
831 /***********************************************************************
832 **********************************************************************/
834 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
836 if ( !ctr
|| !ctr
->msg_groups
)
839 if ( idx
>= ctr
->num_groups
)
842 return &ctr
->msg_groups
[idx
];
846 /***********************************************************************
847 How many groups of change messages do we have ?
848 **********************************************************************/
850 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
855 return ctr
->num_groups
;
858 /***********************************************************************
859 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
860 **********************************************************************/
862 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
864 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
865 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
866 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
872 /* loop over all groups looking for a matching printer name */
874 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
875 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
879 /* add a new group? */
881 if ( i
== ctr
->num_groups
) {
884 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
885 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
888 ctr
->msg_groups
= groups
;
890 /* clear the new entry and set the printer name */
892 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
893 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
896 /* add the change messages; 'i' is the correct index now regardless */
898 msg_grp
= &ctr
->msg_groups
[i
];
902 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
903 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
906 msg_grp
->msgs
= msg_list
;
908 new_slot
= msg_grp
->num_msgs
-1;
909 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
911 /* need to allocate own copy of data */
914 msg_grp
->msgs
[new_slot
].notify
.data
= TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
916 return ctr
->num_groups
;
919 /***********************************************************************
920 Send a change notication message on all handles which have a call
922 **********************************************************************/
924 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
927 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
928 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
929 SPOOLSS_NOTIFY_MSG
*messages
;
930 int sending_msg_count
;
933 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
937 messages
= msg_group
->msgs
;
940 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
944 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
946 /* loop over all printers */
948 for (p
= printers_list
; p
; p
= p
->next
) {
949 SPOOL_NOTIFY_INFO_DATA
*data
;
954 /* Is there notification on this handle? */
956 if ( !p
->notify
.client_connected
)
959 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
961 /* For this printer? Print servers always receive
964 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
965 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
968 DEBUG(10,("Our printer\n"));
970 /* allocate the max entries possible */
972 data
= TALLOC_ARRAY( mem_ctx
, SPOOL_NOTIFY_INFO_DATA
, msg_group
->num_msgs
);
979 /* build the array of change notifications */
981 sending_msg_count
= 0;
983 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
984 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
986 /* Are we monitoring this event? */
988 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
994 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
995 msg
->type
, msg
->field
, p
->sharename
));
998 * if the is a printer notification handle and not a job notification
999 * type, then set the id to 0. Other wise just use what was specified
1002 * When registering change notification on a print server handle
1003 * we always need to send back the id (snum) matching the printer
1004 * for which the change took place. For change notify registered
1005 * on a printer handle, this does not matter and the id should be 0.
1010 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1016 /* Convert unix jobid to smb jobid */
1018 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1019 id
= sysjob_to_jobid(msg
->id
);
1022 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1027 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1030 case PRINTER_NOTIFY_TYPE
:
1031 if ( printer_notify_table
[msg
->field
].fn
)
1032 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1035 case JOB_NOTIFY_TYPE
:
1036 if ( job_notify_table
[msg
->field
].fn
)
1037 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1041 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1048 if ( sending_msg_count
) {
1049 rpccli_spoolss_rrpcn( notify_cli_pipe
, mem_ctx
, &p
->notify
.client_hnd
,
1050 data_len
, data
, p
->notify
.change
, 0 );
1055 DEBUG(8,("send_notify2_changes: Exit...\n"));
1059 /***********************************************************************
1060 **********************************************************************/
1062 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1065 uint32 tv_sec
, tv_usec
;
1068 /* Unpack message */
1070 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1073 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddddd",
1075 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1078 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1079 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1081 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1082 &msg
->len
, &msg
->notify
.data
);
1084 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1085 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1087 tv
->tv_sec
= tv_sec
;
1088 tv
->tv_usec
= tv_usec
;
1091 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1092 msg
->notify
.value
[1]));
1094 dump_data(3, msg
->notify
.data
, msg
->len
);
1099 /********************************************************************
1100 Receive a notify2 message list
1101 ********************************************************************/
1103 static void receive_notify2_message_list(int msg_type
, struct process_id src
,
1104 void *msg
, size_t len
)
1106 size_t msg_count
, i
;
1107 char *buf
= (char *)msg
;
1110 SPOOLSS_NOTIFY_MSG notify
;
1111 SPOOLSS_NOTIFY_MSG_CTR messages
;
1115 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1119 msg_count
= IVAL(buf
, 0);
1122 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1124 if (msg_count
== 0) {
1125 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1129 /* initialize the container */
1131 ZERO_STRUCT( messages
);
1132 notify_msg_ctr_init( &messages
);
1135 * build message groups for each printer identified
1136 * in a change_notify msg. Remember that a PCN message
1137 * includes the handle returned for the srv_spoolss_replyopenprinter()
1138 * call. Therefore messages are grouped according to printer handle.
1141 for ( i
=0; i
<msg_count
; i
++ ) {
1142 struct timeval msg_tv
;
1144 if (msg_ptr
+ 4 - buf
> len
) {
1145 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1149 msg_len
= IVAL(msg_ptr
,0);
1152 if (msg_ptr
+ msg_len
- buf
> len
) {
1153 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1157 /* unpack messages */
1159 ZERO_STRUCT( notify
);
1160 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1163 /* add to correct list in container */
1165 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1167 /* free memory that might have been allocated by notify2_unpack_msg() */
1169 if ( notify
.len
!= 0 )
1170 SAFE_FREE( notify
.notify
.data
);
1173 /* process each group of messages */
1175 num_groups
= notify_msg_ctr_numgroups( &messages
);
1176 for ( i
=0; i
<num_groups
; i
++ )
1177 send_notify2_changes( &messages
, i
);
1182 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1184 notify_msg_ctr_destroy( &messages
);
1189 /********************************************************************
1190 Send a message to ourself about new driver being installed
1191 so we can upgrade the information for each printer bound to this
1193 ********************************************************************/
1195 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1197 int len
= strlen(drivername
);
1202 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1205 message_send_pid(pid_to_procid(sys_getpid()),
1206 MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1211 /**********************************************************************
1212 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1213 over all printers, upgrading ones as necessary
1214 **********************************************************************/
1216 void do_drv_upgrade_printer(int msg_type
, struct process_id src
, void *buf
, size_t len
)
1220 int n_services
= lp_numservices();
1222 len
= MIN(len
,sizeof(drivername
)-1);
1223 strncpy(drivername
, buf
, len
);
1225 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1227 /* Iterate the printer list */
1229 for (snum
=0; snum
<n_services
; snum
++)
1231 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1234 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1236 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1237 if (!W_ERROR_IS_OK(result
))
1240 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1242 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1244 /* all we care about currently is the change_id */
1246 result
= mod_a_printer(printer
, 2);
1247 if (!W_ERROR_IS_OK(result
)) {
1248 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1249 dos_errstr(result
)));
1253 free_a_printer(&printer
, 2);
1260 /********************************************************************
1261 Update the cache for all printq's with a registered client
1263 ********************************************************************/
1265 void update_monitored_printq_cache( void )
1267 Printer_entry
*printer
= printers_list
;
1270 /* loop through all printers and update the cache where
1271 client_connected == True */
1274 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1275 && printer
->notify
.client_connected
)
1277 snum
= print_queue_snum(printer
->sharename
);
1278 print_queue_status( snum
, NULL
, NULL
);
1281 printer
= printer
->next
;
1286 /********************************************************************
1287 Send a message to ourself about new driver being installed
1288 so we can upgrade the information for each printer bound to this
1290 ********************************************************************/
1292 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1294 int len
= strlen(drivername
);
1299 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1302 message_send_pid(pid_to_procid(sys_getpid()),
1303 MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1308 /**********************************************************************
1309 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1310 over all printers, resetting printer data as neessary
1311 **********************************************************************/
1313 void reset_all_printerdata(int msg_type
, struct process_id src
,
1314 void *buf
, size_t len
)
1318 int n_services
= lp_numservices();
1320 len
= MIN( len
, sizeof(drivername
)-1 );
1321 strncpy( drivername
, buf
, len
);
1323 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1325 /* Iterate the printer list */
1327 for ( snum
=0; snum
<n_services
; snum
++ )
1329 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1332 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1334 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1335 if ( !W_ERROR_IS_OK(result
) )
1339 * if the printer is bound to the driver,
1340 * then reset to the new driver initdata
1343 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1345 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1347 if ( !set_driver_init(printer
, 2) ) {
1348 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1349 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1352 result
= mod_a_printer( printer
, 2 );
1353 if ( !W_ERROR_IS_OK(result
) ) {
1354 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1355 get_dos_error_msg(result
)));
1359 free_a_printer( &printer
, 2 );
1368 /********************************************************************
1369 Copy routines used by convert_to_openprinterex()
1370 *******************************************************************/
1372 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1380 DEBUG (8,("dup_devmode\n"));
1382 /* bulk copy first */
1384 d
= TALLOC_MEMDUP(ctx
, devmode
, sizeof(DEVICEMODE
));
1388 /* dup the pointer members separately */
1390 len
= unistrlen(devmode
->devicename
.buffer
);
1392 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1393 if (!d
->devicename
.buffer
) {
1396 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1401 len
= unistrlen(devmode
->formname
.buffer
);
1403 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1404 if (!d
->devicename
.buffer
) {
1407 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1411 d
->dev_private
= TALLOC_MEMDUP(ctx
, devmode
->dev_private
, devmode
->driverextra
);
1412 if (!d
->dev_private
) {
1418 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1420 if (!new_ctr
|| !ctr
)
1423 DEBUG(8,("copy_devmode_ctr\n"));
1425 new_ctr
->size
= ctr
->size
;
1426 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1428 if(ctr
->devmode_ptr
)
1429 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1432 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1434 if (!new_def
|| !def
)
1437 DEBUG(8,("copy_printer_defaults\n"));
1439 new_def
->datatype_ptr
= def
->datatype_ptr
;
1441 if (def
->datatype_ptr
)
1442 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1444 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1446 new_def
->access_required
= def
->access_required
;
1449 /********************************************************************
1450 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1451 * SPOOL_Q_OPEN_PRINTER_EX structure
1452 ********************************************************************/
1454 static WERROR
convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1456 if (!q_u_ex
|| !q_u
)
1459 DEBUG(8,("convert_to_openprinterex\n"));
1461 if ( q_u
->printername
) {
1462 q_u_ex
->printername
= TALLOC_ZERO_P( ctx
, UNISTR2
);
1463 if (q_u_ex
->printername
== NULL
)
1465 copy_unistr2(q_u_ex
->printername
, q_u
->printername
);
1468 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1473 /********************************************************************
1474 * spoolss_open_printer
1476 * called from the spoolss dispatcher
1477 ********************************************************************/
1479 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1481 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1482 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1487 ZERO_STRUCT(q_u_ex
);
1488 ZERO_STRUCT(r_u_ex
);
1490 /* convert the OpenPrinter() call to OpenPrinterEx() */
1492 r_u_ex
.status
= convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1493 if (!W_ERROR_IS_OK(r_u_ex
.status
))
1494 return r_u_ex
.status
;
1496 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1498 /* convert back to OpenPrinter() */
1500 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1505 /********************************************************************
1506 ********************************************************************/
1508 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1510 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1511 POLICY_HND
*handle
= &r_u
->handle
;
1515 Printer_entry
*Printer
=NULL
;
1517 if ( !q_u
->printername
)
1518 return WERR_INVALID_PRINTER_NAME
;
1520 /* some sanity check because you can open a printer or a print server */
1521 /* aka: \\server\printer or \\server */
1523 unistr2_to_ascii(name
, q_u
->printername
, sizeof(name
)-1);
1525 DEBUGADD(3,("checking name: %s\n",name
));
1527 if (!open_printer_hnd(p
, handle
, name
, 0))
1528 return WERR_INVALID_PRINTER_NAME
;
1530 Printer
=find_printer_index_by_hnd(p
, handle
);
1532 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1533 "handle we created for printer %s\n", name
));
1534 close_printer_handle(p
,handle
);
1535 return WERR_INVALID_PRINTER_NAME
;
1539 * First case: the user is opening the print server:
1541 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1542 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1544 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1545 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1546 * or if the user is listed in the smb.conf printer admin parameter.
1548 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1549 * client view printer folder, but does not show the MSAPW.
1551 * Note: this test needs code to check access rights here too. Jeremy
1552 * could you look at this?
1554 * Second case: the user is opening a printer:
1555 * NT doesn't let us connect to a printer if the connecting user
1556 * doesn't have print permission.
1558 * Third case: user is opening a Port Monitor
1559 * access checks same as opening a handle to the print server.
1562 switch (Printer
->printer_type
)
1565 case SPLHND_PORTMON_TCP
:
1566 case SPLHND_PORTMON_LOCAL
:
1567 /* Printserver handles use global struct... */
1571 /* Map standard access rights to object specific access rights */
1573 se_map_standard(&printer_default
->access_required
,
1574 &printserver_std_mapping
);
1576 /* Deny any object specific bits that don't apply to print
1577 servers (i.e printer and job specific bits) */
1579 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1581 if (printer_default
->access_required
&
1582 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1583 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1584 close_printer_handle(p
, handle
);
1585 return WERR_ACCESS_DENIED
;
1588 /* Allow admin access */
1590 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1592 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1594 if (!lp_ms_add_printer_wizard()) {
1595 close_printer_handle(p
, handle
);
1596 return WERR_ACCESS_DENIED
;
1599 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1600 and not a printer admin, then fail */
1602 if ((p
->pipe_user
.ut
.uid
!= 0) &&
1603 !user_has_privileges(p
->pipe_user
.nt_user_token
,
1605 !token_contains_name_in_list(
1606 uidtoname(p
->pipe_user
.ut
.uid
), NULL
,
1607 p
->pipe_user
.nt_user_token
,
1608 lp_printer_admin(snum
))) {
1609 close_printer_handle(p
, handle
);
1610 return WERR_ACCESS_DENIED
;
1613 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1617 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1620 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1621 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1623 /* We fall through to return WERR_OK */
1626 case SPLHND_PRINTER
:
1627 /* NT doesn't let us connect to a printer if the connecting user
1628 doesn't have print permission. */
1630 if (!get_printer_snum(p
, handle
, &snum
)) {
1631 close_printer_handle(p
, handle
);
1635 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1637 /* map an empty access mask to the minimum access mask */
1638 if (printer_default
->access_required
== 0x0)
1639 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1642 * If we are not serving the printer driver for this printer,
1643 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1644 * will keep NT clients happy --jerry
1647 if (lp_use_client_driver(snum
)
1648 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1650 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1653 /* check smb.conf parameters and the the sec_desc */
1655 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1656 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1657 return WERR_ACCESS_DENIED
;
1660 if (!user_ok_token(uidtoname(p
->pipe_user
.ut
.uid
),
1661 p
->pipe_user
.nt_user_token
, snum
) ||
1662 !print_access_check(&p
->pipe_user
, snum
,
1663 printer_default
->access_required
)) {
1664 DEBUG(3, ("access DENIED for printer open\n"));
1665 close_printer_handle(p
, handle
);
1666 return WERR_ACCESS_DENIED
;
1669 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1670 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1671 close_printer_handle(p
, handle
);
1672 return WERR_ACCESS_DENIED
;
1675 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1676 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1678 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1680 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1681 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1686 /* sanity check to prevent programmer error */
1690 Printer
->access_granted
= printer_default
->access_required
;
1693 * If the client sent a devmode in the OpenPrinter() call, then
1694 * save it here in case we get a job submission on this handle
1697 if ( (Printer
->printer_type
!= SPLHND_SERVER
)
1698 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1700 convert_devicemode( Printer
->sharename
, q_u
->printer_default
.devmode_cont
.devmode
,
1701 &Printer
->nt_devmode
);
1704 #if 0 /* JERRY -- I'm doubtful this is really effective */
1705 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1706 optimization in Windows 2000 clients --jerry */
1708 if ( (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1709 && (RA_WIN2K
== get_remote_arch()) )
1711 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1712 sys_usleep( 500000 );
1719 /****************************************************************************
1720 ****************************************************************************/
1722 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1723 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1729 /* allocate memory if needed. Messy because
1730 convert_printer_info is used to update an existing
1731 printer or build a new one */
1733 if ( !printer
->info_2
) {
1734 printer
->info_2
= TALLOC_ZERO_P( printer
, NT_PRINTER_INFO_LEVEL_2
);
1735 if ( !printer
->info_2
) {
1736 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1741 ret
= uni_2_asc_printer_info_2(uni
->info_2
, printer
->info_2
);
1742 printer
->info_2
->setuptime
= time(NULL
);
1750 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1751 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1757 printer
->info_3
=NULL
;
1758 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1762 printer
->info_6
=NULL
;
1763 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1773 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1774 NT_DEVICEMODE
**pp_nt_devmode
)
1776 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1779 * Ensure nt_devmode is a valid pointer
1780 * as we will be overwriting it.
1783 if (nt_devmode
== NULL
) {
1784 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1785 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1789 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1790 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1792 nt_devmode
->specversion
=devmode
->specversion
;
1793 nt_devmode
->driverversion
=devmode
->driverversion
;
1794 nt_devmode
->size
=devmode
->size
;
1795 nt_devmode
->fields
=devmode
->fields
;
1796 nt_devmode
->orientation
=devmode
->orientation
;
1797 nt_devmode
->papersize
=devmode
->papersize
;
1798 nt_devmode
->paperlength
=devmode
->paperlength
;
1799 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1800 nt_devmode
->scale
=devmode
->scale
;
1801 nt_devmode
->copies
=devmode
->copies
;
1802 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1803 nt_devmode
->printquality
=devmode
->printquality
;
1804 nt_devmode
->color
=devmode
->color
;
1805 nt_devmode
->duplex
=devmode
->duplex
;
1806 nt_devmode
->yresolution
=devmode
->yresolution
;
1807 nt_devmode
->ttoption
=devmode
->ttoption
;
1808 nt_devmode
->collate
=devmode
->collate
;
1810 nt_devmode
->logpixels
=devmode
->logpixels
;
1811 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1812 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1813 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1814 nt_devmode
->displayflags
=devmode
->displayflags
;
1815 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1816 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1817 nt_devmode
->icmintent
=devmode
->icmintent
;
1818 nt_devmode
->mediatype
=devmode
->mediatype
;
1819 nt_devmode
->dithertype
=devmode
->dithertype
;
1820 nt_devmode
->reserved1
=devmode
->reserved1
;
1821 nt_devmode
->reserved2
=devmode
->reserved2
;
1822 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1823 nt_devmode
->panningheight
=devmode
->panningheight
;
1826 * Only change private and driverextra if the incoming devmode
1827 * has a new one. JRA.
1830 if ((devmode
->driverextra
!= 0) && (devmode
->dev_private
!= NULL
)) {
1831 SAFE_FREE(nt_devmode
->nt_dev_private
);
1832 nt_devmode
->driverextra
=devmode
->driverextra
;
1833 if((nt_devmode
->nt_dev_private
=SMB_MALLOC_ARRAY(uint8
, nt_devmode
->driverextra
)) == NULL
)
1835 memcpy(nt_devmode
->nt_dev_private
, devmode
->dev_private
, nt_devmode
->driverextra
);
1838 *pp_nt_devmode
= nt_devmode
;
1843 /********************************************************************
1844 * _spoolss_enddocprinter_internal.
1845 ********************************************************************/
1847 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1849 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1853 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1857 if (!get_printer_snum(p
, handle
, &snum
))
1860 Printer
->document_started
=False
;
1861 print_job_end(snum
, Printer
->jobid
,NORMAL_CLOSE
);
1862 /* error codes unhandled so far ... */
1867 /********************************************************************
1868 * api_spoolss_closeprinter
1869 ********************************************************************/
1871 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1873 POLICY_HND
*handle
= &q_u
->handle
;
1875 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1877 if (Printer
&& Printer
->document_started
)
1878 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1880 if (!close_printer_handle(p
, handle
))
1883 /* clear the returned printer handle. Observed behavior
1884 from Win2k server. Don't think this really matters.
1885 Previous code just copied the value of the closed
1888 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1893 /********************************************************************
1894 * api_spoolss_deleteprinter
1896 ********************************************************************/
1898 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1900 POLICY_HND
*handle
= &q_u
->handle
;
1901 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1904 if (Printer
&& Printer
->document_started
)
1905 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1907 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1909 result
= delete_printer_handle(p
, handle
);
1911 update_c_setprinter(False
);
1916 /*******************************************************************
1917 * static function to lookup the version id corresponding to an
1918 * long architecture string
1919 ******************************************************************/
1921 static int get_version_id (char * arch
)
1924 struct table_node archi_table
[]= {
1926 {"Windows 4.0", "WIN40", 0 },
1927 {"Windows NT x86", "W32X86", 2 },
1928 {"Windows NT R4000", "W32MIPS", 2 },
1929 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1930 {"Windows NT PowerPC", "W32PPC", 2 },
1931 {"Windows IA64", "IA64", 3 },
1932 {"Windows x64", "x64", 3 },
1936 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1938 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1939 return (archi_table
[i
].version
);
1945 /********************************************************************
1946 * _spoolss_deleteprinterdriver
1947 ********************************************************************/
1949 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1953 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1954 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1957 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1958 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1960 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1961 and not a printer admin, then fail */
1963 if ( (p
->pipe_user
.ut
.uid
!= 0)
1964 && !user_has_privileges(p
->pipe_user
.nt_user_token
, &se_printop
)
1965 && !token_contains_name_in_list( uidtoname(p
->pipe_user
.ut
.uid
),
1966 NULL
, p
->pipe_user
.nt_user_token
, lp_printer_admin(-1)) )
1968 return WERR_ACCESS_DENIED
;
1971 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1972 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1974 /* check that we have a valid driver name first */
1976 if ((version
=get_version_id(arch
)) == -1)
1977 return WERR_INVALID_ENVIRONMENT
;
1980 ZERO_STRUCT(info_win2k
);
1982 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1984 /* try for Win2k driver if "Windows NT x86" */
1986 if ( version
== 2 ) {
1988 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1989 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1993 /* otherwise it was a failure */
1995 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2001 if (printer_driver_in_use(info
.info_3
)) {
2002 status
= WERR_PRINTER_DRIVER_IN_USE
;
2008 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2010 /* if we get to here, we now have 2 driver info structures to remove */
2011 /* remove the Win2k driver first*/
2013 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &p
->pipe_user
, 3, False
);
2014 free_a_printer_driver( info_win2k
, 3 );
2016 /* this should not have failed---if it did, report to client */
2017 if ( !W_ERROR_IS_OK(status_win2k
) )
2019 status
= status_win2k
;
2025 status
= delete_printer_driver(info
.info_3
, &p
->pipe_user
, version
, False
);
2027 /* if at least one of the deletes succeeded return OK */
2029 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2033 free_a_printer_driver( info
, 3 );
2038 /********************************************************************
2039 * spoolss_deleteprinterdriverex
2040 ********************************************************************/
2042 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
2046 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2047 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2049 uint32 flags
= q_u
->delete_flags
;
2052 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2053 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2055 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2056 and not a printer admin, then fail */
2058 if ( (p
->pipe_user
.ut
.uid
!= 0)
2059 && !user_has_privileges(p
->pipe_user
.nt_user_token
, &se_printop
)
2060 && !token_contains_name_in_list( uidtoname(p
->pipe_user
.ut
.uid
),
2061 NULL
, p
->pipe_user
.nt_user_token
, lp_printer_admin(-1)) )
2063 return WERR_ACCESS_DENIED
;
2066 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2067 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2069 /* check that we have a valid driver name first */
2070 if ((version
=get_version_id(arch
)) == -1) {
2071 /* this is what NT returns */
2072 return WERR_INVALID_ENVIRONMENT
;
2075 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2076 version
= q_u
->version
;
2079 ZERO_STRUCT(info_win2k
);
2081 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2083 if ( !W_ERROR_IS_OK(status
) )
2086 * if the client asked for a specific version,
2087 * or this is something other than Windows NT x86,
2091 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2094 /* try for Win2k driver if "Windows NT x86" */
2097 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2098 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2103 if ( printer_driver_in_use(info
.info_3
) ) {
2104 status
= WERR_PRINTER_DRIVER_IN_USE
;
2109 * we have a couple of cases to consider.
2110 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2111 * then the delete should fail if **any** files overlap with
2113 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2114 * non-overlapping files
2115 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2116 * is set, the do not delete any files
2117 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2120 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2122 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2124 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2125 /* no idea of the correct error here */
2126 status
= WERR_ACCESS_DENIED
;
2131 /* also check for W32X86/3 if necessary; maybe we already have? */
2133 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2134 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2137 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2138 /* no idea of the correct error here */
2139 free_a_printer_driver( info_win2k
, 3 );
2140 status
= WERR_ACCESS_DENIED
;
2144 /* if we get to here, we now have 2 driver info structures to remove */
2145 /* remove the Win2k driver first*/
2147 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &p
->pipe_user
, 3, delete_files
);
2148 free_a_printer_driver( info_win2k
, 3 );
2150 /* this should not have failed---if it did, report to client */
2152 if ( !W_ERROR_IS_OK(status_win2k
) )
2157 status
= delete_printer_driver(info
.info_3
, &p
->pipe_user
, version
, delete_files
);
2159 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2162 free_a_printer_driver( info
, 3 );
2168 /****************************************************************************
2169 Internal routine for retreiving printerdata
2170 ***************************************************************************/
2172 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2173 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2174 uint32
*needed
, uint32 in_size
)
2176 REGISTRY_VALUE
*val
;
2180 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2181 return WERR_BADFILE
;
2183 *type
= regval_type( val
);
2185 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2187 size
= regval_size( val
);
2189 /* copy the min(in_size, len) */
2192 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2194 /* special case for 0 length values */
2196 if ( (*data
= (uint8
*)TALLOC_MEMDUP(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2200 if ( (*data
= (uint8
*)TALLOC_ZERO(ctx
, in_size
)) == NULL
)
2209 DEBUG(5,("get_printer_dataex: copy done\n"));
2214 /****************************************************************************
2215 Internal routine for removing printerdata
2216 ***************************************************************************/
2218 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2220 return delete_printer_data( printer
->info_2
, key
, value
);
2223 /****************************************************************************
2224 Internal routine for storing printerdata
2225 ***************************************************************************/
2227 WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2228 uint32 type
, uint8
*data
, int real_len
)
2230 /* the registry objects enforce uniqueness based on value name */
2232 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2235 /********************************************************************
2236 GetPrinterData on a printer server Handle.
2237 ********************************************************************/
2239 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2243 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2245 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2247 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2253 if (!StrCaseCmp(value
, "BeepEnabled")) {
2255 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2257 SIVAL(*data
, 0, 0x00);
2262 if (!StrCaseCmp(value
, "EventLog")) {
2264 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2266 /* formally was 0x1b */
2267 SIVAL(*data
, 0, 0x0);
2272 if (!StrCaseCmp(value
, "NetPopup")) {
2274 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2276 SIVAL(*data
, 0, 0x00);
2281 if (!StrCaseCmp(value
, "MajorVersion")) {
2283 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2286 /* Windows NT 4.0 seems to not allow uploading of drivers
2287 to a server that reports 0x3 as the MajorVersion.
2288 need to investigate more how Win2k gets around this .
2291 if ( RA_WINNT
== get_remote_arch() )
2300 if (!StrCaseCmp(value
, "MinorVersion")) {
2302 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2310 * uint32 size = 0x114
2312 * uint32 minor = [0|1]
2313 * uint32 build = [2195|2600]
2314 * extra unicode string = e.g. "Service Pack 3"
2316 if (!StrCaseCmp(value
, "OSVersion")) {
2320 if ( !(*data
= TALLOC_ZERO_ARRAY(ctx
, uint8
, (*needed
> in_size
) ? *needed
:in_size
)) )
2323 SIVAL(*data
, 0, *needed
); /* size */
2324 SIVAL(*data
, 4, 5); /* Windows 2000 == 5.0 */
2326 SIVAL(*data
, 12, 2195); /* build */
2328 /* leave extra string empty */
2334 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2335 const char *string
="C:\\PRINTERS";
2337 *needed
= 2*(strlen(string
)+1);
2338 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2340 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2342 /* it's done by hand ready to go on the wire */
2343 for (i
=0; i
<strlen(string
); i
++) {
2344 (*data
)[2*i
]=string
[i
];
2345 (*data
)[2*i
+1]='\0';
2350 if (!StrCaseCmp(value
, "Architecture")) {
2351 const char *string
="Windows NT x86";
2353 *needed
= 2*(strlen(string
)+1);
2354 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2356 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2357 for (i
=0; i
<strlen(string
); i
++) {
2358 (*data
)[2*i
]=string
[i
];
2359 (*data
)[2*i
+1]='\0';
2364 if (!StrCaseCmp(value
, "DsPresent")) {
2366 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2369 /* only show the publish check box if we are a
2370 memeber of a AD domain */
2372 if ( lp_security() == SEC_ADS
)
2373 SIVAL(*data
, 0, 0x01);
2375 SIVAL(*data
, 0, 0x00);
2381 if (!StrCaseCmp(value
, "DNSMachineName")) {
2384 if (!get_mydnsfullname(hostname
))
2385 return WERR_BADFILE
;
2387 *needed
= 2*(strlen(hostname
)+1);
2388 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2390 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2391 for (i
=0; i
<strlen(hostname
); i
++) {
2392 (*data
)[2*i
]=hostname
[i
];
2393 (*data
)[2*i
+1]='\0';
2399 return WERR_BADFILE
;
2402 /********************************************************************
2403 * spoolss_getprinterdata
2404 ********************************************************************/
2406 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2408 POLICY_HND
*handle
= &q_u
->handle
;
2409 UNISTR2
*valuename
= &q_u
->valuename
;
2410 uint32 in_size
= q_u
->size
;
2411 uint32
*type
= &r_u
->type
;
2412 uint32
*out_size
= &r_u
->size
;
2413 uint8
**data
= &r_u
->data
;
2414 uint32
*needed
= &r_u
->needed
;
2417 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2418 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2422 * Reminder: when it's a string, the length is in BYTES
2423 * even if UNICODE is negociated.
2428 *out_size
= in_size
;
2430 /* in case of problem, return some default values */
2435 DEBUG(4,("_spoolss_getprinterdata\n"));
2438 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2439 status
= WERR_BADFID
;
2443 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2445 if ( Printer
->printer_type
== SPLHND_SERVER
)
2446 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2449 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2450 status
= WERR_BADFID
;
2454 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2455 if ( !W_ERROR_IS_OK(status
) )
2458 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2460 if ( strequal(value
, "ChangeId") ) {
2462 *needed
= sizeof(uint32
);
2463 if ( (*data
= (uint8
*)TALLOC(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2464 status
= WERR_NOMEM
;
2467 SIVAL( *data
, 0, printer
->info_2
->changeid
);
2471 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2474 if (*needed
> *out_size
)
2475 status
= WERR_MORE_DATA
;
2478 if ( !W_ERROR_IS_OK(status
) )
2480 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2482 /* reply this param doesn't exist */
2485 if((*data
=(uint8
*)TALLOC_ZERO_ARRAY(p
->mem_ctx
, uint8
, *out_size
)) == NULL
) {
2487 free_a_printer( &printer
, 2 );
2496 /* cleanup & exit */
2499 free_a_printer( &printer
, 2 );
2504 /*********************************************************
2505 Connect to the client machine.
2506 **********************************************************/
2508 static BOOL
spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2509 struct in_addr
*client_ip
, const char *remote_machine
)
2512 struct cli_state
*the_cli
;
2513 struct in_addr rm_addr
;
2515 if ( is_zero_ip(*client_ip
) ) {
2516 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20) ) {
2517 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2521 if ( ismyip( rm_addr
)) {
2522 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2526 rm_addr
.s_addr
= client_ip
->s_addr
;
2527 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2528 inet_ntoa(*client_ip
) ));
2531 /* setup the connection */
2533 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2534 &rm_addr
, 0, "IPC$", "IPC",
2538 0, lp_client_signing(), NULL
);
2540 if ( !NT_STATUS_IS_OK( ret
) ) {
2541 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2546 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2547 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2548 cli_shutdown(the_cli
);
2553 * Ok - we have an anonymous connection to the IPC$ share.
2554 * Now start the NT Domain stuff :-).
2557 if ( !(*pp_pipe
= cli_rpc_pipe_open_noauth(the_cli
, PI_SPOOLSS
, &ret
)) ) {
2558 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2559 remote_machine
, nt_errstr(ret
)));
2560 cli_shutdown(the_cli
);
2564 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2566 (*pp_pipe
)->cli
= the_cli
;
2571 /***************************************************************************
2572 Connect to the client.
2573 ****************************************************************************/
2575 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2576 uint32 localprinter
, uint32 type
,
2577 POLICY_HND
*handle
, struct in_addr
*client_ip
)
2582 * If it's the first connection, contact the client
2583 * and connect to the IPC$ share anonymously
2585 if (smb_connections
==0) {
2586 fstring unix_printer
;
2588 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2590 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ip
, unix_printer
))
2593 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2594 /* Tell the connections db we're now interested in printer
2595 * notify messages. */
2596 register_message_flags( True
, FLAG_MSG_PRINT_NOTIFY
);
2600 * Tell the specific printing tdb we want messages for this printer
2601 * by registering our PID.
2604 if (!print_notify_register_pid(snum
))
2605 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2609 result
= rpccli_spoolss_reply_open_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, printer
, localprinter
,
2612 if (!W_ERROR_IS_OK(result
))
2613 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2614 dos_errstr(result
)));
2616 return (W_ERROR_IS_OK(result
));
2619 /********************************************************************
2621 * ReplyFindFirstPrinterChangeNotifyEx
2623 * before replying OK: status=0 a rpc call is made to the workstation
2624 * asking ReplyOpenPrinter
2626 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2627 * called from api_spoolss_rffpcnex
2628 ********************************************************************/
2630 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2632 POLICY_HND
*handle
= &q_u
->handle
;
2633 uint32 flags
= q_u
->flags
;
2634 uint32 options
= q_u
->options
;
2635 UNISTR2
*localmachine
= &q_u
->localmachine
;
2636 uint32 printerlocal
= q_u
->printerlocal
;
2638 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2639 struct in_addr client_ip
;
2641 /* store the notify value in the printer struct */
2643 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2646 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2650 Printer
->notify
.flags
=flags
;
2651 Printer
->notify
.options
=options
;
2652 Printer
->notify
.printerlocal
=printerlocal
;
2654 if (Printer
->notify
.option
)
2655 free_spool_notify_option(&Printer
->notify
.option
);
2657 Printer
->notify
.option
=dup_spool_notify_option(option
);
2659 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2660 sizeof(Printer
->notify
.localmachine
)-1);
2662 /* Connect to the client machine and send a ReplyOpenPrinter */
2664 if ( Printer
->printer_type
== SPLHND_SERVER
)
2666 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2667 !get_printer_snum(p
, handle
, &snum
) )
2670 client_ip
.s_addr
= inet_addr(p
->conn
->client_address
);
2672 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2673 Printer
->notify
.printerlocal
, 1,
2674 &Printer
->notify
.client_hnd
, &client_ip
))
2675 return WERR_SERVER_UNAVAILABLE
;
2677 Printer
->notify
.client_connected
=True
;
2682 /*******************************************************************
2683 * fill a notify_info_data with the servername
2684 ********************************************************************/
2686 void spoolss_notify_server_name(int snum
,
2687 SPOOL_NOTIFY_INFO_DATA
*data
,
2688 print_queue_struct
*queue
,
2689 NT_PRINTER_INFO_LEVEL
*printer
,
2690 TALLOC_CTX
*mem_ctx
)
2695 len
= rpcstr_push(temp
, printer
->info_2
->servername
, sizeof(temp
)-2, STR_TERMINATE
);
2697 data
->notify_data
.data
.length
= len
;
2698 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2700 if (!data
->notify_data
.data
.string
) {
2701 data
->notify_data
.data
.length
= 0;
2705 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2708 /*******************************************************************
2709 * fill a notify_info_data with the printername (not including the servername).
2710 ********************************************************************/
2712 void spoolss_notify_printer_name(int snum
,
2713 SPOOL_NOTIFY_INFO_DATA
*data
,
2714 print_queue_struct
*queue
,
2715 NT_PRINTER_INFO_LEVEL
*printer
,
2716 TALLOC_CTX
*mem_ctx
)
2721 /* the notify name should not contain the \\server\ part */
2722 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2725 p
= printer
->info_2
->printername
;
2730 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2732 data
->notify_data
.data
.length
= len
;
2733 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2735 if (!data
->notify_data
.data
.string
) {
2736 data
->notify_data
.data
.length
= 0;
2740 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2743 /*******************************************************************
2744 * fill a notify_info_data with the servicename
2745 ********************************************************************/
2747 void spoolss_notify_share_name(int snum
,
2748 SPOOL_NOTIFY_INFO_DATA
*data
,
2749 print_queue_struct
*queue
,
2750 NT_PRINTER_INFO_LEVEL
*printer
,
2751 TALLOC_CTX
*mem_ctx
)
2756 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2758 data
->notify_data
.data
.length
= len
;
2759 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2761 if (!data
->notify_data
.data
.string
) {
2762 data
->notify_data
.data
.length
= 0;
2766 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2769 /*******************************************************************
2770 * fill a notify_info_data with the port name
2771 ********************************************************************/
2773 void spoolss_notify_port_name(int snum
,
2774 SPOOL_NOTIFY_INFO_DATA
*data
,
2775 print_queue_struct
*queue
,
2776 NT_PRINTER_INFO_LEVEL
*printer
,
2777 TALLOC_CTX
*mem_ctx
)
2782 /* even if it's strange, that's consistant in all the code */
2784 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2786 data
->notify_data
.data
.length
= len
;
2787 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2789 if (!data
->notify_data
.data
.string
) {
2790 data
->notify_data
.data
.length
= 0;
2794 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2797 /*******************************************************************
2798 * fill a notify_info_data with the printername
2799 * but it doesn't exist, have to see what to do
2800 ********************************************************************/
2802 void spoolss_notify_driver_name(int snum
,
2803 SPOOL_NOTIFY_INFO_DATA
*data
,
2804 print_queue_struct
*queue
,
2805 NT_PRINTER_INFO_LEVEL
*printer
,
2806 TALLOC_CTX
*mem_ctx
)
2811 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2813 data
->notify_data
.data
.length
= len
;
2814 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2816 if (!data
->notify_data
.data
.string
) {
2817 data
->notify_data
.data
.length
= 0;
2821 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2824 /*******************************************************************
2825 * fill a notify_info_data with the comment
2826 ********************************************************************/
2828 void spoolss_notify_comment(int snum
,
2829 SPOOL_NOTIFY_INFO_DATA
*data
,
2830 print_queue_struct
*queue
,
2831 NT_PRINTER_INFO_LEVEL
*printer
,
2832 TALLOC_CTX
*mem_ctx
)
2837 if (*printer
->info_2
->comment
== '\0')
2838 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2840 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2842 data
->notify_data
.data
.length
= len
;
2843 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2845 if (!data
->notify_data
.data
.string
) {
2846 data
->notify_data
.data
.length
= 0;
2850 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2853 /*******************************************************************
2854 * fill a notify_info_data with the comment
2855 * location = "Room 1, floor 2, building 3"
2856 ********************************************************************/
2858 void spoolss_notify_location(int snum
,
2859 SPOOL_NOTIFY_INFO_DATA
*data
,
2860 print_queue_struct
*queue
,
2861 NT_PRINTER_INFO_LEVEL
*printer
,
2862 TALLOC_CTX
*mem_ctx
)
2867 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2869 data
->notify_data
.data
.length
= len
;
2870 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2872 if (!data
->notify_data
.data
.string
) {
2873 data
->notify_data
.data
.length
= 0;
2877 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2880 /*******************************************************************
2881 * fill a notify_info_data with the device mode
2882 * jfm:xxxx don't to it for know but that's a real problem !!!
2883 ********************************************************************/
2885 static void spoolss_notify_devmode(int snum
,
2886 SPOOL_NOTIFY_INFO_DATA
*data
,
2887 print_queue_struct
*queue
,
2888 NT_PRINTER_INFO_LEVEL
*printer
,
2889 TALLOC_CTX
*mem_ctx
)
2893 /*******************************************************************
2894 * fill a notify_info_data with the separator file name
2895 ********************************************************************/
2897 void spoolss_notify_sepfile(int snum
,
2898 SPOOL_NOTIFY_INFO_DATA
*data
,
2899 print_queue_struct
*queue
,
2900 NT_PRINTER_INFO_LEVEL
*printer
,
2901 TALLOC_CTX
*mem_ctx
)
2906 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2908 data
->notify_data
.data
.length
= len
;
2909 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2911 if (!data
->notify_data
.data
.string
) {
2912 data
->notify_data
.data
.length
= 0;
2916 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2919 /*******************************************************************
2920 * fill a notify_info_data with the print processor
2921 * jfm:xxxx return always winprint to indicate we don't do anything to it
2922 ********************************************************************/
2924 void spoolss_notify_print_processor(int snum
,
2925 SPOOL_NOTIFY_INFO_DATA
*data
,
2926 print_queue_struct
*queue
,
2927 NT_PRINTER_INFO_LEVEL
*printer
,
2928 TALLOC_CTX
*mem_ctx
)
2933 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
2935 data
->notify_data
.data
.length
= len
;
2936 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2938 if (!data
->notify_data
.data
.string
) {
2939 data
->notify_data
.data
.length
= 0;
2943 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2946 /*******************************************************************
2947 * fill a notify_info_data with the print processor options
2948 * jfm:xxxx send an empty string
2949 ********************************************************************/
2951 void spoolss_notify_parameters(int snum
,
2952 SPOOL_NOTIFY_INFO_DATA
*data
,
2953 print_queue_struct
*queue
,
2954 NT_PRINTER_INFO_LEVEL
*printer
,
2955 TALLOC_CTX
*mem_ctx
)
2960 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
2962 data
->notify_data
.data
.length
= len
;
2963 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2965 if (!data
->notify_data
.data
.string
) {
2966 data
->notify_data
.data
.length
= 0;
2970 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2973 /*******************************************************************
2974 * fill a notify_info_data with the data type
2975 * jfm:xxxx always send RAW as data type
2976 ********************************************************************/
2978 void spoolss_notify_datatype(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
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
2989 data
->notify_data
.data
.length
= len
;
2990 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2992 if (!data
->notify_data
.data
.string
) {
2993 data
->notify_data
.data
.length
= 0;
2997 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3000 /*******************************************************************
3001 * fill a notify_info_data with the security descriptor
3002 * jfm:xxxx send an null pointer to say no security desc
3003 * have to implement security before !
3004 ********************************************************************/
3006 static void spoolss_notify_security_desc(int snum
,
3007 SPOOL_NOTIFY_INFO_DATA
*data
,
3008 print_queue_struct
*queue
,
3009 NT_PRINTER_INFO_LEVEL
*printer
,
3010 TALLOC_CTX
*mem_ctx
)
3012 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
3013 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
3016 /*******************************************************************
3017 * fill a notify_info_data with the attributes
3018 * jfm:xxxx a samba printer is always shared
3019 ********************************************************************/
3021 void spoolss_notify_attributes(int snum
,
3022 SPOOL_NOTIFY_INFO_DATA
*data
,
3023 print_queue_struct
*queue
,
3024 NT_PRINTER_INFO_LEVEL
*printer
,
3025 TALLOC_CTX
*mem_ctx
)
3027 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
3028 data
->notify_data
.value
[1] = 0;
3031 /*******************************************************************
3032 * fill a notify_info_data with the priority
3033 ********************************************************************/
3035 static void spoolss_notify_priority(int snum
,
3036 SPOOL_NOTIFY_INFO_DATA
*data
,
3037 print_queue_struct
*queue
,
3038 NT_PRINTER_INFO_LEVEL
*printer
,
3039 TALLOC_CTX
*mem_ctx
)
3041 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
3042 data
->notify_data
.value
[1] = 0;
3045 /*******************************************************************
3046 * fill a notify_info_data with the default priority
3047 ********************************************************************/
3049 static void spoolss_notify_default_priority(int snum
,
3050 SPOOL_NOTIFY_INFO_DATA
*data
,
3051 print_queue_struct
*queue
,
3052 NT_PRINTER_INFO_LEVEL
*printer
,
3053 TALLOC_CTX
*mem_ctx
)
3055 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
3056 data
->notify_data
.value
[1] = 0;
3059 /*******************************************************************
3060 * fill a notify_info_data with the start time
3061 ********************************************************************/
3063 static void spoolss_notify_start_time(int snum
,
3064 SPOOL_NOTIFY_INFO_DATA
*data
,
3065 print_queue_struct
*queue
,
3066 NT_PRINTER_INFO_LEVEL
*printer
,
3067 TALLOC_CTX
*mem_ctx
)
3069 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
3070 data
->notify_data
.value
[1] = 0;
3073 /*******************************************************************
3074 * fill a notify_info_data with the until time
3075 ********************************************************************/
3077 static void spoolss_notify_until_time(int snum
,
3078 SPOOL_NOTIFY_INFO_DATA
*data
,
3079 print_queue_struct
*queue
,
3080 NT_PRINTER_INFO_LEVEL
*printer
,
3081 TALLOC_CTX
*mem_ctx
)
3083 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3084 data
->notify_data
.value
[1] = 0;
3087 /*******************************************************************
3088 * fill a notify_info_data with the status
3089 ********************************************************************/
3091 static void spoolss_notify_status(int snum
,
3092 SPOOL_NOTIFY_INFO_DATA
*data
,
3093 print_queue_struct
*queue
,
3094 NT_PRINTER_INFO_LEVEL
*printer
,
3095 TALLOC_CTX
*mem_ctx
)
3097 print_status_struct status
;
3099 print_queue_length(snum
, &status
);
3100 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3101 data
->notify_data
.value
[1] = 0;
3104 /*******************************************************************
3105 * fill a notify_info_data with the number of jobs queued
3106 ********************************************************************/
3108 void spoolss_notify_cjobs(int snum
,
3109 SPOOL_NOTIFY_INFO_DATA
*data
,
3110 print_queue_struct
*queue
,
3111 NT_PRINTER_INFO_LEVEL
*printer
,
3112 TALLOC_CTX
*mem_ctx
)
3114 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3115 data
->notify_data
.value
[1] = 0;
3118 /*******************************************************************
3119 * fill a notify_info_data with the average ppm
3120 ********************************************************************/
3122 static void spoolss_notify_average_ppm(int snum
,
3123 SPOOL_NOTIFY_INFO_DATA
*data
,
3124 print_queue_struct
*queue
,
3125 NT_PRINTER_INFO_LEVEL
*printer
,
3126 TALLOC_CTX
*mem_ctx
)
3128 /* always respond 8 pages per minutes */
3129 /* a little hard ! */
3130 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3131 data
->notify_data
.value
[1] = 0;
3134 /*******************************************************************
3135 * fill a notify_info_data with username
3136 ********************************************************************/
3138 static void spoolss_notify_username(int snum
,
3139 SPOOL_NOTIFY_INFO_DATA
*data
,
3140 print_queue_struct
*queue
,
3141 NT_PRINTER_INFO_LEVEL
*printer
,
3142 TALLOC_CTX
*mem_ctx
)
3147 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3149 data
->notify_data
.data
.length
= len
;
3150 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3152 if (!data
->notify_data
.data
.string
) {
3153 data
->notify_data
.data
.length
= 0;
3157 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3160 /*******************************************************************
3161 * fill a notify_info_data with job status
3162 ********************************************************************/
3164 static void spoolss_notify_job_status(int snum
,
3165 SPOOL_NOTIFY_INFO_DATA
*data
,
3166 print_queue_struct
*queue
,
3167 NT_PRINTER_INFO_LEVEL
*printer
,
3168 TALLOC_CTX
*mem_ctx
)
3170 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3171 data
->notify_data
.value
[1] = 0;
3174 /*******************************************************************
3175 * fill a notify_info_data with job name
3176 ********************************************************************/
3178 static void spoolss_notify_job_name(int snum
,
3179 SPOOL_NOTIFY_INFO_DATA
*data
,
3180 print_queue_struct
*queue
,
3181 NT_PRINTER_INFO_LEVEL
*printer
,
3182 TALLOC_CTX
*mem_ctx
)
3187 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3189 data
->notify_data
.data
.length
= len
;
3190 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3192 if (!data
->notify_data
.data
.string
) {
3193 data
->notify_data
.data
.length
= 0;
3197 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3200 /*******************************************************************
3201 * fill a notify_info_data with job status
3202 ********************************************************************/
3204 static void spoolss_notify_job_status_string(int snum
,
3205 SPOOL_NOTIFY_INFO_DATA
*data
,
3206 print_queue_struct
*queue
,
3207 NT_PRINTER_INFO_LEVEL
*printer
,
3208 TALLOC_CTX
*mem_ctx
)
3211 * Now we're returning job status codes we just return a "" here. JRA.
3218 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3221 switch (queue
->status
) {
3226 p
= ""; /* NT provides the paused string */
3235 #endif /* NO LONGER NEEDED. */
3237 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3239 data
->notify_data
.data
.length
= len
;
3240 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3242 if (!data
->notify_data
.data
.string
) {
3243 data
->notify_data
.data
.length
= 0;
3247 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3250 /*******************************************************************
3251 * fill a notify_info_data with job time
3252 ********************************************************************/
3254 static void spoolss_notify_job_time(int snum
,
3255 SPOOL_NOTIFY_INFO_DATA
*data
,
3256 print_queue_struct
*queue
,
3257 NT_PRINTER_INFO_LEVEL
*printer
,
3258 TALLOC_CTX
*mem_ctx
)
3260 data
->notify_data
.value
[0]=0x0;
3261 data
->notify_data
.value
[1]=0;
3264 /*******************************************************************
3265 * fill a notify_info_data with job size
3266 ********************************************************************/
3268 static void spoolss_notify_job_size(int snum
,
3269 SPOOL_NOTIFY_INFO_DATA
*data
,
3270 print_queue_struct
*queue
,
3271 NT_PRINTER_INFO_LEVEL
*printer
,
3272 TALLOC_CTX
*mem_ctx
)
3274 data
->notify_data
.value
[0]=queue
->size
;
3275 data
->notify_data
.value
[1]=0;
3278 /*******************************************************************
3279 * fill a notify_info_data with page info
3280 ********************************************************************/
3281 static void spoolss_notify_total_pages(int snum
,
3282 SPOOL_NOTIFY_INFO_DATA
*data
,
3283 print_queue_struct
*queue
,
3284 NT_PRINTER_INFO_LEVEL
*printer
,
3285 TALLOC_CTX
*mem_ctx
)
3287 data
->notify_data
.value
[0]=queue
->page_count
;
3288 data
->notify_data
.value
[1]=0;
3291 /*******************************************************************
3292 * fill a notify_info_data with pages printed info.
3293 ********************************************************************/
3294 static void spoolss_notify_pages_printed(int snum
,
3295 SPOOL_NOTIFY_INFO_DATA
*data
,
3296 print_queue_struct
*queue
,
3297 NT_PRINTER_INFO_LEVEL
*printer
,
3298 TALLOC_CTX
*mem_ctx
)
3300 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3301 data
->notify_data
.value
[1]=0;
3304 /*******************************************************************
3305 Fill a notify_info_data with job position.
3306 ********************************************************************/
3308 static void spoolss_notify_job_position(int snum
,
3309 SPOOL_NOTIFY_INFO_DATA
*data
,
3310 print_queue_struct
*queue
,
3311 NT_PRINTER_INFO_LEVEL
*printer
,
3312 TALLOC_CTX
*mem_ctx
)
3314 data
->notify_data
.value
[0]=queue
->job
;
3315 data
->notify_data
.value
[1]=0;
3318 /*******************************************************************
3319 Fill a notify_info_data with submitted time.
3320 ********************************************************************/
3322 static void spoolss_notify_submitted_time(int snum
,
3323 SPOOL_NOTIFY_INFO_DATA
*data
,
3324 print_queue_struct
*queue
,
3325 NT_PRINTER_INFO_LEVEL
*printer
,
3326 TALLOC_CTX
*mem_ctx
)
3333 t
=gmtime(&queue
->time
);
3335 len
= sizeof(SYSTEMTIME
);
3337 data
->notify_data
.data
.length
= len
;
3338 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3340 if (!data
->notify_data
.data
.string
) {
3341 data
->notify_data
.data
.length
= 0;
3345 make_systemtime(&st
, t
);
3348 * Systemtime must be linearized as a set of UINT16's.
3349 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3352 p
= (char *)data
->notify_data
.data
.string
;
3353 SSVAL(p
, 0, st
.year
);
3354 SSVAL(p
, 2, st
.month
);
3355 SSVAL(p
, 4, st
.dayofweek
);
3356 SSVAL(p
, 6, st
.day
);
3357 SSVAL(p
, 8, st
.hour
);
3358 SSVAL(p
, 10, st
.minute
);
3359 SSVAL(p
, 12, st
.second
);
3360 SSVAL(p
, 14, st
.milliseconds
);
3363 struct s_notify_info_data_table
3369 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3370 print_queue_struct
*queue
,
3371 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3374 /* A table describing the various print notification constants and
3375 whether the notification data is a pointer to a variable sized
3376 buffer, a one value uint32 or a two value uint32. */
3378 static const struct s_notify_info_data_table notify_info_data_table
[] =
3380 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3381 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3382 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3383 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3384 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3385 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3386 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3387 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3388 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3389 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3390 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3391 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3392 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3393 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3394 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3395 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3396 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3397 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3398 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3399 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3400 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3401 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3402 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3403 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3404 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3405 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3406 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3407 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3408 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3409 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3410 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3411 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3412 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3413 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3414 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3415 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3416 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3417 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3418 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3419 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3420 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3421 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3422 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3423 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3424 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3425 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3426 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3427 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3428 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3429 { PRINT_TABLE_END
, 0x0, NULL
, 0x0, NULL
},
3432 /*******************************************************************
3433 Return the size of info_data structure.
3434 ********************************************************************/
3436 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3440 for (i
= 0; i
< (sizeof(notify_info_data_table
)/sizeof(struct s_notify_info_data_table
)); i
++) {
3441 if ( (notify_info_data_table
[i
].type
== type
)
3442 && (notify_info_data_table
[i
].field
== field
) ) {
3443 switch(notify_info_data_table
[i
].size
) {
3444 case NOTIFY_ONE_VALUE
:
3445 case NOTIFY_TWO_VALUE
:
3450 /* The only pointer notify data I have seen on
3451 the wire is the submitted time and this has
3452 the notify size set to 4. -tpot */
3454 case NOTIFY_POINTER
:
3457 case NOTIFY_SECDESC
:
3463 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3468 /*******************************************************************
3469 Return the type of notify_info_data.
3470 ********************************************************************/
3472 static uint32
type_of_notify_info_data(uint16 type
, uint16 field
)
3476 for (i
= 0; i
< (sizeof(notify_info_data_table
)/sizeof(struct s_notify_info_data_table
)); i
++) {
3477 if (notify_info_data_table
[i
].type
== type
&&
3478 notify_info_data_table
[i
].field
== field
)
3479 return notify_info_data_table
[i
].size
;
3485 /****************************************************************************
3486 ****************************************************************************/
3488 static BOOL
search_notify(uint16 type
, uint16 field
, int *value
)
3492 for (i
= 0; notify_info_data_table
[i
].type
!= PRINT_TABLE_END
; i
++) {
3493 if (notify_info_data_table
[i
].type
== type
&&
3494 notify_info_data_table
[i
].field
== field
&&
3495 notify_info_data_table
[i
].fn
!= NULL
) {
3504 /****************************************************************************
3505 ****************************************************************************/
3507 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3509 info_data
->type
= type
;
3510 info_data
->field
= field
;
3511 info_data
->reserved
= 0;
3513 info_data
->size
= size_of_notify_info_data(type
, field
);
3514 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3519 /*******************************************************************
3521 * fill a notify_info struct with info asked
3523 ********************************************************************/
3525 static BOOL
construct_notify_printer_info(Printer_entry
*print_hnd
, SPOOL_NOTIFY_INFO
*info
, int
3526 snum
, SPOOL_NOTIFY_OPTION_TYPE
3527 *option_type
, uint32 id
,
3528 TALLOC_CTX
*mem_ctx
)
3534 SPOOL_NOTIFY_INFO_DATA
*current_data
;
3535 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3536 print_queue_struct
*queue
=NULL
;
3538 type
=option_type
->type
;
3540 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3541 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3542 option_type
->count
, lp_servicename(snum
)));
3544 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3547 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3548 field
= option_type
->fields
[field_num
];
3550 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3552 if (!search_notify(type
, field
, &j
) )
3555 if((info
->data
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3556 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3557 free_a_printer(&printer
, 2);
3561 current_data
= &info
->data
[info
->count
];
3563 construct_info_data(current_data
, type
, field
, id
);
3565 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3566 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3568 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3574 free_a_printer(&printer
, 2);
3578 /*******************************************************************
3580 * fill a notify_info struct with info asked
3582 ********************************************************************/
3584 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3585 SPOOL_NOTIFY_INFO
*info
,
3586 NT_PRINTER_INFO_LEVEL
*printer
,
3587 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3588 *option_type
, uint32 id
,
3589 TALLOC_CTX
*mem_ctx
)
3595 SPOOL_NOTIFY_INFO_DATA
*current_data
;
3597 DEBUG(4,("construct_notify_jobs_info\n"));
3599 type
= option_type
->type
;
3601 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3602 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3603 option_type
->count
));
3605 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3606 field
= option_type
->fields
[field_num
];
3608 if (!search_notify(type
, field
, &j
) )
3611 if((info
->data
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3612 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3616 current_data
=&(info
->data
[info
->count
]);
3618 construct_info_data(current_data
, type
, field
, id
);
3619 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3628 * JFM: The enumeration is not that simple, it's even non obvious.
3630 * let's take an example: I want to monitor the PRINTER SERVER for
3631 * the printer's name and the number of jobs currently queued.
3632 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3633 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3635 * I have 3 printers on the back of my server.
3637 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3640 * 1 printer 1 name 1
3641 * 2 printer 1 cjob 1
3642 * 3 printer 2 name 2
3643 * 4 printer 2 cjob 2
3644 * 5 printer 3 name 3
3645 * 6 printer 3 name 3
3647 * that's the print server case, the printer case is even worse.
3650 /*******************************************************************
3652 * enumerate all printers on the printserver
3653 * fill a notify_info struct with info asked
3655 ********************************************************************/
3657 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3658 SPOOL_NOTIFY_INFO
*info
,
3659 TALLOC_CTX
*mem_ctx
)
3662 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3663 int n_services
=lp_numservices();
3665 SPOOL_NOTIFY_OPTION
*option
;
3666 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3668 DEBUG(4,("printserver_notify_info\n"));
3673 option
=Printer
->notify
.option
;
3678 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3679 sending a ffpcn() request first */
3684 for (i
=0; i
<option
->count
; i
++) {
3685 option_type
=&(option
->ctr
.type
[i
]);
3687 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3690 for (snum
=0; snum
<n_services
; snum
++)
3692 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3693 construct_notify_printer_info ( Printer
, info
, snum
, option_type
, snum
, mem_ctx
);
3699 * Debugging information, don't delete.
3702 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3703 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3704 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3706 for (i
=0; i
<info
->count
; i
++) {
3707 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3708 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3709 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3716 /*******************************************************************
3718 * fill a notify_info struct with info asked
3720 ********************************************************************/
3722 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3723 TALLOC_CTX
*mem_ctx
)
3726 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3729 SPOOL_NOTIFY_OPTION
*option
;
3730 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3732 print_queue_struct
*queue
=NULL
;
3733 print_status_struct status
;
3735 DEBUG(4,("printer_notify_info\n"));
3740 option
=Printer
->notify
.option
;
3746 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3747 sending a ffpcn() request first */
3752 get_printer_snum(p
, hnd
, &snum
);
3754 for (i
=0; i
<option
->count
; i
++) {
3755 option_type
=&option
->ctr
.type
[i
];
3757 switch ( option_type
->type
) {
3758 case PRINTER_NOTIFY_TYPE
:
3759 if(construct_notify_printer_info(Printer
, info
, snum
,
3765 case JOB_NOTIFY_TYPE
: {
3766 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3768 count
= print_queue_status(snum
, &queue
, &status
);
3770 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3773 for (j
=0; j
<count
; j
++) {
3774 construct_notify_jobs_info(&queue
[j
], info
,
3781 free_a_printer(&printer
, 2);
3791 * Debugging information, don't delete.
3794 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3795 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3796 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3798 for (i=0; i<info->count; i++) {
3799 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3800 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3801 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3807 /********************************************************************
3809 ********************************************************************/
3811 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3813 POLICY_HND
*handle
= &q_u
->handle
;
3814 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3816 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3817 WERROR result
= WERR_BADFID
;
3819 /* we always have a NOTIFY_INFO struct */
3823 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3824 OUR_HANDLE(handle
)));
3828 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3831 * We are now using the change value, and
3832 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3833 * I don't have a global notification system, I'm sending back all the
3834 * informations even when _NOTHING_ has changed.
3837 /* We need to keep track of the change value to send back in
3838 RRPCN replies otherwise our updates are ignored. */
3840 Printer
->notify
.fnpcn
= True
;
3842 if (Printer
->notify
.client_connected
) {
3843 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3844 Printer
->notify
.change
= q_u
->change
;
3847 /* just ignore the SPOOL_NOTIFY_OPTION */
3849 switch (Printer
->printer_type
) {
3851 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3854 case SPLHND_PRINTER
:
3855 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3859 Printer
->notify
.fnpcn
= False
;
3865 /********************************************************************
3866 * construct_printer_info_0
3867 * fill a printer_info_0 struct
3868 ********************************************************************/
3870 static BOOL
construct_printer_info_0(Printer_entry
*print_hnd
, PRINTER_INFO_0
*printer
, int snum
)
3874 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3875 counter_printer_0
*session_counter
;
3876 uint32 global_counter
;
3879 print_status_struct status
;
3881 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3884 count
= print_queue_length(snum
, &status
);
3886 /* check if we already have a counter for this printer */
3887 for(session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3888 if (session_counter
->snum
== snum
)
3892 /* it's the first time, add it to the list */
3893 if (session_counter
==NULL
) {
3894 if((session_counter
=SMB_MALLOC_P(counter_printer_0
)) == NULL
) {
3895 free_a_printer(&ntprinter
, 2);
3898 ZERO_STRUCTP(session_counter
);
3899 session_counter
->snum
=snum
;
3900 session_counter
->counter
=0;
3901 DLIST_ADD(counter_list
, session_counter
);
3905 session_counter
->counter
++;
3908 * the global_counter should be stored in a TDB as it's common to all the clients
3909 * and should be zeroed on samba startup
3911 global_counter
=session_counter
->counter
;
3913 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3915 init_unistr(&printer
->printername
, chaine
);
3917 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_server_name(print_hnd
));
3918 init_unistr(&printer
->servername
, chaine
);
3920 printer
->cjobs
= count
;
3921 printer
->total_jobs
= 0;
3922 printer
->total_bytes
= 0;
3924 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3925 t
=gmtime(&setuptime
);
3927 printer
->year
= t
->tm_year
+1900;
3928 printer
->month
= t
->tm_mon
+1;
3929 printer
->dayofweek
= t
->tm_wday
;
3930 printer
->day
= t
->tm_mday
;
3931 printer
->hour
= t
->tm_hour
;
3932 printer
->minute
= t
->tm_min
;
3933 printer
->second
= t
->tm_sec
;
3934 printer
->milliseconds
= 0;
3936 printer
->global_counter
= global_counter
;
3937 printer
->total_pages
= 0;
3939 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3940 printer
->major_version
= 0x0005; /* NT 5 */
3941 printer
->build_version
= 0x0893; /* build 2195 */
3943 printer
->unknown7
= 0x1;
3944 printer
->unknown8
= 0x0;
3945 printer
->unknown9
= 0x0;
3946 printer
->session_counter
= session_counter
->counter
;
3947 printer
->unknown11
= 0x0;
3948 printer
->printer_errors
= 0x0; /* number of print failure */
3949 printer
->unknown13
= 0x0;
3950 printer
->unknown14
= 0x1;
3951 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3952 printer
->unknown16
= 0x0;
3953 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3954 printer
->unknown18
= 0x0;
3955 printer
->status
= nt_printq_status(status
.status
);
3956 printer
->unknown20
= 0x0;
3957 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3958 printer
->unknown22
= 0x0;
3959 printer
->unknown23
= 0x6; /* 6 ???*/
3960 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3961 printer
->unknown25
= 0;
3962 printer
->unknown26
= 0;
3963 printer
->unknown27
= 0;
3964 printer
->unknown28
= 0;
3965 printer
->unknown29
= 0;
3967 free_a_printer(&ntprinter
,2);
3971 /********************************************************************
3972 * construct_printer_info_1
3973 * fill a printer_info_1 struct
3974 ********************************************************************/
3975 static BOOL
construct_printer_info_1(Printer_entry
*print_hnd
, uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
3979 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3981 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3984 printer
->flags
=flags
;
3986 if (*ntprinter
->info_2
->comment
== '\0') {
3987 init_unistr(&printer
->comment
, lp_comment(snum
));
3988 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3989 ntprinter
->info_2
->drivername
, lp_comment(snum
));
3992 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
3993 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
3994 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
3997 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
3999 init_unistr(&printer
->description
, chaine
);
4000 init_unistr(&printer
->name
, chaine2
);
4002 free_a_printer(&ntprinter
,2);
4007 /****************************************************************************
4008 Free a DEVMODE struct.
4009 ****************************************************************************/
4011 static void free_dev_mode(DEVICEMODE
*dev
)
4016 SAFE_FREE(dev
->dev_private
);
4021 /****************************************************************************
4022 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4023 should be valid upon entry
4024 ****************************************************************************/
4026 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
4028 if ( !devmode
|| !ntdevmode
)
4031 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
4033 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
4035 devmode
->specversion
= ntdevmode
->specversion
;
4036 devmode
->driverversion
= ntdevmode
->driverversion
;
4037 devmode
->size
= ntdevmode
->size
;
4038 devmode
->driverextra
= ntdevmode
->driverextra
;
4039 devmode
->fields
= ntdevmode
->fields
;
4041 devmode
->orientation
= ntdevmode
->orientation
;
4042 devmode
->papersize
= ntdevmode
->papersize
;
4043 devmode
->paperlength
= ntdevmode
->paperlength
;
4044 devmode
->paperwidth
= ntdevmode
->paperwidth
;
4045 devmode
->scale
= ntdevmode
->scale
;
4046 devmode
->copies
= ntdevmode
->copies
;
4047 devmode
->defaultsource
= ntdevmode
->defaultsource
;
4048 devmode
->printquality
= ntdevmode
->printquality
;
4049 devmode
->color
= ntdevmode
->color
;
4050 devmode
->duplex
= ntdevmode
->duplex
;
4051 devmode
->yresolution
= ntdevmode
->yresolution
;
4052 devmode
->ttoption
= ntdevmode
->ttoption
;
4053 devmode
->collate
= ntdevmode
->collate
;
4054 devmode
->icmmethod
= ntdevmode
->icmmethod
;
4055 devmode
->icmintent
= ntdevmode
->icmintent
;
4056 devmode
->mediatype
= ntdevmode
->mediatype
;
4057 devmode
->dithertype
= ntdevmode
->dithertype
;
4059 if (ntdevmode
->nt_dev_private
!= NULL
) {
4060 if ((devmode
->dev_private
=(uint8
*)memdup(ntdevmode
->nt_dev_private
, ntdevmode
->driverextra
)) == NULL
)
4067 /****************************************************************************
4068 Create a DEVMODE struct. Returns malloced memory.
4069 ****************************************************************************/
4071 DEVICEMODE
*construct_dev_mode(const char *servicename
)
4073 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4074 DEVICEMODE
*devmode
= NULL
;
4076 DEBUG(7,("construct_dev_mode\n"));
4078 DEBUGADD(8,("getting printer characteristics\n"));
4080 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
4083 if ( !printer
->info_2
->devmode
) {
4084 DEBUG(5, ("BONG! There was no device mode!\n"));
4088 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) == NULL
) {
4089 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4093 ZERO_STRUCTP(devmode
);
4095 DEBUGADD(8,("loading DEVICEMODE\n"));
4097 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4098 free_dev_mode( devmode
);
4103 free_a_printer(&printer
,2);
4108 /********************************************************************
4109 * construct_printer_info_2
4110 * fill a printer_info_2 struct
4111 ********************************************************************/
4113 static BOOL
construct_printer_info_2(Printer_entry
*print_hnd
, PRINTER_INFO_2
*printer
, int snum
)
4116 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4118 print_status_struct status
;
4120 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4123 count
= print_queue_length(snum
, &status
);
4125 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4126 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4127 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4128 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4129 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4131 if (*ntprinter
->info_2
->comment
== '\0')
4132 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4134 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4136 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4137 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4138 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4139 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4140 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4142 printer
->attributes
= ntprinter
->info_2
->attributes
;
4144 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4145 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4146 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4147 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4148 printer
->status
= nt_printq_status(status
.status
); /* status */
4149 printer
->cjobs
= count
; /* jobs */
4150 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4152 if ( !(printer
->devmode
= construct_dev_mode(lp_const_servicename(snum
))) )
4153 DEBUG(8, ("Returning NULL Devicemode!\n"));
4155 printer
->secdesc
= NULL
;
4157 if ( ntprinter
->info_2
->secdesc_buf
4158 && ntprinter
->info_2
->secdesc_buf
->len
!= 0 )
4160 /* don't use talloc_steal() here unless you do a deep steal of all
4161 the SEC_DESC members */
4163 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4164 ntprinter
->info_2
->secdesc_buf
->sec
);
4167 free_a_printer(&ntprinter
, 2);
4172 /********************************************************************
4173 * construct_printer_info_3
4174 * fill a printer_info_3 struct
4175 ********************************************************************/
4177 static BOOL
construct_printer_info_3(Printer_entry
*print_hnd
, PRINTER_INFO_3
**pp_printer
, int snum
)
4179 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4180 PRINTER_INFO_3
*printer
= NULL
;
4182 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4186 if ((printer
= SMB_MALLOC_P(PRINTER_INFO_3
)) == NULL
) {
4187 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4188 free_a_printer(&ntprinter
, 2);
4192 ZERO_STRUCTP(printer
);
4194 /* These are the components of the SD we are returning. */
4196 printer
->flags
= 0x4;
4198 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4199 /* don't use talloc_steal() here unless you do a deep steal of all
4200 the SEC_DESC members */
4202 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4203 ntprinter
->info_2
->secdesc_buf
->sec
);
4206 free_a_printer(&ntprinter
, 2);
4208 *pp_printer
= printer
;
4212 /********************************************************************
4213 * construct_printer_info_4
4214 * fill a printer_info_4 struct
4215 ********************************************************************/
4217 static BOOL
construct_printer_info_4(Printer_entry
*print_hnd
, PRINTER_INFO_4
*printer
, int snum
)
4219 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4221 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4224 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4225 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4226 printer
->attributes
= ntprinter
->info_2
->attributes
;
4228 free_a_printer(&ntprinter
, 2);
4232 /********************************************************************
4233 * construct_printer_info_5
4234 * fill a printer_info_5 struct
4235 ********************************************************************/
4237 static BOOL
construct_printer_info_5(Printer_entry
*print_hnd
, PRINTER_INFO_5
*printer
, int snum
)
4239 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4241 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4244 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4245 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4246 printer
->attributes
= ntprinter
->info_2
->attributes
;
4248 /* these two are not used by NT+ according to MSDN */
4250 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4251 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4253 free_a_printer(&ntprinter
, 2);
4258 /********************************************************************
4259 * construct_printer_info_7
4260 * fill a printer_info_7 struct
4261 ********************************************************************/
4263 static BOOL
construct_printer_info_7(Printer_entry
*print_hnd
, PRINTER_INFO_7
*printer
, int snum
)
4265 char *guid_str
= NULL
;
4268 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4269 asprintf(&guid_str
, "{%s}", smb_uuid_string_static(guid
));
4270 strupper_m(guid_str
);
4271 init_unistr(&printer
->guid
, guid_str
);
4272 printer
->action
= SPOOL_DS_PUBLISH
;
4274 init_unistr(&printer
->guid
, "");
4275 printer
->action
= SPOOL_DS_UNPUBLISH
;
4281 /********************************************************************
4282 Spoolss_enumprinters.
4283 ********************************************************************/
4285 static WERROR
enum_all_printers_info_1(uint32 flags
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4289 int n_services
=lp_numservices();
4290 PRINTER_INFO_1
*printers
=NULL
;
4291 PRINTER_INFO_1 current_prt
;
4292 WERROR result
= WERR_OK
;
4294 DEBUG(4,("enum_all_printers_info_1\n"));
4296 for (snum
=0; snum
<n_services
; snum
++) {
4297 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4298 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4300 if (construct_printer_info_1(NULL
, flags
, ¤t_prt
, snum
)) {
4301 if((printers
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_1
, *returned
+1)) == NULL
) {
4302 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4306 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4308 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4314 /* check the required size. */
4315 for (i
=0; i
<*returned
; i
++)
4316 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4318 if (*needed
> offered
) {
4319 result
= WERR_INSUFFICIENT_BUFFER
;
4323 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4324 result
= WERR_NOMEM
;
4328 /* fill the buffer with the structures */
4329 for (i
=0; i
<*returned
; i
++)
4330 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4335 SAFE_FREE(printers
);
4337 if ( !W_ERROR_IS_OK(result
) )
4343 /********************************************************************
4344 enum_all_printers_info_1_local.
4345 *********************************************************************/
4347 static WERROR
enum_all_printers_info_1_local(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4349 DEBUG(4,("enum_all_printers_info_1_local\n"));
4351 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4354 /********************************************************************
4355 enum_all_printers_info_1_name.
4356 *********************************************************************/
4358 static WERROR
enum_all_printers_info_1_name(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4362 DEBUG(4,("enum_all_printers_info_1_name\n"));
4364 if ((name
[0] == '\\') && (name
[1] == '\\'))
4367 if (is_myname_or_ipaddr(s
)) {
4368 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4371 return WERR_INVALID_NAME
;
4374 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4375 /********************************************************************
4376 enum_all_printers_info_1_remote.
4377 *********************************************************************/
4379 static WERROR
enum_all_printers_info_1_remote(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4381 PRINTER_INFO_1
*printer
;
4382 fstring printername
;
4385 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4386 WERROR result
= WERR_OK
;
4388 /* JFM: currently it's more a place holder than anything else.
4389 * In the spooler world there is a notion of server registration.
4390 * the print servers are registered on the PDC (in the same domain)
4392 * We should have a TDB here. The registration is done thru an
4393 * undocumented RPC call.
4396 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4401 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", name
);
4402 slprintf(desc
, sizeof(desc
)-1,"%s", name
);
4403 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4405 init_unistr(&printer
->description
, desc
);
4406 init_unistr(&printer
->name
, printername
);
4407 init_unistr(&printer
->comment
, comment
);
4408 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4410 /* check the required size. */
4411 *needed
+= spoolss_size_printer_info_1(printer
);
4413 if (*needed
> offered
) {
4414 result
= WERR_INSUFFICIENT_BUFFER
;
4418 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4419 result
= WERR_NOMEM
;
4423 /* fill the buffer with the structures */
4424 smb_io_printer_info_1("", buffer
, printer
, 0);
4430 if ( !W_ERROR_IS_OK(result
) )
4438 /********************************************************************
4439 enum_all_printers_info_1_network.
4440 *********************************************************************/
4442 static WERROR
enum_all_printers_info_1_network(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4446 DEBUG(4,("enum_all_printers_info_1_network\n"));
4448 /* If we respond to a enum_printers level 1 on our name with flags
4449 set to PRINTER_ENUM_REMOTE with a list of printers then these
4450 printers incorrectly appear in the APW browse list.
4451 Specifically the printers for the server appear at the workgroup
4452 level where all the other servers in the domain are
4453 listed. Windows responds to this call with a
4454 WERR_CAN_NOT_COMPLETE so we should do the same. */
4456 if (name
[0] == '\\' && name
[1] == '\\')
4459 if (is_myname_or_ipaddr(s
))
4460 return WERR_CAN_NOT_COMPLETE
;
4462 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4465 /********************************************************************
4466 * api_spoolss_enumprinters
4468 * called from api_spoolss_enumprinters (see this to understand)
4469 ********************************************************************/
4471 static WERROR
enum_all_printers_info_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4475 int n_services
=lp_numservices();
4476 PRINTER_INFO_2
*printers
=NULL
;
4477 PRINTER_INFO_2 current_prt
;
4478 WERROR result
= WERR_OK
;
4482 for (snum
=0; snum
<n_services
; snum
++) {
4483 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4484 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4486 if (construct_printer_info_2(NULL
, ¤t_prt
, snum
)) {
4487 if ( !(printers
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_2
, *returned
+1)) ) {
4488 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4493 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
+ 1));
4495 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4502 /* check the required size. */
4503 for (i
=0; i
<*returned
; i
++)
4504 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4506 if (*needed
> offered
) {
4507 result
= WERR_INSUFFICIENT_BUFFER
;
4511 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4512 result
= WERR_NOMEM
;
4516 /* fill the buffer with the structures */
4517 for (i
=0; i
<*returned
; i
++)
4518 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4523 for (i
=0; i
<*returned
; i
++)
4524 free_devmode(printers
[i
].devmode
);
4526 SAFE_FREE(printers
);
4528 if ( !W_ERROR_IS_OK(result
) )
4534 /********************************************************************
4535 * handle enumeration of printers at level 1
4536 ********************************************************************/
4538 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4539 RPC_BUFFER
*buffer
, uint32 offered
,
4540 uint32
*needed
, uint32
*returned
)
4542 /* Not all the flags are equals */
4544 if (flags
& PRINTER_ENUM_LOCAL
)
4545 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4547 if (flags
& PRINTER_ENUM_NAME
)
4548 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4550 #if 0 /* JERRY - disabled for now */
4551 if (flags
& PRINTER_ENUM_REMOTE
)
4552 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4555 if (flags
& PRINTER_ENUM_NETWORK
)
4556 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4558 return WERR_OK
; /* NT4sp5 does that */
4561 /********************************************************************
4562 * handle enumeration of printers at level 2
4563 ********************************************************************/
4565 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4566 RPC_BUFFER
*buffer
, uint32 offered
,
4567 uint32
*needed
, uint32
*returned
)
4569 char *s
= servername
;
4571 if (flags
& PRINTER_ENUM_LOCAL
) {
4572 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4575 if (flags
& PRINTER_ENUM_NAME
) {
4576 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4578 if (is_myname_or_ipaddr(s
))
4579 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4581 return WERR_INVALID_NAME
;
4584 if (flags
& PRINTER_ENUM_REMOTE
)
4585 return WERR_UNKNOWN_LEVEL
;
4590 /********************************************************************
4591 * handle enumeration of printers at level 5
4592 ********************************************************************/
4594 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4595 RPC_BUFFER
*buffer
, uint32 offered
,
4596 uint32
*needed
, uint32
*returned
)
4598 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4602 /********************************************************************
4603 * api_spoolss_enumprinters
4605 * called from api_spoolss_enumprinters (see this to understand)
4606 ********************************************************************/
4608 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4610 uint32 flags
= q_u
->flags
;
4611 UNISTR2
*servername
= &q_u
->servername
;
4612 uint32 level
= q_u
->level
;
4613 RPC_BUFFER
*buffer
= NULL
;
4614 uint32 offered
= q_u
->offered
;
4615 uint32
*needed
= &r_u
->needed
;
4616 uint32
*returned
= &r_u
->returned
;
4620 /* that's an [in out] buffer */
4622 if (!q_u
->buffer
&& (offered
!=0)) {
4623 return WERR_INVALID_PARAM
;
4626 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
4627 buffer
= r_u
->buffer
;
4629 DEBUG(4,("_spoolss_enumprinters\n"));
4636 * flags==PRINTER_ENUM_NAME
4637 * if name=="" then enumerates all printers
4638 * if name!="" then enumerate the printer
4639 * flags==PRINTER_ENUM_REMOTE
4640 * name is NULL, enumerate printers
4641 * Level 2: name!="" enumerates printers, name can't be NULL
4642 * Level 3: doesn't exist
4643 * Level 4: does a local registry lookup
4644 * Level 5: same as Level 2
4647 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4652 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4654 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4656 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4661 return WERR_UNKNOWN_LEVEL
;
4664 /****************************************************************************
4665 ****************************************************************************/
4667 static WERROR
getprinter_level_0(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4669 PRINTER_INFO_0
*printer
=NULL
;
4670 WERROR result
= WERR_OK
;
4672 if((printer
=SMB_MALLOC_P(PRINTER_INFO_0
)) == NULL
)
4675 construct_printer_info_0(print_hnd
, printer
, snum
);
4677 /* check the required size. */
4678 *needed
+= spoolss_size_printer_info_0(printer
);
4680 if (*needed
> offered
) {
4681 result
= WERR_INSUFFICIENT_BUFFER
;
4685 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4686 result
= WERR_NOMEM
;
4690 /* fill the buffer with the structures */
4691 smb_io_printer_info_0("", buffer
, printer
, 0);
4701 /****************************************************************************
4702 ****************************************************************************/
4704 static WERROR
getprinter_level_1(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4706 PRINTER_INFO_1
*printer
=NULL
;
4707 WERROR result
= WERR_OK
;
4709 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4712 construct_printer_info_1(print_hnd
, PRINTER_ENUM_ICON8
, printer
, snum
);
4714 /* check the required size. */
4715 *needed
+= spoolss_size_printer_info_1(printer
);
4717 if (*needed
> offered
) {
4718 result
= WERR_INSUFFICIENT_BUFFER
;
4722 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4723 result
= WERR_NOMEM
;
4727 /* fill the buffer with the structures */
4728 smb_io_printer_info_1("", buffer
, printer
, 0);
4737 /****************************************************************************
4738 ****************************************************************************/
4740 static WERROR
getprinter_level_2(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4742 PRINTER_INFO_2
*printer
=NULL
;
4743 WERROR result
= WERR_OK
;
4745 if((printer
=SMB_MALLOC_P(PRINTER_INFO_2
))==NULL
)
4748 construct_printer_info_2(print_hnd
, printer
, snum
);
4750 /* check the required size. */
4751 *needed
+= spoolss_size_printer_info_2(printer
);
4753 if (*needed
> offered
) {
4754 result
= WERR_INSUFFICIENT_BUFFER
;
4758 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4759 result
= WERR_NOMEM
;
4763 /* fill the buffer with the structures */
4764 if (!smb_io_printer_info_2("", buffer
, printer
, 0))
4765 result
= WERR_NOMEM
;
4769 free_printer_info_2(printer
);
4774 /****************************************************************************
4775 ****************************************************************************/
4777 static WERROR
getprinter_level_3(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4779 PRINTER_INFO_3
*printer
=NULL
;
4780 WERROR result
= WERR_OK
;
4782 if (!construct_printer_info_3(print_hnd
, &printer
, snum
))
4785 /* check the required size. */
4786 *needed
+= spoolss_size_printer_info_3(printer
);
4788 if (*needed
> offered
) {
4789 result
= WERR_INSUFFICIENT_BUFFER
;
4793 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4794 result
= WERR_NOMEM
;
4798 /* fill the buffer with the structures */
4799 smb_io_printer_info_3("", buffer
, printer
, 0);
4803 free_printer_info_3(printer
);
4808 /****************************************************************************
4809 ****************************************************************************/
4811 static WERROR
getprinter_level_4(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4813 PRINTER_INFO_4
*printer
=NULL
;
4814 WERROR result
= WERR_OK
;
4816 if((printer
=SMB_MALLOC_P(PRINTER_INFO_4
))==NULL
)
4819 if (!construct_printer_info_4(print_hnd
, printer
, snum
)) {
4824 /* check the required size. */
4825 *needed
+= spoolss_size_printer_info_4(printer
);
4827 if (*needed
> offered
) {
4828 result
= WERR_INSUFFICIENT_BUFFER
;
4832 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4833 result
= WERR_NOMEM
;
4837 /* fill the buffer with the structures */
4838 smb_io_printer_info_4("", buffer
, printer
, 0);
4842 free_printer_info_4(printer
);
4847 /****************************************************************************
4848 ****************************************************************************/
4850 static WERROR
getprinter_level_5(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4852 PRINTER_INFO_5
*printer
=NULL
;
4853 WERROR result
= WERR_OK
;
4855 if((printer
=SMB_MALLOC_P(PRINTER_INFO_5
))==NULL
)
4858 if (!construct_printer_info_5(print_hnd
, printer
, snum
)) {
4859 free_printer_info_5(printer
);
4863 /* check the required size. */
4864 *needed
+= spoolss_size_printer_info_5(printer
);
4866 if (*needed
> offered
) {
4867 result
= WERR_INSUFFICIENT_BUFFER
;
4871 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4872 result
= WERR_NOMEM
;
4876 /* fill the buffer with the structures */
4877 smb_io_printer_info_5("", buffer
, printer
, 0);
4881 free_printer_info_5(printer
);
4886 static WERROR
getprinter_level_7(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4888 PRINTER_INFO_7
*printer
=NULL
;
4889 WERROR result
= WERR_OK
;
4891 if((printer
=SMB_MALLOC_P(PRINTER_INFO_7
))==NULL
)
4894 if (!construct_printer_info_7(print_hnd
, printer
, snum
))
4897 /* check the required size. */
4898 *needed
+= spoolss_size_printer_info_7(printer
);
4900 if (*needed
> offered
) {
4901 result
= WERR_INSUFFICIENT_BUFFER
;
4905 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4906 result
= WERR_NOMEM
;
4911 /* fill the buffer with the structures */
4912 smb_io_printer_info_7("", buffer
, printer
, 0);
4916 free_printer_info_7(printer
);
4921 /****************************************************************************
4922 ****************************************************************************/
4924 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
4926 POLICY_HND
*handle
= &q_u
->handle
;
4927 uint32 level
= q_u
->level
;
4928 RPC_BUFFER
*buffer
= NULL
;
4929 uint32 offered
= q_u
->offered
;
4930 uint32
*needed
= &r_u
->needed
;
4931 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
4935 /* that's an [in out] buffer */
4937 if (!q_u
->buffer
&& (offered
!=0)) {
4938 return WERR_INVALID_PARAM
;
4941 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
4942 buffer
= r_u
->buffer
;
4946 if (!get_printer_snum(p
, handle
, &snum
))
4951 return getprinter_level_0(Printer
, snum
, buffer
, offered
, needed
);
4953 return getprinter_level_1(Printer
, snum
, buffer
, offered
, needed
);
4955 return getprinter_level_2(Printer
, snum
, buffer
, offered
, needed
);
4957 return getprinter_level_3(Printer
, snum
, buffer
, offered
, needed
);
4959 return getprinter_level_4(Printer
, snum
, buffer
, offered
, needed
);
4961 return getprinter_level_5(Printer
, snum
, buffer
, offered
, needed
);
4963 return getprinter_level_7(Printer
, snum
, buffer
, offered
, needed
);
4965 return WERR_UNKNOWN_LEVEL
;
4968 /********************************************************************
4969 * fill a DRIVER_INFO_1 struct
4970 ********************************************************************/
4972 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
4974 init_unistr( &info
->name
, driver
.info_3
->name
);
4977 /********************************************************************
4978 * construct_printer_driver_info_1
4979 ********************************************************************/
4981 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
4983 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4984 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
4986 ZERO_STRUCT(driver
);
4988 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
4989 return WERR_INVALID_PRINTER_NAME
;
4991 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
4992 free_a_printer(&printer
, 2);
4993 return WERR_UNKNOWN_PRINTER_DRIVER
;
4996 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
4998 free_a_printer(&printer
,2);
5003 /********************************************************************
5004 * construct_printer_driver_info_2
5005 * fill a printer_info_2 struct
5006 ********************************************************************/
5008 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5012 info
->version
=driver
.info_3
->cversion
;
5014 init_unistr( &info
->name
, driver
.info_3
->name
);
5015 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5018 if (strlen(driver
.info_3
->driverpath
)) {
5019 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5020 init_unistr( &info
->driverpath
, temp
);
5022 init_unistr( &info
->driverpath
, "" );
5024 if (strlen(driver
.info_3
->datafile
)) {
5025 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5026 init_unistr( &info
->datafile
, temp
);
5028 init_unistr( &info
->datafile
, "" );
5030 if (strlen(driver
.info_3
->configfile
)) {
5031 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5032 init_unistr( &info
->configfile
, temp
);
5034 init_unistr( &info
->configfile
, "" );
5037 /********************************************************************
5038 * construct_printer_driver_info_2
5039 * fill a printer_info_2 struct
5040 ********************************************************************/
5042 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5044 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5045 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5047 ZERO_STRUCT(printer
);
5048 ZERO_STRUCT(driver
);
5050 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5051 return WERR_INVALID_PRINTER_NAME
;
5053 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5054 free_a_printer(&printer
, 2);
5055 return WERR_UNKNOWN_PRINTER_DRIVER
;
5058 fill_printer_driver_info_2(info
, driver
, servername
);
5060 free_a_printer(&printer
,2);
5065 /********************************************************************
5066 * copy a strings array and convert to UNICODE
5068 * convert an array of ascii string to a UNICODE string
5069 ********************************************************************/
5071 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
5078 DEBUG(6,("init_unistr_array\n"));
5089 v
= ""; /* hack to handle null lists */
5092 /* hack to allow this to be used in places other than when generating
5093 the list of dependent files */
5096 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
5100 DEBUGADD(6,("%d:%s:%lu\n", i
, line
, (unsigned long)strlen(line
)));
5102 /* add one extra unit16 for the second terminating NULL */
5104 if ( (*uni_array
=SMB_REALLOC_ARRAY(*uni_array
, uint16
, j
+1+strlen(line
)+2)) == NULL
) {
5105 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5112 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
5117 /* special case for ""; we need to add both NULL's here */
5119 (*uni_array
)[j
++]=0x0000;
5120 (*uni_array
)[j
]=0x0000;
5123 DEBUGADD(6,("last one:done\n"));
5125 /* return size of array in uint16's */
5130 /********************************************************************
5131 * construct_printer_info_3
5132 * fill a printer_info_3 struct
5133 ********************************************************************/
5135 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5141 info
->version
=driver
.info_3
->cversion
;
5143 init_unistr( &info
->name
, driver
.info_3
->name
);
5144 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5146 if (strlen(driver
.info_3
->driverpath
)) {
5147 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5148 init_unistr( &info
->driverpath
, temp
);
5150 init_unistr( &info
->driverpath
, "" );
5152 if (strlen(driver
.info_3
->datafile
)) {
5153 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5154 init_unistr( &info
->datafile
, temp
);
5156 init_unistr( &info
->datafile
, "" );
5158 if (strlen(driver
.info_3
->configfile
)) {
5159 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5160 init_unistr( &info
->configfile
, temp
);
5162 init_unistr( &info
->configfile
, "" );
5164 if (strlen(driver
.info_3
->helpfile
)) {
5165 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5166 init_unistr( &info
->helpfile
, temp
);
5168 init_unistr( &info
->helpfile
, "" );
5170 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5171 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5173 info
->dependentfiles
=NULL
;
5174 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5177 /********************************************************************
5178 * construct_printer_info_3
5179 * fill a printer_info_3 struct
5180 ********************************************************************/
5182 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5184 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5185 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5187 ZERO_STRUCT(driver
);
5189 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5190 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5191 if (!W_ERROR_IS_OK(status
))
5192 return WERR_INVALID_PRINTER_NAME
;
5194 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5195 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5200 * I put this code in during testing. Helpful when commenting out the
5201 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5202 * as win2k always queries the driver using an infor level of 6.
5203 * I've left it in (but ifdef'd out) because I'll probably
5204 * use it in experimentation again in the future. --jerry 22/01/2002
5207 if (!W_ERROR_IS_OK(status
)) {
5209 * Is this a W2k client ?
5212 /* Yes - try again with a WinNT driver. */
5214 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5215 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5219 if (!W_ERROR_IS_OK(status
)) {
5220 free_a_printer(&printer
,2);
5221 return WERR_UNKNOWN_PRINTER_DRIVER
;
5229 fill_printer_driver_info_3(info
, driver
, servername
);
5231 free_a_printer(&printer
,2);
5236 /********************************************************************
5237 * construct_printer_info_6
5238 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5239 ********************************************************************/
5241 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5247 memset(&nullstr
, '\0', sizeof(fstring
));
5249 info
->version
=driver
.info_3
->cversion
;
5251 init_unistr( &info
->name
, driver
.info_3
->name
);
5252 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5254 if (strlen(driver
.info_3
->driverpath
)) {
5255 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5256 init_unistr( &info
->driverpath
, temp
);
5258 init_unistr( &info
->driverpath
, "" );
5260 if (strlen(driver
.info_3
->datafile
)) {
5261 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5262 init_unistr( &info
->datafile
, temp
);
5264 init_unistr( &info
->datafile
, "" );
5266 if (strlen(driver
.info_3
->configfile
)) {
5267 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5268 init_unistr( &info
->configfile
, temp
);
5270 init_unistr( &info
->configfile
, "" );
5272 if (strlen(driver
.info_3
->helpfile
)) {
5273 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5274 init_unistr( &info
->helpfile
, temp
);
5276 init_unistr( &info
->helpfile
, "" );
5278 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5279 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5281 info
->dependentfiles
= NULL
;
5282 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5284 info
->previousdrivernames
=NULL
;
5285 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5287 info
->driver_date
.low
=0;
5288 info
->driver_date
.high
=0;
5291 info
->driver_version_low
=0;
5292 info
->driver_version_high
=0;
5294 init_unistr( &info
->mfgname
, "");
5295 init_unistr( &info
->oem_url
, "");
5296 init_unistr( &info
->hardware_id
, "");
5297 init_unistr( &info
->provider
, "");
5300 /********************************************************************
5301 * construct_printer_info_6
5302 * fill a printer_info_6 struct
5303 ********************************************************************/
5305 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5306 fstring servername
, fstring architecture
, uint32 version
)
5308 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5309 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5312 ZERO_STRUCT(driver
);
5314 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5316 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5318 if (!W_ERROR_IS_OK(status
))
5319 return WERR_INVALID_PRINTER_NAME
;
5321 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5323 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5325 if (!W_ERROR_IS_OK(status
))
5328 * Is this a W2k client ?
5332 free_a_printer(&printer
,2);
5333 return WERR_UNKNOWN_PRINTER_DRIVER
;
5336 /* Yes - try again with a WinNT driver. */
5338 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5339 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5340 if (!W_ERROR_IS_OK(status
)) {
5341 free_a_printer(&printer
,2);
5342 return WERR_UNKNOWN_PRINTER_DRIVER
;
5346 fill_printer_driver_info_6(info
, driver
, servername
);
5348 free_a_printer(&printer
,2);
5349 free_a_printer_driver(driver
, 3);
5354 /****************************************************************************
5355 ****************************************************************************/
5357 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5359 SAFE_FREE(info
->dependentfiles
);
5362 /****************************************************************************
5363 ****************************************************************************/
5365 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5367 SAFE_FREE(info
->dependentfiles
);
5370 /****************************************************************************
5371 ****************************************************************************/
5373 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5375 DRIVER_INFO_1
*info
=NULL
;
5378 if((info
=SMB_MALLOC_P(DRIVER_INFO_1
)) == NULL
)
5381 result
= construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5382 if (!W_ERROR_IS_OK(result
))
5385 /* check the required size. */
5386 *needed
+= spoolss_size_printer_driver_info_1(info
);
5388 if (*needed
> offered
) {
5389 result
= WERR_INSUFFICIENT_BUFFER
;
5393 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5394 result
= WERR_NOMEM
;
5398 /* fill the buffer with the structures */
5399 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5408 /****************************************************************************
5409 ****************************************************************************/
5411 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5413 DRIVER_INFO_2
*info
=NULL
;
5416 if((info
=SMB_MALLOC_P(DRIVER_INFO_2
)) == NULL
)
5419 result
= construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5420 if (!W_ERROR_IS_OK(result
))
5423 /* check the required size. */
5424 *needed
+= spoolss_size_printer_driver_info_2(info
);
5426 if (*needed
> offered
) {
5427 result
= WERR_INSUFFICIENT_BUFFER
;
5431 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5432 result
= WERR_NOMEM
;
5436 /* fill the buffer with the structures */
5437 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5446 /****************************************************************************
5447 ****************************************************************************/
5449 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5456 result
= construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5457 if (!W_ERROR_IS_OK(result
))
5460 /* check the required size. */
5461 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5463 if (*needed
> offered
) {
5464 result
= WERR_INSUFFICIENT_BUFFER
;
5468 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5469 result
= WERR_NOMEM
;
5473 /* fill the buffer with the structures */
5474 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5477 free_printer_driver_info_3(&info
);
5482 /****************************************************************************
5483 ****************************************************************************/
5485 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5492 result
= construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5493 if (!W_ERROR_IS_OK(result
))
5496 /* check the required size. */
5497 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5499 if (*needed
> offered
) {
5500 result
= WERR_INSUFFICIENT_BUFFER
;
5504 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5505 result
= WERR_NOMEM
;
5509 /* fill the buffer with the structures */
5510 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5513 free_printer_driver_info_6(&info
);
5518 /****************************************************************************
5519 ****************************************************************************/
5521 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5523 POLICY_HND
*handle
= &q_u
->handle
;
5524 UNISTR2
*uni_arch
= &q_u
->architecture
;
5525 uint32 level
= q_u
->level
;
5526 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5527 RPC_BUFFER
*buffer
= NULL
;
5528 uint32 offered
= q_u
->offered
;
5529 uint32
*needed
= &r_u
->needed
;
5530 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5531 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5532 Printer_entry
*printer
;
5535 fstring architecture
;
5538 /* that's an [in out] buffer */
5540 if (!q_u
->buffer
&& (offered
!=0)) {
5541 return WERR_INVALID_PARAM
;
5544 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5545 buffer
= r_u
->buffer
;
5547 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5549 if ( !(printer
= find_printer_index_by_hnd( p
, handle
)) ) {
5550 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5551 return WERR_INVALID_PRINTER_NAME
;
5555 *servermajorversion
= 0;
5556 *serverminorversion
= 0;
5558 fstrcpy(servername
, get_server_name( printer
));
5559 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5561 if (!get_printer_snum(p
, handle
, &snum
))
5566 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5568 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5570 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5572 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5575 /* apparently this call is the equivalent of
5576 EnumPrinterDataEx() for the DsDriver key */
5581 return WERR_UNKNOWN_LEVEL
;
5584 /****************************************************************************
5585 ****************************************************************************/
5587 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5589 POLICY_HND
*handle
= &q_u
->handle
;
5591 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5594 DEBUG(3,("Error in startpageprinter printer handle\n"));
5598 Printer
->page_started
=True
;
5602 /****************************************************************************
5603 ****************************************************************************/
5605 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5607 POLICY_HND
*handle
= &q_u
->handle
;
5610 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5613 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5617 if (!get_printer_snum(p
, handle
, &snum
))
5620 Printer
->page_started
=False
;
5621 print_job_endpage(snum
, Printer
->jobid
);
5626 /********************************************************************
5627 * api_spoolss_getprinter
5628 * called from the spoolss dispatcher
5630 ********************************************************************/
5632 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5634 POLICY_HND
*handle
= &q_u
->handle
;
5635 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5636 uint32
*jobid
= &r_u
->jobid
;
5638 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5642 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5645 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5650 * a nice thing with NT is it doesn't listen to what you tell it.
5651 * when asked to send _only_ RAW datas, it tries to send datas
5654 * So I add checks like in NT Server ...
5657 if (info_1
->p_datatype
!= 0) {
5658 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5659 if (strcmp(datatype
, "RAW") != 0) {
5661 return WERR_INVALID_DATATYPE
;
5665 /* get the share number of the printer */
5666 if (!get_printer_snum(p
, handle
, &snum
)) {
5670 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5672 Printer
->jobid
= print_job_start(&p
->pipe_user
, snum
, jobname
, Printer
->nt_devmode
);
5674 /* An error occured in print_job_start() so return an appropriate
5677 if (Printer
->jobid
== -1) {
5678 return map_werror_from_unix(errno
);
5681 Printer
->document_started
=True
;
5682 (*jobid
) = Printer
->jobid
;
5687 /********************************************************************
5688 * api_spoolss_getprinter
5689 * called from the spoolss dispatcher
5691 ********************************************************************/
5693 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5695 POLICY_HND
*handle
= &q_u
->handle
;
5697 return _spoolss_enddocprinter_internal(p
, handle
);
5700 /****************************************************************************
5701 ****************************************************************************/
5703 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5705 POLICY_HND
*handle
= &q_u
->handle
;
5706 uint32 buffer_size
= q_u
->buffer_size
;
5707 uint8
*buffer
= q_u
->buffer
;
5708 uint32
*buffer_written
= &q_u
->buffer_size2
;
5710 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5713 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5714 r_u
->buffer_written
= q_u
->buffer_size2
;
5718 if (!get_printer_snum(p
, handle
, &snum
))
5721 (*buffer_written
) = (uint32
)print_job_write(snum
, Printer
->jobid
, (const char *)buffer
,
5722 (SMB_OFF_T
)-1, (size_t)buffer_size
);
5723 if (*buffer_written
== (uint32
)-1) {
5724 r_u
->buffer_written
= 0;
5725 if (errno
== ENOSPC
)
5726 return WERR_NO_SPOOL_SPACE
;
5728 return WERR_ACCESS_DENIED
;
5731 r_u
->buffer_written
= q_u
->buffer_size2
;
5736 /********************************************************************
5737 * api_spoolss_getprinter
5738 * called from the spoolss dispatcher
5740 ********************************************************************/
5742 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5746 WERROR errcode
= WERR_BADFUNC
;
5747 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5750 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5754 if (!get_printer_snum(p
, handle
, &snum
))
5758 case PRINTER_CONTROL_PAUSE
:
5759 if (print_queue_pause(&p
->pipe_user
, snum
, &errcode
)) {
5763 case PRINTER_CONTROL_RESUME
:
5764 case PRINTER_CONTROL_UNPAUSE
:
5765 if (print_queue_resume(&p
->pipe_user
, snum
, &errcode
)) {
5769 case PRINTER_CONTROL_PURGE
:
5770 if (print_queue_purge(&p
->pipe_user
, snum
, &errcode
)) {
5775 return WERR_UNKNOWN_LEVEL
;
5781 /********************************************************************
5782 * api_spoolss_abortprinter
5783 * From MSDN: "Deletes printer's spool file if printer is configured
5785 ********************************************************************/
5787 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5789 POLICY_HND
*handle
= &q_u
->handle
;
5790 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5792 WERROR errcode
= WERR_OK
;
5795 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5799 if (!get_printer_snum(p
, handle
, &snum
))
5802 print_job_delete( &p
->pipe_user
, snum
, Printer
->jobid
, &errcode
);
5807 /********************************************************************
5808 * called by spoolss_api_setprinter
5809 * when updating a printer description
5810 ********************************************************************/
5812 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5813 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5814 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5816 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5820 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5822 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5823 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5824 OUR_HANDLE(handle
)));
5826 result
= WERR_BADFID
;
5830 /* Check the user has permissions to change the security
5831 descriptor. By experimentation with two NT machines, the user
5832 requires Full Access to the printer to change security
5835 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5836 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5837 result
= WERR_ACCESS_DENIED
;
5841 /* NT seems to like setting the security descriptor even though
5842 nothing may have actually changed. */
5844 nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
);
5846 if (DEBUGLEVEL
>= 10) {
5850 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5851 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5852 PRINTERNAME(snum
), the_acl
->num_aces
));
5854 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5857 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5859 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5860 the_acl
->ace
[i
].info
.mask
));
5863 the_acl
= secdesc_ctr
->sec
->dacl
;
5866 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5867 PRINTERNAME(snum
), the_acl
->num_aces
));
5869 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5872 sid_to_string(sid_str
, &the_acl
->ace
[i
].trustee
);
5874 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5875 the_acl
->ace
[i
].info
.mask
));
5878 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5882 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5883 if (!new_secdesc_ctr
) {
5884 result
= WERR_NOMEM
;
5888 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5893 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5900 /********************************************************************
5901 Canonicalize printer info from a client
5903 ATTN: It does not matter what we set the servername to hear
5904 since we do the necessary work in get_a_printer() to set it to
5905 the correct value based on what the client sent in the
5906 _spoolss_open_printer_ex().
5907 ********************************************************************/
5909 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5911 fstring printername
;
5914 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5915 "portname=%s drivername=%s comment=%s location=%s\n",
5916 info
->servername
, info
->printername
, info
->sharename
,
5917 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5919 /* we force some elements to "correct" values */
5920 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5921 fstrcpy(info
->sharename
, lp_servicename(snum
));
5923 /* check to see if we allow printername != sharename */
5925 if ( lp_force_printername(snum
) ) {
5926 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5927 global_myname(), info
->sharename
);
5930 /* make sure printername is in \\server\printername format */
5932 fstrcpy( printername
, info
->printername
);
5934 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5935 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5939 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5940 global_myname(), p
);
5943 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5944 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5951 /****************************************************************************
5952 ****************************************************************************/
5954 WERROR
add_port_hook(NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
5956 char *cmd
= lp_addport_cmd();
5960 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5961 BOOL is_print_op
= False
;
5964 return WERR_ACCESS_DENIED
;
5967 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
5970 is_print_op
= user_has_privileges( token
, &se_printop
);
5972 DEBUG(10,("Running [%s]\n", command
));
5974 /********* BEGIN SePrintOperatorPrivilege **********/
5979 ret
= smbrun(command
, &fd
);
5984 /********* END SePrintOperatorPrivilege **********/
5986 DEBUGADD(10,("returned [%d]\n", ret
));
5991 return WERR_ACCESS_DENIED
;
5997 /****************************************************************************
5998 ****************************************************************************/
6000 BOOL
add_printer_hook(NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
6002 char *cmd
= lp_addprinter_cmd();
6008 fstring remote_machine
= "%m";
6009 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
6010 BOOL is_print_op
= False
;
6012 standard_sub_basic(current_user_info
.smb_name
,
6013 current_user_info
.domain
,
6014 remote_machine
,sizeof(remote_machine
));
6016 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6017 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
6018 printer
->info_2
->portname
, printer
->info_2
->drivername
,
6019 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
6022 is_print_op
= user_has_privileges( token
, &se_printop
);
6024 DEBUG(10,("Running [%s]\n", command
));
6026 /********* BEGIN SePrintOperatorPrivilege **********/
6031 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6032 /* Tell everyone we updated smb.conf. */
6033 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
6039 /********* END SePrintOperatorPrivilege **********/
6041 DEBUGADD(10,("returned [%d]\n", ret
));
6049 /* reload our services immediately */
6050 reload_services( False
);
6053 /* Get lines and convert them back to dos-codepage */
6054 qlines
= fd_lines_load(fd
, &numlines
, 0);
6055 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6058 /* Set the portname to what the script says the portname should be. */
6059 /* but don't require anything to be return from the script exit a good error code */
6062 /* Set the portname to what the script says the portname should be. */
6063 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
6064 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6067 file_lines_free(qlines
);
6072 /********************************************************************
6073 * Called by spoolss_api_setprinter
6074 * when updating a printer description.
6075 ********************************************************************/
6077 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
6078 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6079 DEVICEMODE
*devmode
)
6082 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6083 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6088 DEBUG(8,("update_printer\n"));
6093 result
= WERR_BADFID
;
6097 if (!get_printer_snum(p
, handle
, &snum
)) {
6098 result
= WERR_BADFID
;
6102 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6103 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6104 result
= WERR_BADFID
;
6108 DEBUGADD(8,("Converting info_2 struct\n"));
6111 * convert_printer_info converts the incoming
6112 * info from the client and overwrites the info
6113 * just read from the tdb in the pointer 'printer'.
6116 if (!convert_printer_info(info
, printer
, level
)) {
6117 result
= WERR_NOMEM
;
6122 /* we have a valid devmode
6123 convert it and link it*/
6125 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6126 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6127 &printer
->info_2
->devmode
)) {
6128 result
= WERR_NOMEM
;
6133 /* Do sanity check on the requested changes for Samba */
6135 if (!check_printer_ok(printer
->info_2
, snum
)) {
6136 result
= WERR_INVALID_PARAM
;
6140 /* FIXME!!! If the driver has changed we really should verify that
6141 it is installed before doing much else --jerry */
6143 /* Check calling user has permission to update printer description */
6145 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6146 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6147 result
= WERR_ACCESS_DENIED
;
6151 /* Call addprinter hook */
6152 /* Check changes to see if this is really needed */
6154 if ( *lp_addprinter_cmd()
6155 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6156 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6157 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6158 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6160 /* add_printer_hook() will call reload_services() */
6162 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
6163 result
= WERR_ACCESS_DENIED
;
6169 * When a *new* driver is bound to a printer, the drivername is used to
6170 * lookup previously saved driver initialization info, which is then
6171 * bound to the printer, simulating what happens in the Windows arch.
6173 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6175 if (!set_driver_init(printer
, 2))
6177 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6178 printer
->info_2
->drivername
));
6181 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6182 printer
->info_2
->drivername
));
6184 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6188 * flag which changes actually occured. This is a small subset of
6189 * all the possible changes. We also have to update things in the
6193 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6194 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6195 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6196 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6198 notify_printer_comment(snum
, printer
->info_2
->comment
);
6201 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6202 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6203 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6204 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6206 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6209 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6212 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6215 pname
= printer
->info_2
->printername
;
6218 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6219 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6220 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6222 notify_printer_printername( snum
, pname
);
6225 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6226 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6227 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6228 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6230 notify_printer_port(snum
, printer
->info_2
->portname
);
6233 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6234 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6235 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6236 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6238 notify_printer_location(snum
, printer
->info_2
->location
);
6241 /* here we need to update some more DsSpooler keys */
6242 /* uNCName, serverName, shortServerName */
6244 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6245 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6246 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6247 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6248 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6250 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6251 global_myname(), printer
->info_2
->sharename
);
6252 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6253 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6254 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6256 /* Update printer info */
6257 result
= mod_a_printer(printer
, 2);
6260 free_a_printer(&printer
, 2);
6261 free_a_printer(&old_printer
, 2);
6267 /****************************************************************************
6268 ****************************************************************************/
6269 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6270 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6273 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6275 Printer_entry
*Printer
;
6277 if ( lp_security() != SEC_ADS
) {
6278 return WERR_UNKNOWN_LEVEL
;
6281 Printer
= find_printer_index_by_hnd(p
, handle
);
6283 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6288 if (!get_printer_snum(p
, handle
, &snum
))
6291 nt_printer_publish(Printer
, snum
, info7
->action
);
6295 return WERR_UNKNOWN_LEVEL
;
6298 /****************************************************************************
6299 ****************************************************************************/
6301 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6303 POLICY_HND
*handle
= &q_u
->handle
;
6304 uint32 level
= q_u
->level
;
6305 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6306 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6307 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6308 uint32 command
= q_u
->command
;
6311 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6314 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6318 /* check the level */
6321 return control_printer(handle
, command
, p
);
6323 result
= update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6324 if (!W_ERROR_IS_OK(result
))
6327 result
= update_printer_sec(handle
, level
, info
, p
, secdesc_ctr
);
6330 return update_printer_sec(handle
, level
, info
, p
,
6333 return publish_or_unpublish_printer(p
, handle
, info
);
6335 return WERR_UNKNOWN_LEVEL
;
6339 /****************************************************************************
6340 ****************************************************************************/
6342 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6344 POLICY_HND
*handle
= &q_u
->handle
;
6345 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6348 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6352 if (Printer
->notify
.client_connected
==True
) {
6355 if ( Printer
->printer_type
== SPLHND_SERVER
)
6357 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
6358 !get_printer_snum(p
, handle
, &snum
) )
6361 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6364 Printer
->notify
.flags
=0;
6365 Printer
->notify
.options
=0;
6366 Printer
->notify
.localmachine
[0]='\0';
6367 Printer
->notify
.printerlocal
=0;
6368 if (Printer
->notify
.option
)
6369 free_spool_notify_option(&Printer
->notify
.option
);
6370 Printer
->notify
.client_connected
=False
;
6375 /****************************************************************************
6376 ****************************************************************************/
6378 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6380 /* that's an [in out] buffer */
6382 if (!q_u
->buffer
&& (q_u
->offered
!=0)) {
6383 return WERR_INVALID_PARAM
;
6386 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6389 return WERR_INVALID_PARAM
; /* this is what a NT server
6390 returns for AddJob. AddJob
6391 must fail on non-local
6395 /****************************************************************************
6396 ****************************************************************************/
6398 static void fill_job_info_1(JOB_INFO_1
*job_info
, print_queue_struct
*queue
,
6399 int position
, int snum
,
6400 NT_PRINTER_INFO_LEVEL
*ntprinter
)
6404 t
=gmtime(&queue
->time
);
6406 job_info
->jobid
=queue
->job
;
6407 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6408 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6409 init_unistr(&job_info
->username
, queue
->fs_user
);
6410 init_unistr(&job_info
->document
, queue
->fs_file
);
6411 init_unistr(&job_info
->datatype
, "RAW");
6412 init_unistr(&job_info
->text_status
, "");
6413 job_info
->status
=nt_printj_status(queue
->status
);
6414 job_info
->priority
=queue
->priority
;
6415 job_info
->position
=position
;
6416 job_info
->totalpages
=queue
->page_count
;
6417 job_info
->pagesprinted
=0;
6419 make_systemtime(&job_info
->submitted
, t
);
6422 /****************************************************************************
6423 ****************************************************************************/
6425 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, print_queue_struct
*queue
,
6426 int position
, int snum
,
6427 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6428 DEVICEMODE
*devmode
)
6432 t
=gmtime(&queue
->time
);
6434 job_info
->jobid
=queue
->job
;
6436 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6438 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6439 init_unistr(&job_info
->username
, queue
->fs_user
);
6440 init_unistr(&job_info
->document
, queue
->fs_file
);
6441 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6442 init_unistr(&job_info
->datatype
, "RAW");
6443 init_unistr(&job_info
->printprocessor
, "winprint");
6444 init_unistr(&job_info
->parameters
, "");
6445 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6446 init_unistr(&job_info
->text_status
, "");
6448 /* and here the security descriptor */
6450 job_info
->status
=nt_printj_status(queue
->status
);
6451 job_info
->priority
=queue
->priority
;
6452 job_info
->position
=position
;
6453 job_info
->starttime
=0;
6454 job_info
->untiltime
=0;
6455 job_info
->totalpages
=queue
->page_count
;
6456 job_info
->size
=queue
->size
;
6457 make_systemtime(&(job_info
->submitted
), t
);
6458 job_info
->timeelapsed
=0;
6459 job_info
->pagesprinted
=0;
6461 job_info
->devmode
= devmode
;
6466 /****************************************************************************
6467 Enumjobs at level 1.
6468 ****************************************************************************/
6470 static WERROR
enumjobs_level1(print_queue_struct
*queue
, int snum
,
6471 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6472 RPC_BUFFER
*buffer
, uint32 offered
,
6473 uint32
*needed
, uint32
*returned
)
6477 WERROR result
= WERR_OK
;
6479 info
=SMB_MALLOC_ARRAY(JOB_INFO_1
,*returned
);
6486 for (i
=0; i
<*returned
; i
++)
6487 fill_job_info_1( &info
[i
], &queue
[i
], i
, snum
, ntprinter
);
6491 /* check the required size. */
6492 for (i
=0; i
<*returned
; i
++)
6493 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6495 if (*needed
> offered
) {
6496 result
= WERR_INSUFFICIENT_BUFFER
;
6500 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6501 result
= WERR_NOMEM
;
6505 /* fill the buffer with the structures */
6506 for (i
=0; i
<*returned
; i
++)
6507 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6513 if ( !W_ERROR_IS_OK(result
) )
6519 /****************************************************************************
6520 Enumjobs at level 2.
6521 ****************************************************************************/
6523 static WERROR
enumjobs_level2(print_queue_struct
*queue
, int snum
,
6524 NT_PRINTER_INFO_LEVEL
*ntprinter
,
6525 RPC_BUFFER
*buffer
, uint32 offered
,
6526 uint32
*needed
, uint32
*returned
)
6528 JOB_INFO_2
*info
= NULL
;
6530 WERROR result
= WERR_OK
;
6531 DEVICEMODE
*devmode
= NULL
;
6533 if ( !(info
= SMB_MALLOC_ARRAY(JOB_INFO_2
,*returned
)) ) {
6538 /* this should not be a failure condition if the devmode is NULL */
6540 devmode
= construct_dev_mode(lp_const_servicename(snum
));
6542 for (i
=0; i
<*returned
; i
++)
6543 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
, devmode
);
6545 free_a_printer(&ntprinter
, 2);
6548 /* check the required size. */
6549 for (i
=0; i
<*returned
; i
++)
6550 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6552 if (*needed
> offered
) {
6553 result
= WERR_INSUFFICIENT_BUFFER
;
6557 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6558 result
= WERR_NOMEM
;
6562 /* fill the buffer with the structures */
6563 for (i
=0; i
<*returned
; i
++)
6564 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6567 free_devmode(devmode
);
6570 if ( !W_ERROR_IS_OK(result
) )
6577 /****************************************************************************
6579 ****************************************************************************/
6581 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6583 POLICY_HND
*handle
= &q_u
->handle
;
6584 uint32 level
= q_u
->level
;
6585 RPC_BUFFER
*buffer
= NULL
;
6586 uint32 offered
= q_u
->offered
;
6587 uint32
*needed
= &r_u
->needed
;
6588 uint32
*returned
= &r_u
->returned
;
6590 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6592 print_status_struct prt_status
;
6593 print_queue_struct
*queue
=NULL
;
6595 /* that's an [in out] buffer */
6597 if (!q_u
->buffer
&& (offered
!=0)) {
6598 return WERR_INVALID_PARAM
;
6601 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6602 buffer
= r_u
->buffer
;
6604 DEBUG(4,("_spoolss_enumjobs\n"));
6609 /* lookup the printer snum and tdb entry */
6611 if (!get_printer_snum(p
, handle
, &snum
))
6614 wret
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6615 if ( !W_ERROR_IS_OK(wret
) )
6618 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6619 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6621 if (*returned
== 0) {
6623 free_a_printer(&ntprinter
, 2);
6629 wret
= enumjobs_level1(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6632 wret
= enumjobs_level2(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6636 wret
= WERR_UNKNOWN_LEVEL
;
6641 free_a_printer( &ntprinter
, 2 );
6645 /****************************************************************************
6646 ****************************************************************************/
6648 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6653 /****************************************************************************
6654 ****************************************************************************/
6656 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6658 POLICY_HND
*handle
= &q_u
->handle
;
6659 uint32 jobid
= q_u
->jobid
;
6660 uint32 command
= q_u
->command
;
6663 WERROR errcode
= WERR_BADFUNC
;
6665 if (!get_printer_snum(p
, handle
, &snum
)) {
6669 if (!print_job_exists(lp_const_servicename(snum
), jobid
)) {
6670 return WERR_INVALID_PRINTER_NAME
;
6674 case JOB_CONTROL_CANCEL
:
6675 case JOB_CONTROL_DELETE
:
6676 if (print_job_delete(&p
->pipe_user
, snum
, jobid
, &errcode
)) {
6680 case JOB_CONTROL_PAUSE
:
6681 if (print_job_pause(&p
->pipe_user
, snum
, jobid
, &errcode
)) {
6685 case JOB_CONTROL_RESTART
:
6686 case JOB_CONTROL_RESUME
:
6687 if (print_job_resume(&p
->pipe_user
, snum
, jobid
, &errcode
)) {
6692 return WERR_UNKNOWN_LEVEL
;
6698 /****************************************************************************
6699 Enumerates all printer drivers at level 1.
6700 ****************************************************************************/
6702 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6707 fstring
*list
= NULL
;
6708 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6709 DRIVER_INFO_1
*driver_info_1
=NULL
;
6710 WERROR result
= WERR_OK
;
6714 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6716 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6717 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6719 if(ndrivers
== -1) {
6720 SAFE_FREE(driver_info_1
);
6725 if((driver_info_1
=SMB_REALLOC_ARRAY(driver_info_1
, DRIVER_INFO_1
, *returned
+ndrivers
)) == NULL
) {
6726 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6732 for (i
=0; i
<ndrivers
; i
++) {
6734 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6735 ZERO_STRUCT(driver
);
6736 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6737 architecture
, version
);
6738 if (!W_ERROR_IS_OK(status
)) {
6740 SAFE_FREE(driver_info_1
);
6743 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6744 free_a_printer_driver(driver
, 3);
6747 *returned
+=ndrivers
;
6751 /* check the required size. */
6752 for (i
=0; i
<*returned
; i
++) {
6753 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6754 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6757 if (*needed
> offered
) {
6758 result
= WERR_INSUFFICIENT_BUFFER
;
6762 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6763 result
= WERR_NOMEM
;
6767 /* fill the buffer with the driver structures */
6768 for (i
=0; i
<*returned
; i
++) {
6769 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6770 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6774 SAFE_FREE(driver_info_1
);
6776 if ( !W_ERROR_IS_OK(result
) )
6782 /****************************************************************************
6783 Enumerates all printer drivers at level 2.
6784 ****************************************************************************/
6786 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6791 fstring
*list
= NULL
;
6792 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6793 DRIVER_INFO_2
*driver_info_2
=NULL
;
6794 WERROR result
= WERR_OK
;
6798 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6800 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6801 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6803 if(ndrivers
== -1) {
6804 SAFE_FREE(driver_info_2
);
6809 if((driver_info_2
=SMB_REALLOC_ARRAY(driver_info_2
, DRIVER_INFO_2
, *returned
+ndrivers
)) == NULL
) {
6810 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6816 for (i
=0; i
<ndrivers
; i
++) {
6819 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6820 ZERO_STRUCT(driver
);
6821 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6822 architecture
, version
);
6823 if (!W_ERROR_IS_OK(status
)) {
6825 SAFE_FREE(driver_info_2
);
6828 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6829 free_a_printer_driver(driver
, 3);
6832 *returned
+=ndrivers
;
6836 /* check the required size. */
6837 for (i
=0; i
<*returned
; i
++) {
6838 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6839 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6842 if (*needed
> offered
) {
6843 result
= WERR_INSUFFICIENT_BUFFER
;
6847 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6848 result
= WERR_NOMEM
;
6852 /* fill the buffer with the form structures */
6853 for (i
=0; i
<*returned
; i
++) {
6854 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6855 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6859 SAFE_FREE(driver_info_2
);
6861 if ( !W_ERROR_IS_OK(result
) )
6867 /****************************************************************************
6868 Enumerates all printer drivers at level 3.
6869 ****************************************************************************/
6871 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6876 fstring
*list
= NULL
;
6877 DRIVER_INFO_3
*driver_info_3
=NULL
;
6878 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6879 WERROR result
= WERR_OK
;
6883 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6885 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6886 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6888 if(ndrivers
== -1) {
6889 SAFE_FREE(driver_info_3
);
6894 if((driver_info_3
=SMB_REALLOC_ARRAY(driver_info_3
, DRIVER_INFO_3
, *returned
+ndrivers
)) == NULL
) {
6895 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6901 for (i
=0; i
<ndrivers
; i
++) {
6904 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6905 ZERO_STRUCT(driver
);
6906 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6907 architecture
, version
);
6908 if (!W_ERROR_IS_OK(status
)) {
6910 SAFE_FREE(driver_info_3
);
6913 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
6914 free_a_printer_driver(driver
, 3);
6917 *returned
+=ndrivers
;
6921 /* check the required size. */
6922 for (i
=0; i
<*returned
; i
++) {
6923 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6924 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
6927 if (*needed
> offered
) {
6928 result
= WERR_INSUFFICIENT_BUFFER
;
6932 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6933 result
= WERR_NOMEM
;
6937 /* fill the buffer with the driver structures */
6938 for (i
=0; i
<*returned
; i
++) {
6939 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6940 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
6944 for (i
=0; i
<*returned
; i
++) {
6945 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
6948 SAFE_FREE(driver_info_3
);
6950 if ( !W_ERROR_IS_OK(result
) )
6956 /****************************************************************************
6957 Enumerates all printer drivers.
6958 ****************************************************************************/
6960 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
6962 uint32 level
= q_u
->level
;
6963 RPC_BUFFER
*buffer
= NULL
;
6964 uint32 offered
= q_u
->offered
;
6965 uint32
*needed
= &r_u
->needed
;
6966 uint32
*returned
= &r_u
->returned
;
6969 fstring architecture
;
6971 /* that's an [in out] buffer */
6973 if (!q_u
->buffer
&& (offered
!=0)) {
6974 return WERR_INVALID_PARAM
;
6977 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6978 buffer
= r_u
->buffer
;
6980 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
6985 unistr2_to_ascii(architecture
, &q_u
->environment
, sizeof(architecture
)-1);
6986 unistr2_to_ascii(servername
, &q_u
->name
, sizeof(servername
)-1);
6988 if ( !is_myname_or_ipaddr( servername
) )
6989 return WERR_UNKNOWN_PRINTER_DRIVER
;
6993 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
6995 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
6997 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
6999 return WERR_UNKNOWN_LEVEL
;
7003 /****************************************************************************
7004 ****************************************************************************/
7006 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
7008 form
->flag
=list
->flag
;
7009 init_unistr(&form
->name
, list
->name
);
7010 form
->width
=list
->width
;
7011 form
->length
=list
->length
;
7012 form
->left
=list
->left
;
7013 form
->top
=list
->top
;
7014 form
->right
=list
->right
;
7015 form
->bottom
=list
->bottom
;
7018 /****************************************************************************
7019 ****************************************************************************/
7021 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
7023 uint32 level
= q_u
->level
;
7024 RPC_BUFFER
*buffer
= NULL
;
7025 uint32 offered
= q_u
->offered
;
7026 uint32
*needed
= &r_u
->needed
;
7027 uint32
*numofforms
= &r_u
->numofforms
;
7028 uint32 numbuiltinforms
;
7030 nt_forms_struct
*list
=NULL
;
7031 nt_forms_struct
*builtinlist
=NULL
;
7036 /* that's an [in out] buffer */
7038 if (!q_u
->buffer
&& (offered
!=0) ) {
7039 return WERR_INVALID_PARAM
;
7042 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7043 buffer
= r_u
->buffer
;
7045 DEBUG(4,("_spoolss_enumforms\n"));
7046 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7047 DEBUGADD(5,("Info level [%d]\n", level
));
7049 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
7050 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
7051 *numofforms
= get_ntforms(&list
);
7052 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
7053 *numofforms
+= numbuiltinforms
;
7055 if (*numofforms
== 0) {
7056 SAFE_FREE(builtinlist
);
7058 return WERR_NO_MORE_ITEMS
;
7063 if ((forms_1
=SMB_MALLOC_ARRAY(FORM_1
, *numofforms
)) == NULL
) {
7064 SAFE_FREE(builtinlist
);
7070 /* construct the list of form structures */
7071 for (i
=0; i
<numbuiltinforms
; i
++) {
7072 DEBUGADD(6,("Filling form number [%d]\n",i
));
7073 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
7076 SAFE_FREE(builtinlist
);
7078 for (; i
<*numofforms
; i
++) {
7079 DEBUGADD(6,("Filling form number [%d]\n",i
));
7080 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
7085 /* check the required size. */
7086 for (i
=0; i
<numbuiltinforms
; i
++) {
7087 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7088 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7090 for (; i
<*numofforms
; i
++) {
7091 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7092 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7095 *needed
=buffer_size
;
7097 if (*needed
> offered
) {
7100 return WERR_INSUFFICIENT_BUFFER
;
7103 if (!rpcbuf_alloc_size(buffer
, buffer_size
)){
7109 /* fill the buffer with the form structures */
7110 for (i
=0; i
<numbuiltinforms
; i
++) {
7111 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7112 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7114 for (; i
<*numofforms
; i
++) {
7115 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7116 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7125 SAFE_FREE(builtinlist
);
7126 return WERR_UNKNOWN_LEVEL
;
7130 /****************************************************************************
7131 ****************************************************************************/
7133 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
7135 uint32 level
= q_u
->level
;
7136 UNISTR2
*uni_formname
= &q_u
->formname
;
7137 RPC_BUFFER
*buffer
= NULL
;
7138 uint32 offered
= q_u
->offered
;
7139 uint32
*needed
= &r_u
->needed
;
7141 nt_forms_struct
*list
=NULL
;
7142 nt_forms_struct builtin_form
;
7147 int numofforms
=0, i
=0;
7149 /* that's an [in out] buffer */
7151 if (!q_u
->buffer
&& (offered
!=0)) {
7152 return WERR_INVALID_PARAM
;
7155 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7156 buffer
= r_u
->buffer
;
7158 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
7160 DEBUG(4,("_spoolss_getform\n"));
7161 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7162 DEBUGADD(5,("Info level [%d]\n", level
));
7164 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
7165 if (!foundBuiltin
) {
7166 numofforms
= get_ntforms(&list
);
7167 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
7169 if (numofforms
== 0)
7176 fill_form_1(&form_1
, &builtin_form
);
7179 /* Check if the requested name is in the list of form structures */
7180 for (i
=0; i
<numofforms
; i
++) {
7182 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
7184 if (strequal(form_name
, list
[i
].name
)) {
7185 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
7186 fill_form_1(&form_1
, &list
[i
]);
7192 if (i
== numofforms
) {
7196 /* check the required size. */
7198 *needed
=spoolss_size_form_1(&form_1
);
7200 if (*needed
> offered
)
7201 return WERR_INSUFFICIENT_BUFFER
;
7203 if (!rpcbuf_alloc_size(buffer
, buffer_size
))
7206 /* fill the buffer with the form structures */
7207 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
7208 smb_io_form_1("", buffer
, &form_1
, 0);
7214 return WERR_UNKNOWN_LEVEL
;
7218 /****************************************************************************
7219 ****************************************************************************/
7221 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
7223 init_unistr(&port
->port_name
, name
);
7226 /****************************************************************************
7227 TODO: This probably needs distinguish between TCP/IP and Local ports
7229 ****************************************************************************/
7231 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
7233 init_unistr(&port
->port_name
, name
);
7234 init_unistr(&port
->monitor_name
, "Local Monitor");
7235 init_unistr(&port
->description
, SPL_LOCAL_PORT
);
7236 port
->port_type
=PORT_TYPE_WRITE
;
7241 /****************************************************************************
7242 wrapper around the enumer ports command
7243 ****************************************************************************/
7245 WERROR
enumports_hook( int *count
, char ***lines
)
7247 char *cmd
= lp_enumports_cmd();
7257 /* if no hook then just fill in the default port */
7260 qlines
= SMB_MALLOC_ARRAY( char*, 2 );
7261 qlines
[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME
);
7266 /* we have a valid enumport command */
7268 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
7270 DEBUG(10,("Running [%s]\n", command
));
7271 ret
= smbrun(command
, &fd
);
7272 DEBUG(10,("Returned [%d]\n", ret
));
7277 return WERR_ACCESS_DENIED
;
7281 qlines
= fd_lines_load(fd
, &numlines
, 0);
7282 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7292 /****************************************************************************
7294 ****************************************************************************/
7296 static WERROR
enumports_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7298 PORT_INFO_1
*ports
=NULL
;
7300 WERROR result
= WERR_OK
;
7301 char **qlines
= NULL
;
7304 result
= enumports_hook( &numlines
, &qlines
);
7305 if (!W_ERROR_IS_OK(result
)) {
7306 file_lines_free(qlines
);
7311 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_1
, numlines
)) == NULL
) {
7312 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7313 dos_errstr(WERR_NOMEM
)));
7314 file_lines_free(qlines
);
7318 for (i
=0; i
<numlines
; i
++) {
7319 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7320 fill_port_1(&ports
[i
], qlines
[i
]);
7323 file_lines_free(qlines
);
7325 *returned
= numlines
;
7327 /* check the required size. */
7328 for (i
=0; i
<*returned
; i
++) {
7329 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7330 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7333 if (*needed
> offered
) {
7334 result
= WERR_INSUFFICIENT_BUFFER
;
7338 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7339 result
= WERR_NOMEM
;
7343 /* fill the buffer with the ports structures */
7344 for (i
=0; i
<*returned
; i
++) {
7345 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7346 smb_io_port_1("", buffer
, &ports
[i
], 0);
7352 if ( !W_ERROR_IS_OK(result
) )
7358 /****************************************************************************
7360 ****************************************************************************/
7362 static WERROR
enumports_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7364 PORT_INFO_2
*ports
=NULL
;
7366 WERROR result
= WERR_OK
;
7367 char **qlines
= NULL
;
7370 result
= enumports_hook( &numlines
, &qlines
);
7371 if ( !W_ERROR_IS_OK(result
)) {
7372 file_lines_free(qlines
);
7377 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_2
, numlines
)) == NULL
) {
7378 file_lines_free(qlines
);
7382 for (i
=0; i
<numlines
; i
++) {
7383 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7384 fill_port_2(&(ports
[i
]), qlines
[i
]);
7388 file_lines_free(qlines
);
7390 *returned
= numlines
;
7392 /* check the required size. */
7393 for (i
=0; i
<*returned
; i
++) {
7394 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7395 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7398 if (*needed
> offered
) {
7399 result
= WERR_INSUFFICIENT_BUFFER
;
7403 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7404 result
= WERR_NOMEM
;
7408 /* fill the buffer with the ports structures */
7409 for (i
=0; i
<*returned
; i
++) {
7410 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7411 smb_io_port_2("", buffer
, &ports
[i
], 0);
7417 if ( !W_ERROR_IS_OK(result
) )
7423 /****************************************************************************
7425 ****************************************************************************/
7427 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7429 uint32 level
= q_u
->level
;
7430 RPC_BUFFER
*buffer
= NULL
;
7431 uint32 offered
= q_u
->offered
;
7432 uint32
*needed
= &r_u
->needed
;
7433 uint32
*returned
= &r_u
->returned
;
7435 /* that's an [in out] buffer */
7437 if (!q_u
->buffer
&& (offered
!=0)) {
7438 return WERR_INVALID_PARAM
;
7441 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7442 buffer
= r_u
->buffer
;
7444 DEBUG(4,("_spoolss_enumports\n"));
7451 return enumports_level_1(buffer
, offered
, needed
, returned
);
7453 return enumports_level_2(buffer
, offered
, needed
, returned
);
7455 return WERR_UNKNOWN_LEVEL
;
7459 /****************************************************************************
7460 ****************************************************************************/
7462 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7463 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7464 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7465 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7468 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7471 WERROR err
= WERR_OK
;
7473 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7474 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7478 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7479 if (!convert_printer_info(info
, printer
, 2)) {
7480 free_a_printer(&printer
, 2);
7484 /* check to see if the printer already exists */
7486 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7487 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7488 printer
->info_2
->sharename
));
7489 free_a_printer(&printer
, 2);
7490 return WERR_PRINTER_ALREADY_EXISTS
;
7493 /* FIXME!!! smbd should check to see if the driver is installed before
7494 trying to add a printer like this --jerry */
7496 if (*lp_addprinter_cmd() ) {
7497 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
7498 free_a_printer(&printer
,2);
7499 return WERR_ACCESS_DENIED
;
7502 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7503 "smb.conf parameter \"addprinter command\" is defined. This"
7504 "parameter must exist for this call to succeed\n",
7505 printer
->info_2
->sharename
));
7508 /* use our primary netbios name since get_a_printer() will convert
7509 it to what the client expects on a case by case basis */
7511 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7512 printer
->info_2
->sharename
);
7515 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7516 free_a_printer(&printer
,2);
7517 return WERR_ACCESS_DENIED
;
7520 /* you must be a printer admin to add a new printer */
7521 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7522 free_a_printer(&printer
,2);
7523 return WERR_ACCESS_DENIED
;
7527 * Do sanity check on the requested changes for Samba.
7530 if (!check_printer_ok(printer
->info_2
, snum
)) {
7531 free_a_printer(&printer
,2);
7532 return WERR_INVALID_PARAM
;
7536 * When a printer is created, the drivername bound to the printer is used
7537 * to lookup previously saved driver initialization info, which is then
7538 * bound to the new printer, simulating what happens in the Windows arch.
7543 set_driver_init(printer
, 2);
7547 /* A valid devmode was included, convert and link it
7549 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7551 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7552 &printer
->info_2
->devmode
))
7556 /* write the ASCII on disk */
7557 err
= mod_a_printer(printer
, 2);
7558 if (!W_ERROR_IS_OK(err
)) {
7559 free_a_printer(&printer
,2);
7563 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7564 /* Handle open failed - remove addition. */
7565 del_a_printer(printer
->info_2
->sharename
);
7566 free_a_printer(&printer
,2);
7567 return WERR_ACCESS_DENIED
;
7570 update_c_setprinter(False
);
7571 free_a_printer(&printer
,2);
7576 /****************************************************************************
7577 ****************************************************************************/
7579 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7581 UNISTR2
*uni_srv_name
= q_u
->server_name
;
7582 uint32 level
= q_u
->level
;
7583 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7584 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7585 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7586 uint32 user_switch
= q_u
->user_switch
;
7587 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7588 POLICY_HND
*handle
= &r_u
->handle
;
7592 /* we don't handle yet */
7593 /* but I know what to do ... */
7594 return WERR_UNKNOWN_LEVEL
;
7596 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7598 user_switch
, user
, handle
);
7600 return WERR_UNKNOWN_LEVEL
;
7604 /****************************************************************************
7605 ****************************************************************************/
7607 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7609 uint32 level
= q_u
->level
;
7610 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7611 WERROR err
= WERR_OK
;
7612 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7613 fstring driver_name
;
7616 ZERO_STRUCT(driver
);
7618 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7623 DEBUG(5,("Cleaning driver's information\n"));
7624 err
= clean_up_driver_struct(driver
, level
, &p
->pipe_user
);
7625 if (!W_ERROR_IS_OK(err
))
7628 DEBUG(5,("Moving driver to final destination\n"));
7629 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(driver
, level
, &p
->pipe_user
, &err
)) ) {
7633 if (add_a_printer_driver(driver
, level
)!=0) {
7634 err
= WERR_ACCESS_DENIED
;
7639 * I think this is where he DrvUpgradePrinter() hook would be
7640 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7641 * server. Right now, we just need to send ourselves a message
7642 * to update each printer bound to this driver. --jerry
7645 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7646 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7651 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7652 * decide if the driver init data should be deleted. The rules are:
7653 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7654 * 2) delete init data only if there is no 2k/Xp driver
7655 * 3) always delete init data
7656 * The generalized rule is always use init data from the highest order driver.
7657 * It is necessary to follow the driver install by an initialization step to
7658 * finish off this process.
7661 version
= driver
.info_3
->cversion
;
7662 else if (level
== 6)
7663 version
= driver
.info_6
->version
;
7668 * 9x printer driver - never delete init data
7671 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7676 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7677 * there is no 2k/Xp driver init data for this driver name.
7681 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7683 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7685 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7687 if (!del_driver_init(driver_name
))
7688 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7691 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7693 free_a_printer_driver(driver1
,3);
7694 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7701 * 2k or Xp printer driver - always delete init data
7704 if (!del_driver_init(driver_name
))
7705 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7709 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7715 free_a_printer_driver(driver
, level
);
7719 /********************************************************************
7720 * spoolss_addprinterdriverex
7721 ********************************************************************/
7723 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7725 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7726 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7729 * we only support the semantics of AddPrinterDriver()
7730 * i.e. only copy files that are newer than existing ones
7733 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7734 return WERR_ACCESS_DENIED
;
7736 ZERO_STRUCT(q_u_local
);
7737 ZERO_STRUCT(r_u_local
);
7739 /* just pass the information off to _spoolss_addprinterdriver() */
7740 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7741 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7742 q_u_local
.level
= q_u
->level
;
7743 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7745 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7748 /****************************************************************************
7749 ****************************************************************************/
7751 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7753 init_unistr(&info
->name
, name
);
7756 /****************************************************************************
7757 ****************************************************************************/
7759 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7765 const char *short_archi
;
7766 DRIVER_DIRECTORY_1
*info
=NULL
;
7767 WERROR result
= WERR_OK
;
7769 unistr2_to_ascii(servername
, name
, sizeof(servername
)-1);
7770 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7772 /* check for beginning double '\'s and that the server
7775 pservername
= servername
;
7776 if ( *pservername
== '\\' && strlen(servername
)>2 ) {
7780 if ( !is_myname_or_ipaddr( pservername
) )
7781 return WERR_INVALID_PARAM
;
7783 if (!(short_archi
= get_short_archi(long_archi
)))
7784 return WERR_INVALID_ENVIRONMENT
;
7786 if((info
=SMB_MALLOC_P(DRIVER_DIRECTORY_1
)) == NULL
)
7789 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", pservername
, short_archi
);
7791 DEBUG(4,("printer driver directory: [%s]\n", path
));
7793 fill_driverdir_1(info
, path
);
7795 *needed
+= spoolss_size_driverdir_info_1(info
);
7797 if (*needed
> offered
) {
7798 result
= WERR_INSUFFICIENT_BUFFER
;
7802 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7803 result
= WERR_NOMEM
;
7807 smb_io_driverdir_1("", buffer
, info
, 0);
7815 /****************************************************************************
7816 ****************************************************************************/
7818 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7820 UNISTR2
*name
= &q_u
->name
;
7821 UNISTR2
*uni_environment
= &q_u
->environment
;
7822 uint32 level
= q_u
->level
;
7823 RPC_BUFFER
*buffer
= NULL
;
7824 uint32 offered
= q_u
->offered
;
7825 uint32
*needed
= &r_u
->needed
;
7827 /* that's an [in out] buffer */
7829 if (!q_u
->buffer
&& (offered
!=0)) {
7830 return WERR_INVALID_PARAM
;
7833 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7834 buffer
= r_u
->buffer
;
7836 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7842 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7844 return WERR_UNKNOWN_LEVEL
;
7848 /****************************************************************************
7849 ****************************************************************************/
7851 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7853 POLICY_HND
*handle
= &q_u
->handle
;
7854 uint32 idx
= q_u
->index
;
7855 uint32 in_value_len
= q_u
->valuesize
;
7856 uint32 in_data_len
= q_u
->datasize
;
7857 uint32
*out_max_value_len
= &r_u
->valuesize
;
7858 uint16
**out_value
= &r_u
->value
;
7859 uint32
*out_value_len
= &r_u
->realvaluesize
;
7860 uint32
*out_type
= &r_u
->type
;
7861 uint32
*out_max_data_len
= &r_u
->datasize
;
7862 uint8
**data_out
= &r_u
->data
;
7863 uint32
*out_data_len
= &r_u
->realdatasize
;
7865 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7867 uint32 biggest_valuesize
;
7868 uint32 biggest_datasize
;
7870 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7873 REGISTRY_VALUE
*val
= NULL
;
7874 NT_PRINTER_DATA
*p_data
;
7875 int i
, key_index
, num_values
;
7880 *out_max_data_len
= 0;
7884 DEBUG(5,("spoolss_enumprinterdata\n"));
7887 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7891 if (!get_printer_snum(p
,handle
, &snum
))
7894 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7895 if (!W_ERROR_IS_OK(result
))
7898 p_data
= printer
->info_2
->data
;
7899 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
7904 * The NT machine wants to know the biggest size of value and data
7906 * cf: MSDN EnumPrinterData remark section
7909 if ( !in_value_len
&& !in_data_len
&& (key_index
!= -1) )
7911 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7913 biggest_valuesize
= 0;
7914 biggest_datasize
= 0;
7916 num_values
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
7918 for ( i
=0; i
<num_values
; i
++ )
7920 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
7922 name_length
= strlen(val
->valuename
);
7923 if ( strlen(val
->valuename
) > biggest_valuesize
)
7924 biggest_valuesize
= name_length
;
7926 if ( val
->size
> biggest_datasize
)
7927 biggest_datasize
= val
->size
;
7929 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7933 /* the value is an UNICODE string but real_value_size is the length
7934 in bytes including the trailing 0 */
7936 *out_value_len
= 2 * (1+biggest_valuesize
);
7937 *out_data_len
= biggest_datasize
;
7939 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
7945 * the value len is wrong in NT sp3
7946 * that's the number of bytes not the number of unicode chars
7949 if ( key_index
!= -1 )
7950 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, idx
);
7955 /* out_value should default to "" or else NT4 has
7956 problems unmarshalling the response */
7958 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7960 if((*out_value
=(uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7962 result
= WERR_NOMEM
;
7966 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
7968 /* the data is counted in bytes */
7970 *out_max_data_len
= in_data_len
;
7971 *out_data_len
= in_data_len
;
7973 /* only allocate when given a non-zero data_len */
7975 if ( in_data_len
&& ((*data_out
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
7977 result
= WERR_NOMEM
;
7981 result
= WERR_NO_MORE_ITEMS
;
7987 * - counted in bytes in the request
7988 * - counted in UNICODE chars in the max reply
7989 * - counted in bytes in the real size
7991 * take a pause *before* coding not *during* coding
7995 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
7996 if ( (*out_value
= (uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
7998 result
= WERR_NOMEM
;
8002 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), (size_t)in_value_len
, 0);
8006 *out_type
= regval_type( val
);
8008 /* data - counted in bytes */
8010 *out_max_data_len
= in_data_len
;
8011 if ( in_data_len
&& (*data_out
= (uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
8013 result
= WERR_NOMEM
;
8016 data_len
= regval_size(val
);
8018 memcpy( *data_out
, regval_data_p(val
), data_len
);
8019 *out_data_len
= data_len
;
8023 free_a_printer(&printer
, 2);
8027 /****************************************************************************
8028 ****************************************************************************/
8030 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
8032 POLICY_HND
*handle
= &q_u
->handle
;
8033 UNISTR2
*value
= &q_u
->value
;
8034 uint32 type
= q_u
->type
;
8035 uint8
*data
= q_u
->data
;
8036 uint32 real_len
= q_u
->real_len
;
8038 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8040 WERROR status
= WERR_OK
;
8041 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8044 DEBUG(5,("spoolss_setprinterdata\n"));
8047 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8051 if ( Printer
->printer_type
== SPLHND_SERVER
) {
8052 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8053 return WERR_INVALID_PARAM
;
8056 if (!get_printer_snum(p
,handle
, &snum
))
8060 * Access check : NT returns "access denied" if you make a
8061 * SetPrinterData call without the necessary privildge.
8062 * we were originally returning OK if nothing changed
8063 * which made Win2k issue **a lot** of SetPrinterData
8064 * when connecting to a printer --jerry
8067 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8069 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8070 status
= WERR_ACCESS_DENIED
;
8074 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8075 if (!W_ERROR_IS_OK(status
))
8078 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8081 * When client side code sets a magic printer data key, detect it and save
8082 * the current printer data and the magic key's data (its the DEVMODE) for
8083 * future printer/driver initializations.
8085 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
8087 /* Set devmode and printer initialization info */
8088 status
= save_driver_init( printer
, 2, data
, real_len
);
8090 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
8094 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
8095 type
, data
, real_len
);
8096 if ( W_ERROR_IS_OK(status
) )
8097 status
= mod_a_printer(printer
, 2);
8101 free_a_printer(&printer
, 2);
8106 /****************************************************************************
8107 ****************************************************************************/
8109 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
8111 POLICY_HND
*handle
= &q_u
->handle
;
8112 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8115 DEBUG(5,("_spoolss_resetprinter\n"));
8118 * All we do is to check to see if the handle and queue is valid.
8119 * This call really doesn't mean anything to us because we only
8120 * support RAW printing. --jerry
8124 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8128 if (!get_printer_snum(p
,handle
, &snum
))
8132 /* blindly return success */
8137 /****************************************************************************
8138 ****************************************************************************/
8140 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
8142 POLICY_HND
*handle
= &q_u
->handle
;
8143 UNISTR2
*value
= &q_u
->valuename
;
8145 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8147 WERROR status
= WERR_OK
;
8148 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8151 DEBUG(5,("spoolss_deleteprinterdata\n"));
8154 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8158 if (!get_printer_snum(p
, handle
, &snum
))
8161 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8162 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8163 return WERR_ACCESS_DENIED
;
8166 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8167 if (!W_ERROR_IS_OK(status
))
8170 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8172 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
8174 if ( W_ERROR_IS_OK(status
) )
8175 mod_a_printer( printer
, 2 );
8177 free_a_printer(&printer
, 2);
8182 /****************************************************************************
8183 ****************************************************************************/
8185 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
8187 POLICY_HND
*handle
= &q_u
->handle
;
8188 FORM
*form
= &q_u
->form
;
8189 nt_forms_struct tmpForm
;
8191 WERROR status
= WERR_OK
;
8192 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8195 nt_forms_struct
*list
=NULL
;
8196 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8198 DEBUG(5,("spoolss_addform\n"));
8201 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8206 /* forms can be added on printer of on the print server handle */
8208 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8210 if (!get_printer_snum(p
,handle
, &snum
))
8213 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8214 if (!W_ERROR_IS_OK(status
))
8218 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8219 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8220 status
= WERR_ACCESS_DENIED
;
8224 /* can't add if builtin */
8226 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8227 status
= WERR_ALREADY_EXISTS
;
8231 count
= get_ntforms(&list
);
8233 if(!add_a_form(&list
, form
, &count
)) {
8234 status
= WERR_NOMEM
;
8238 write_ntforms(&list
, count
);
8241 * ChangeID must always be set if this is a printer
8244 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8245 status
= mod_a_printer(printer
, 2);
8249 free_a_printer(&printer
, 2);
8255 /****************************************************************************
8256 ****************************************************************************/
8258 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
8260 POLICY_HND
*handle
= &q_u
->handle
;
8261 UNISTR2
*form_name
= &q_u
->name
;
8262 nt_forms_struct tmpForm
;
8264 nt_forms_struct
*list
=NULL
;
8265 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8267 WERROR status
= WERR_OK
;
8268 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8270 DEBUG(5,("spoolss_deleteform\n"));
8273 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8277 /* forms can be deleted on printer of on the print server handle */
8279 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8281 if (!get_printer_snum(p
,handle
, &snum
))
8284 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8285 if (!W_ERROR_IS_OK(status
))
8289 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8290 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8291 status
= WERR_ACCESS_DENIED
;
8295 /* can't delete if builtin */
8297 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
8298 status
= WERR_INVALID_PARAM
;
8302 count
= get_ntforms(&list
);
8304 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8308 * ChangeID must always be set if this is a printer
8311 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8312 status
= mod_a_printer(printer
, 2);
8316 free_a_printer(&printer
, 2);
8322 /****************************************************************************
8323 ****************************************************************************/
8325 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8327 POLICY_HND
*handle
= &q_u
->handle
;
8328 FORM
*form
= &q_u
->form
;
8329 nt_forms_struct tmpForm
;
8331 WERROR status
= WERR_OK
;
8332 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8335 nt_forms_struct
*list
=NULL
;
8336 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8338 DEBUG(5,("spoolss_setform\n"));
8341 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8345 /* forms can be modified on printer of on the print server handle */
8347 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8349 if (!get_printer_snum(p
,handle
, &snum
))
8352 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8353 if (!W_ERROR_IS_OK(status
))
8357 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8358 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8359 status
= WERR_ACCESS_DENIED
;
8363 /* can't set if builtin */
8364 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8365 status
= WERR_INVALID_PARAM
;
8369 count
= get_ntforms(&list
);
8370 update_a_form(&list
, form
, count
);
8371 write_ntforms(&list
, count
);
8374 * ChangeID must always be set if this is a printer
8377 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8378 status
= mod_a_printer(printer
, 2);
8383 free_a_printer(&printer
, 2);
8389 /****************************************************************************
8390 enumprintprocessors level 1.
8391 ****************************************************************************/
8393 static WERROR
enumprintprocessors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8395 PRINTPROCESSOR_1
*info_1
=NULL
;
8396 WERROR result
= WERR_OK
;
8398 if((info_1
= SMB_MALLOC_P(PRINTPROCESSOR_1
)) == NULL
)
8403 init_unistr(&info_1
->name
, "winprint");
8405 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8407 if (*needed
> offered
) {
8408 result
= WERR_INSUFFICIENT_BUFFER
;
8412 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8413 result
= WERR_NOMEM
;
8417 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8422 if ( !W_ERROR_IS_OK(result
) )
8428 /****************************************************************************
8429 ****************************************************************************/
8431 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8433 uint32 level
= q_u
->level
;
8434 RPC_BUFFER
*buffer
= NULL
;
8435 uint32 offered
= q_u
->offered
;
8436 uint32
*needed
= &r_u
->needed
;
8437 uint32
*returned
= &r_u
->returned
;
8439 /* that's an [in out] buffer */
8441 if (!q_u
->buffer
&& (offered
!=0)) {
8442 return WERR_INVALID_PARAM
;
8445 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8446 buffer
= r_u
->buffer
;
8448 DEBUG(5,("spoolss_enumprintprocessors\n"));
8451 * Enumerate the print processors ...
8453 * Just reply with "winprint", to keep NT happy
8454 * and I can use my nice printer checker.
8462 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8464 return WERR_UNKNOWN_LEVEL
;
8468 /****************************************************************************
8469 enumprintprocdatatypes level 1.
8470 ****************************************************************************/
8472 static WERROR
enumprintprocdatatypes_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8474 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8475 WERROR result
= WERR_NOMEM
;
8477 if((info_1
= SMB_MALLOC_P(PRINTPROCDATATYPE_1
)) == NULL
)
8482 init_unistr(&info_1
->name
, "RAW");
8484 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8486 if (*needed
> offered
) {
8487 result
= WERR_INSUFFICIENT_BUFFER
;
8491 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8492 result
= WERR_NOMEM
;
8496 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8501 if ( !W_ERROR_IS_OK(result
) )
8507 /****************************************************************************
8508 ****************************************************************************/
8510 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8512 uint32 level
= q_u
->level
;
8513 RPC_BUFFER
*buffer
= NULL
;
8514 uint32 offered
= q_u
->offered
;
8515 uint32
*needed
= &r_u
->needed
;
8516 uint32
*returned
= &r_u
->returned
;
8518 /* that's an [in out] buffer */
8520 if (!q_u
->buffer
&& (offered
!=0)) {
8521 return WERR_INVALID_PARAM
;
8524 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8525 buffer
= r_u
->buffer
;
8527 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8534 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8536 return WERR_UNKNOWN_LEVEL
;
8540 /****************************************************************************
8541 enumprintmonitors level 1.
8542 ****************************************************************************/
8544 static WERROR
enumprintmonitors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8546 PRINTMONITOR_1
*info_1
;
8547 WERROR result
= WERR_OK
;
8550 if((info_1
= SMB_MALLOC_ARRAY(PRINTMONITOR_1
, 2)) == NULL
)
8555 init_unistr(&(info_1
[0].name
), SPL_LOCAL_PORT
);
8556 init_unistr(&(info_1
[1].name
), SPL_TCPIP_PORT
);
8558 for ( i
=0; i
<*returned
; i
++ ) {
8559 *needed
+= spoolss_size_printmonitor_info_1(&info_1
[i
]);
8562 if (*needed
> offered
) {
8563 result
= WERR_INSUFFICIENT_BUFFER
;
8567 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8568 result
= WERR_NOMEM
;
8572 for ( i
=0; i
<*returned
; i
++ ) {
8573 smb_io_printmonitor_info_1("", buffer
, &info_1
[i
], 0);
8579 if ( !W_ERROR_IS_OK(result
) )
8585 /****************************************************************************
8586 enumprintmonitors level 2.
8587 ****************************************************************************/
8589 static WERROR
enumprintmonitors_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8591 PRINTMONITOR_2
*info_2
;
8592 WERROR result
= WERR_OK
;
8595 if((info_2
= SMB_MALLOC_ARRAY(PRINTMONITOR_2
, 2)) == NULL
)
8600 init_unistr( &(info_2
[0].name
), SPL_LOCAL_PORT
);
8601 init_unistr( &(info_2
[0].environment
), "Windows NT X86" );
8602 init_unistr( &(info_2
[0].dll_name
), "localmon.dll" );
8604 init_unistr( &(info_2
[1].name
), SPL_TCPIP_PORT
);
8605 init_unistr( &(info_2
[1].environment
), "Windows NT X86" );
8606 init_unistr( &(info_2
[1].dll_name
), "tcpmon.dll" );
8608 for ( i
=0; i
<*returned
; i
++ ) {
8609 *needed
+= spoolss_size_printmonitor_info_2(&info_2
[i
]);
8612 if (*needed
> offered
) {
8613 result
= WERR_INSUFFICIENT_BUFFER
;
8617 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8618 result
= WERR_NOMEM
;
8622 for ( i
=0; i
<*returned
; i
++ ) {
8623 smb_io_printmonitor_info_2("", buffer
, &info_2
[i
], 0);
8629 if ( !W_ERROR_IS_OK(result
) )
8635 /****************************************************************************
8636 ****************************************************************************/
8638 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8640 uint32 level
= q_u
->level
;
8641 RPC_BUFFER
*buffer
= NULL
;
8642 uint32 offered
= q_u
->offered
;
8643 uint32
*needed
= &r_u
->needed
;
8644 uint32
*returned
= &r_u
->returned
;
8646 /* that's an [in out] buffer */
8648 if (!q_u
->buffer
&& (offered
!=0)) {
8649 return WERR_INVALID_PARAM
;
8652 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8653 buffer
= r_u
->buffer
;
8655 DEBUG(5,("spoolss_enumprintmonitors\n"));
8658 * Enumerate the print monitors ...
8660 * Just reply with "Local Port", to keep NT happy
8661 * and I can use my nice printer checker.
8669 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8671 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8673 return WERR_UNKNOWN_LEVEL
;
8677 /****************************************************************************
8678 ****************************************************************************/
8680 static WERROR
getjob_level_1(print_queue_struct
**queue
, int count
, int snum
,
8681 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8682 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8687 JOB_INFO_1
*info_1
=NULL
;
8688 WERROR result
= WERR_OK
;
8690 info_1
=SMB_MALLOC_P(JOB_INFO_1
);
8692 if (info_1
== NULL
) {
8696 for (i
=0; i
<count
&& found
==False
; i
++) {
8697 if ((*queue
)[i
].job
==(int)jobid
)
8703 /* NT treats not found as bad param... yet another bad choice */
8704 return WERR_INVALID_PARAM
;
8707 fill_job_info_1( info_1
, &((*queue
)[i
-1]), i
, snum
, ntprinter
);
8709 *needed
+= spoolss_size_job_info_1(info_1
);
8711 if (*needed
> offered
) {
8712 result
= WERR_INSUFFICIENT_BUFFER
;
8716 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8717 result
= WERR_NOMEM
;
8721 smb_io_job_info_1("", buffer
, info_1
, 0);
8729 /****************************************************************************
8730 ****************************************************************************/
8732 static WERROR
getjob_level_2(print_queue_struct
**queue
, int count
, int snum
,
8733 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8734 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8741 DEVICEMODE
*devmode
= NULL
;
8742 NT_DEVICEMODE
*nt_devmode
= NULL
;
8744 if ( !(info_2
=SMB_MALLOC_P(JOB_INFO_2
)) )
8747 ZERO_STRUCTP(info_2
);
8749 for ( i
=0; i
<count
&& found
==False
; i
++ )
8751 if ((*queue
)[i
].job
== (int)jobid
)
8756 /* NT treats not found as bad param... yet another bad
8758 result
= WERR_INVALID_PARAM
;
8763 * if the print job does not have a DEVMODE associated with it,
8764 * just use the one for the printer. A NULL devicemode is not
8765 * a failure condition
8768 if ( !(nt_devmode
=print_job_devmode( lp_const_servicename(snum
), jobid
)) )
8769 devmode
= construct_dev_mode(lp_const_servicename(snum
));
8771 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) != NULL
) {
8772 ZERO_STRUCTP( devmode
);
8773 convert_nt_devicemode( devmode
, nt_devmode
);
8777 fill_job_info_2(info_2
, &((*queue
)[i
-1]), i
, snum
, ntprinter
, devmode
);
8779 *needed
+= spoolss_size_job_info_2(info_2
);
8781 if (*needed
> offered
) {
8782 result
= WERR_INSUFFICIENT_BUFFER
;
8786 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8787 result
= WERR_NOMEM
;
8791 smb_io_job_info_2("", buffer
, info_2
, 0);
8796 /* Cleanup allocated memory */
8798 free_job_info_2(info_2
); /* Also frees devmode */
8804 /****************************************************************************
8805 ****************************************************************************/
8807 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8809 POLICY_HND
*handle
= &q_u
->handle
;
8810 uint32 jobid
= q_u
->jobid
;
8811 uint32 level
= q_u
->level
;
8812 RPC_BUFFER
*buffer
= NULL
;
8813 uint32 offered
= q_u
->offered
;
8814 uint32
*needed
= &r_u
->needed
;
8815 WERROR wstatus
= WERR_OK
;
8816 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8819 print_queue_struct
*queue
= NULL
;
8820 print_status_struct prt_status
;
8822 /* that's an [in out] buffer */
8824 if (!q_u
->buffer
&& (offered
!=0)) {
8825 return WERR_INVALID_PARAM
;
8828 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8829 buffer
= r_u
->buffer
;
8831 DEBUG(5,("spoolss_getjob\n"));
8835 if (!get_printer_snum(p
, handle
, &snum
))
8838 wstatus
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8839 if ( !W_ERROR_IS_OK(wstatus
) )
8842 count
= print_queue_status(snum
, &queue
, &prt_status
);
8844 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8845 count
, prt_status
.status
, prt_status
.message
));
8849 wstatus
= getjob_level_1(&queue
, count
, snum
, ntprinter
, jobid
,
8850 buffer
, offered
, needed
);
8853 wstatus
= getjob_level_2(&queue
, count
, snum
, ntprinter
, jobid
,
8854 buffer
, offered
, needed
);
8857 wstatus
= WERR_UNKNOWN_LEVEL
;
8862 free_a_printer( &ntprinter
, 2 );
8867 /********************************************************************
8868 spoolss_getprinterdataex
8870 From MSDN documentation of GetPrinterDataEx: pass request
8871 to GetPrinterData if key is "PrinterDriverData".
8872 ********************************************************************/
8874 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8876 POLICY_HND
*handle
= &q_u
->handle
;
8877 uint32 in_size
= q_u
->size
;
8878 uint32
*type
= &r_u
->type
;
8879 uint32
*out_size
= &r_u
->size
;
8880 uint8
**data
= &r_u
->data
;
8881 uint32
*needed
= &r_u
->needed
;
8882 fstring keyname
, valuename
;
8884 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8886 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8888 WERROR status
= WERR_OK
;
8890 DEBUG(4,("_spoolss_getprinterdataex\n"));
8892 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8893 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
8895 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
8896 keyname
, valuename
));
8898 /* in case of problem, return some default values */
8902 *out_size
= in_size
;
8905 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8906 status
= WERR_BADFID
;
8910 /* Is the handle to a printer or to the server? */
8912 if (Printer
->printer_type
== SPLHND_SERVER
) {
8913 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
8914 status
= WERR_INVALID_PARAM
;
8918 if ( !get_printer_snum(p
,handle
, &snum
) )
8921 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8922 if ( !W_ERROR_IS_OK(status
) )
8925 /* check to see if the keyname is valid */
8926 if ( !strlen(keyname
) ) {
8927 status
= WERR_INVALID_PARAM
;
8931 if ( lookup_printerkey( printer
->info_2
->data
, keyname
) == -1 ) {
8932 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
8933 free_a_printer( &printer
, 2 );
8934 status
= WERR_BADFILE
;
8938 /* When given a new keyname, we should just create it */
8940 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
8942 if (*needed
> *out_size
)
8943 status
= WERR_MORE_DATA
;
8946 if ( !W_ERROR_IS_OK(status
) )
8948 DEBUG(5, ("error: allocating %d\n", *out_size
));
8950 /* reply this param doesn't exist */
8954 if( (*data
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
8955 status
= WERR_NOMEM
;
8965 free_a_printer( &printer
, 2 );
8970 /********************************************************************
8971 * spoolss_setprinterdataex
8972 ********************************************************************/
8974 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
8976 POLICY_HND
*handle
= &q_u
->handle
;
8977 uint32 type
= q_u
->type
;
8978 uint8
*data
= q_u
->data
;
8979 uint32 real_len
= q_u
->real_len
;
8981 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8983 WERROR status
= WERR_OK
;
8984 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8989 DEBUG(4,("_spoolss_setprinterdataex\n"));
8991 /* From MSDN documentation of SetPrinterDataEx: pass request to
8992 SetPrinterData if key is "PrinterDriverData" */
8995 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8999 if ( Printer
->printer_type
== SPLHND_SERVER
) {
9000 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9001 return WERR_INVALID_PARAM
;
9004 if ( !get_printer_snum(p
,handle
, &snum
) )
9008 * Access check : NT returns "access denied" if you make a
9009 * SetPrinterData call without the necessary privildge.
9010 * we were originally returning OK if nothing changed
9011 * which made Win2k issue **a lot** of SetPrinterData
9012 * when connecting to a printer --jerry
9015 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
9017 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9018 return WERR_ACCESS_DENIED
;
9021 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9022 if (!W_ERROR_IS_OK(status
))
9025 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
9026 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
9028 /* check for OID in valuename */
9030 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
9036 /* save the registry data */
9038 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
9040 if ( W_ERROR_IS_OK(status
) )
9042 /* save the OID if one was specified */
9044 fstrcat( keyname
, "\\" );
9045 fstrcat( keyname
, SPOOL_OID_KEY
);
9048 * I'm not checking the status here on purpose. Don't know
9049 * if this is right, but I'm returning the status from the
9050 * previous set_printer_dataex() call. I have no idea if
9051 * this is right. --jerry
9054 set_printer_dataex( printer
, keyname
, valuename
,
9055 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
9058 status
= mod_a_printer(printer
, 2);
9061 free_a_printer(&printer
, 2);
9067 /********************************************************************
9068 * spoolss_deleteprinterdataex
9069 ********************************************************************/
9071 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
9073 POLICY_HND
*handle
= &q_u
->handle
;
9074 UNISTR2
*value
= &q_u
->valuename
;
9075 UNISTR2
*key
= &q_u
->keyname
;
9077 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9079 WERROR status
= WERR_OK
;
9080 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
9081 pstring valuename
, keyname
;
9083 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9086 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9090 if (!get_printer_snum(p
, handle
, &snum
))
9093 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9094 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9095 return WERR_ACCESS_DENIED
;
9098 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9099 if (!W_ERROR_IS_OK(status
))
9102 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
9103 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
9105 status
= delete_printer_dataex( printer
, keyname
, valuename
);
9107 if ( W_ERROR_IS_OK(status
) )
9108 mod_a_printer( printer
, 2 );
9110 free_a_printer(&printer
, 2);
9115 /********************************************************************
9116 * spoolss_enumprinterkey
9117 ********************************************************************/
9120 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
9123 fstring
*keynames
= NULL
;
9124 uint16
*enumkeys
= NULL
;
9127 POLICY_HND
*handle
= &q_u
->handle
;
9128 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9129 NT_PRINTER_DATA
*data
;
9130 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9132 WERROR status
= WERR_BADFILE
;
9135 DEBUG(4,("_spoolss_enumprinterkey\n"));
9138 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9142 if ( !get_printer_snum(p
,handle
, &snum
) )
9145 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9146 if (!W_ERROR_IS_OK(status
))
9149 /* get the list of subkey names */
9151 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
9152 data
= printer
->info_2
->data
;
9154 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
9156 if ( num_keys
== -1 ) {
9157 status
= WERR_BADFILE
;
9161 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
9163 r_u
->needed
= printerkey_len
*2;
9165 if ( q_u
->size
< r_u
->needed
) {
9166 status
= WERR_MORE_DATA
;
9170 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
9171 status
= WERR_NOMEM
;
9177 if ( q_u
->size
< r_u
->needed
)
9178 status
= WERR_MORE_DATA
;
9181 free_a_printer( &printer
, 2 );
9182 SAFE_FREE( keynames
);
9187 /********************************************************************
9188 * spoolss_deleteprinterkey
9189 ********************************************************************/
9191 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
9193 POLICY_HND
*handle
= &q_u
->handle
;
9194 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9196 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9200 DEBUG(5,("spoolss_deleteprinterkey\n"));
9203 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9207 /* if keyname == NULL, return error */
9209 if ( !q_u
->keyname
.buffer
)
9210 return WERR_INVALID_PARAM
;
9212 if (!get_printer_snum(p
, handle
, &snum
))
9215 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9216 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9217 return WERR_ACCESS_DENIED
;
9220 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9221 if (!W_ERROR_IS_OK(status
))
9224 /* delete the key and all subneys */
9226 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
9228 status
= delete_all_printer_data( printer
->info_2
, key
);
9230 if ( W_ERROR_IS_OK(status
) )
9231 status
= mod_a_printer(printer
, 2);
9233 free_a_printer( &printer
, 2 );
9239 /********************************************************************
9240 * spoolss_enumprinterdataex
9241 ********************************************************************/
9243 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9245 POLICY_HND
*handle
= &q_u
->handle
;
9246 uint32 in_size
= q_u
->size
;
9249 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9250 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9251 NT_PRINTER_DATA
*p_data
;
9253 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9258 REGISTRY_VALUE
*val
;
9263 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9266 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9271 * first check for a keyname of NULL or "". Win2k seems to send
9272 * this a lot and we should send back WERR_INVALID_PARAM
9273 * no need to spend time looking up the printer in this case.
9277 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9278 if ( !strlen(key
) ) {
9279 result
= WERR_INVALID_PARAM
;
9283 /* get the printer off of disk */
9285 if (!get_printer_snum(p
,handle
, &snum
))
9288 ZERO_STRUCT(printer
);
9289 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9290 if (!W_ERROR_IS_OK(result
))
9293 /* now look for a match on the key name */
9295 p_data
= printer
->info_2
->data
;
9297 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9298 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9300 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9301 result
= WERR_INVALID_PARAM
;
9308 /* allocate the memory for the array of pointers -- if necessary */
9310 num_entries
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
9313 if ( (enum_values
=TALLOC_ARRAY(p
->mem_ctx
, PRINTER_ENUM_VALUES
, num_entries
)) == NULL
)
9315 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9316 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9317 result
= WERR_NOMEM
;
9321 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9325 * loop through all params and build the array to pass
9326 * back to the client
9329 for ( i
=0; i
<num_entries
; i
++ )
9331 /* lookup the registry value */
9333 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
9334 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9338 value_name
= regval_name( val
);
9339 init_unistr( &enum_values
[i
].valuename
, value_name
);
9340 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9341 enum_values
[i
].type
= regval_type( val
);
9343 data_len
= regval_size( val
);
9345 if ( !(enum_values
[i
].data
= TALLOC_MEMDUP(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9347 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9349 result
= WERR_NOMEM
;
9353 enum_values
[i
].data_len
= data_len
;
9355 /* keep track of the size of the array in bytes */
9357 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9360 /* housekeeping information in the reply */
9362 r_u
->needed
= needed
;
9363 r_u
->returned
= num_entries
;
9365 if (needed
> in_size
) {
9366 result
= WERR_MORE_DATA
;
9370 /* copy data into the reply */
9372 r_u
->ctr
.size
= r_u
->needed
;
9373 r_u
->ctr
.size_of_array
= r_u
->returned
;
9374 r_u
->ctr
.values
= enum_values
;
9380 free_a_printer(&printer
, 2);
9385 /****************************************************************************
9386 ****************************************************************************/
9388 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9390 init_unistr(&info
->name
, name
);
9393 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9394 UNISTR2
*environment
,
9401 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9402 WERROR result
= WERR_OK
;
9404 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9406 if (!get_short_archi(long_archi
))
9407 return WERR_INVALID_ENVIRONMENT
;
9409 if((info
=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1
)) == NULL
)
9412 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9414 fill_printprocessordirectory_1(info
, path
);
9416 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9418 if (*needed
> offered
) {
9419 result
= WERR_INSUFFICIENT_BUFFER
;
9423 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
9424 result
= WERR_INSUFFICIENT_BUFFER
;
9428 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9436 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9438 uint32 level
= q_u
->level
;
9439 RPC_BUFFER
*buffer
= NULL
;
9440 uint32 offered
= q_u
->offered
;
9441 uint32
*needed
= &r_u
->needed
;
9444 /* that's an [in out] buffer */
9446 if (!q_u
->buffer
&& (offered
!=0)) {
9447 return WERR_INVALID_PARAM
;
9450 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
9451 buffer
= r_u
->buffer
;
9453 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9459 result
= getprintprocessordirectory_level_1
9460 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9463 result
= WERR_UNKNOWN_LEVEL
;
9469 /*******************************************************************
9470 Streams the monitor UI DLL name in UNICODE
9471 *******************************************************************/
9473 static WERROR
xcvtcp_monitorui( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9474 RPC_BUFFER
*out
, uint32
*needed
)
9476 const char *dllname
= "tcpmonui.dll";
9478 *needed
= (strlen(dllname
)+1) * 2;
9480 if ( rpcbuf_get_size(out
) < *needed
) {
9481 return WERR_INSUFFICIENT_BUFFER
;
9484 if ( !make_monitorui_buf( out
, dllname
) ) {
9491 /*******************************************************************
9492 Create a new TCP/IP port
9493 *******************************************************************/
9495 static WERROR
xcvtcp_addport( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9496 RPC_BUFFER
*out
, uint32
*needed
)
9498 NT_PORT_DATA_1 port1
;
9501 ZERO_STRUCT( port1
);
9503 /* convert to our internal port data structure */
9505 if ( !convert_port_data_1( &port1
, in
) ) {
9509 /* create the device URI and call the add_port_hook() */
9511 switch ( port1
.protocol
) {
9512 case PORT_PROTOCOL_DIRECT
:
9513 pstr_sprintf( device_uri
, "socket://%s:%d/", port1
.hostaddr
, port1
.port
);
9516 case PORT_PROTOCOL_LPR
:
9517 pstr_sprintf( device_uri
, "lpr://%s/%s", port1
.hostaddr
, port1
.queue
);
9521 return WERR_UNKNOWN_PORT
;
9524 return add_port_hook( token
, port1
.name
, device_uri
);
9527 /*******************************************************************
9528 *******************************************************************/
9530 struct xcv_api_table xcvtcp_cmds
[] = {
9531 { "MonitorUI", xcvtcp_monitorui
},
9532 { "AddPort", xcvtcp_addport
},
9536 static WERROR
process_xcvtcp_command( NT_USER_TOKEN
*token
, const char *command
,
9537 RPC_BUFFER
*inbuf
, RPC_BUFFER
*outbuf
,
9542 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9544 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9545 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9546 return xcvtcp_cmds
[i
].fn( token
, inbuf
, outbuf
, needed
);
9549 return WERR_BADFUNC
;
9552 /*******************************************************************
9553 *******************************************************************/
9554 #if 0 /* don't support management using the "Local Port" monitor */
9556 static WERROR
xcvlocal_monitorui( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9557 RPC_BUFFER
*out
, uint32
*needed
)
9559 const char *dllname
= "localui.dll";
9561 *needed
= (strlen(dllname
)+1) * 2;
9563 if ( rpcbuf_get_size(out
) < *needed
) {
9564 return WERR_INSUFFICIENT_BUFFER
;
9567 if ( !make_monitorui_buf( out
, dllname
)) {
9574 /*******************************************************************
9575 *******************************************************************/
9577 struct xcv_api_table xcvlocal_cmds
[] = {
9578 { "MonitorUI", xcvlocal_monitorui
},
9582 struct xcv_api_table xcvlocal_cmds
[] = {
9589 /*******************************************************************
9590 *******************************************************************/
9592 static WERROR
process_xcvlocal_command( NT_USER_TOKEN
*token
, const char *command
,
9593 RPC_BUFFER
*inbuf
, RPC_BUFFER
*outbuf
,
9598 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9600 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9601 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9602 return xcvlocal_cmds
[i
].fn( token
, inbuf
, outbuf
, needed
);
9604 return WERR_BADFUNC
;
9607 /*******************************************************************
9608 *******************************************************************/
9610 WERROR
_spoolss_xcvdataport(pipes_struct
*p
, SPOOL_Q_XCVDATAPORT
*q_u
, SPOOL_R_XCVDATAPORT
*r_u
)
9612 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9616 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u
->handle
)));
9620 /* Has to be a handle to the TCP/IP port monitor */
9622 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9623 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9627 /* requires administrative access to the server */
9629 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9630 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9631 return WERR_ACCESS_DENIED
;
9634 /* Get the command name. There's numerous commands supported by the
9635 TCPMON interface. */
9637 rpcstr_pull(command
, q_u
->dataname
.buffer
, sizeof(command
),
9638 q_u
->dataname
.uni_str_len
*2, 0);
9640 /* Allocate the outgoing buffer */
9642 rpcbuf_init( &r_u
->outdata
, q_u
->offered
, p
->mem_ctx
);
9644 switch ( Printer
->printer_type
) {
9645 case SPLHND_PORTMON_TCP
:
9646 return process_xcvtcp_command( p
->pipe_user
.nt_user_token
, command
,
9647 &q_u
->indata
, &r_u
->outdata
, &r_u
->needed
);
9648 case SPLHND_PORTMON_LOCAL
:
9649 return process_xcvlocal_command( p
->pipe_user
.nt_user_token
, command
,
9650 &q_u
->indata
, &r_u
->outdata
, &r_u
->needed
);
9653 return WERR_INVALID_PRINT_MONITOR
;