2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info
;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 const char *long_archi
;
45 const char *short_archi
;
49 static Printer_entry
*printers_list
;
51 typedef struct _counter_printer_0
{
52 struct _counter_printer_0
*next
;
53 struct _counter_printer_0
*prev
;
59 static counter_printer_0
*counter_list
;
61 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections
=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
69 /* API table for Xcv Monitor functions */
71 struct xcv_api_table
{
73 WERROR(*fn
) (NT_USER_TOKEN
*token
, RPC_BUFFER
*in
, RPC_BUFFER
*out
, uint32
*needed
);
76 /********************************************************************
77 * Canonicalize servername.
78 ********************************************************************/
80 static const char *canon_servername(const char *servername
)
82 const char *pservername
= servername
;
83 while (*pservername
== '\\') {
89 /* translate between internal status numbers and NT status numbers */
90 static int nt_printj_status(int v
)
96 return JOB_STATUS_PAUSED
;
98 return JOB_STATUS_SPOOLING
;
100 return JOB_STATUS_PRINTING
;
102 return JOB_STATUS_ERROR
;
104 return JOB_STATUS_DELETING
;
106 return JOB_STATUS_OFFLINE
;
108 return JOB_STATUS_PAPEROUT
;
110 return JOB_STATUS_PRINTED
;
112 return JOB_STATUS_DELETED
;
114 return JOB_STATUS_BLOCKED
;
115 case LPQ_USER_INTERVENTION
:
116 return JOB_STATUS_USER_INTERVENTION
;
121 static int nt_printq_status(int v
)
125 return PRINTER_STATUS_PAUSED
;
134 /****************************************************************************
135 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
136 ****************************************************************************/
138 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
143 SAFE_FREE((*pp
)->ctr
.type
);
147 /***************************************************************************
148 Disconnect from the client
149 ****************************************************************************/
151 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum
))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections
==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 result
= rpccli_spoolss_reply_close_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, handle
);
171 if (!W_ERROR_IS_OK(result
))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 dos_errstr(result
)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections
==1) {
178 cli_shutdown( notify_cli_pipe
->cli
);
179 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
181 message_deregister(MSG_PRINTER_NOTIFY2
);
183 /* Tell the connections db we're no longer interested in
184 * printer notify messages. */
186 register_message_flags( False
, FLAG_MSG_PRINT_NOTIFY
);
192 /****************************************************************************
193 Functions to free a printer entry datastruct.
194 ****************************************************************************/
196 static void free_printer_entry(void *ptr
)
198 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
200 if (Printer
->notify
.client_connected
==True
) {
203 if ( Printer
->printer_type
== SPLHND_SERVER
) {
205 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
206 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
207 snum
= print_queue_snum(Printer
->sharename
);
209 srv_spoolss_replycloseprinter(snum
,
210 &Printer
->notify
.client_hnd
);
214 Printer
->notify
.flags
=0;
215 Printer
->notify
.options
=0;
216 Printer
->notify
.localmachine
[0]='\0';
217 Printer
->notify
.printerlocal
=0;
218 free_spool_notify_option(&Printer
->notify
.option
);
219 Printer
->notify
.option
=NULL
;
220 Printer
->notify
.client_connected
=False
;
222 free_nt_devicemode( &Printer
->nt_devmode
);
223 free_a_printer( &Printer
->printer_info
, 2 );
225 talloc_destroy( Printer
->ctx
);
227 /* Remove from the internal list. */
228 DLIST_REMOVE(printers_list
, Printer
);
233 /****************************************************************************
234 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
235 ****************************************************************************/
237 static SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
239 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
244 new_sp
= SMB_MALLOC_P(SPOOL_NOTIFY_OPTION
);
251 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
253 if (!new_sp
->ctr
.type
) {
262 /****************************************************************************
263 find printer index by handle
264 ****************************************************************************/
266 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
268 Printer_entry
*find_printer
= NULL
;
270 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
271 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
278 /****************************************************************************
279 Close printer index by handle.
280 ****************************************************************************/
282 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
284 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
287 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
291 close_policy_hnd(p
, hnd
);
296 /****************************************************************************
297 Delete a printer given a handle.
298 ****************************************************************************/
299 WERROR
delete_printer_hook( NT_USER_TOKEN
*token
, const char *sharename
)
301 char *cmd
= lp_deleteprinter_cmd();
304 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
305 BOOL is_print_op
= False
;
307 /* can't fail if we don't try */
312 pstr_sprintf(command
, "%s \"%s\"", cmd
, sharename
);
315 is_print_op
= user_has_privileges( token
, &se_printop
);
317 DEBUG(10,("Running [%s]\n", command
));
319 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
324 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
325 /* Tell everyone we updated smb.conf. */
326 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
332 /********** END SePrintOperatorPrivlege BLOCK **********/
334 DEBUGADD(10,("returned [%d]\n", ret
));
337 return WERR_BADFID
; /* What to return here? */
339 /* go ahead and re-read the services immediately */
340 reload_services( False
);
342 if ( lp_servicenumber( sharename
) < 0 )
343 return WERR_ACCESS_DENIED
;
348 /****************************************************************************
349 Delete a printer given a handle.
350 ****************************************************************************/
352 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
354 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
357 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
362 * It turns out that Windows allows delete printer on a handle
363 * opened by an admin user, then used on a pipe handle created
364 * by an anonymous user..... but they're working on security.... riiight !
368 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
369 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
370 return WERR_ACCESS_DENIED
;
373 /* this does not need a become root since the access check has been
374 done on the handle already */
376 if (del_a_printer( Printer
->sharename
) != 0) {
377 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
381 return delete_printer_hook( p
->pipe_user
.nt_user_token
, Printer
->sharename
);
384 /****************************************************************************
385 Return the snum of a printer corresponding to an handle.
386 ****************************************************************************/
388 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
)
390 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
393 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
397 switch (Printer
->printer_type
) {
399 DEBUG(4,("short name:%s\n", Printer
->sharename
));
400 *number
= print_queue_snum(Printer
->sharename
);
401 return (*number
!= -1);
409 /****************************************************************************
410 Set printer handle type.
411 Check if it's \\server or \\server\printer
412 ****************************************************************************/
414 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
416 DEBUG(3,("Setting printer type=%s\n", handlename
));
418 if ( strlen(handlename
) < 3 ) {
419 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
423 /* it's a print server */
424 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
425 DEBUGADD(4,("Printer is a print server\n"));
426 Printer
->printer_type
= SPLHND_SERVER
;
428 /* it's a printer (set_printer_hnd_name() will handle port monitors */
430 DEBUGADD(4,("Printer is a printer\n"));
431 Printer
->printer_type
= SPLHND_PRINTER
;
437 /****************************************************************************
438 Set printer handle name.. Accept names like \\server, \\server\printer,
439 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
440 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
441 XcvDataPort() interface.
442 ****************************************************************************/
444 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
447 int n_services
=lp_numservices();
448 char *aprinter
, *printername
;
449 const char *servername
;
452 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
455 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
, (unsigned long)strlen(handlename
)));
457 aprinter
= handlename
;
458 if ( *handlename
== '\\' ) {
459 servername
= canon_servername(handlename
);
460 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
468 /* save the servername to fill in replies on this handle */
470 if ( !is_myname_or_ipaddr( servername
) )
473 fstrcpy( Printer
->servername
, servername
);
475 if ( Printer
->printer_type
== SPLHND_SERVER
)
478 if ( Printer
->printer_type
!= SPLHND_PRINTER
)
481 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
483 /* check for the Port Monitor Interface */
485 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
486 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
487 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
490 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
491 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
492 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
496 /* Search all sharenames first as this is easier than pulling
497 the printer_info_2 off of disk. Don't use find_service() since
498 that calls out to map_username() */
500 /* do another loop to look for printernames */
502 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
504 /* no point going on if this is not a printer */
506 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
509 fstrcpy(sname
, lp_servicename(snum
));
510 if ( strequal( aprinter
, sname
) ) {
515 /* no point looking up the printer object if
516 we aren't allowing printername != sharename */
518 if ( lp_force_printername(snum
) )
521 fstrcpy(sname
, lp_servicename(snum
));
525 /* This call doesn't fill in the location or comment from
526 * a CUPS server for efficiency with large numbers of printers.
529 result
= get_a_printer_search( NULL
, &printer
, 2, sname
);
530 if ( !W_ERROR_IS_OK(result
) ) {
531 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
532 sname
, dos_errstr(result
)));
536 /* printername is always returned as \\server\printername */
537 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
538 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
539 printer
->info_2
->printername
));
540 free_a_printer( &printer
, 2);
546 if ( strequal(printername
, aprinter
) ) {
547 free_a_printer( &printer
, 2);
552 DEBUGADD(10, ("printername: %s\n", printername
));
554 free_a_printer( &printer
, 2);
557 free_a_printer( &printer
, 2);
560 DEBUGADD(4,("Printer not found\n"));
564 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
566 fstrcpy(Printer
->sharename
, sname
);
571 /****************************************************************************
572 Find first available printer slot. creates a printer handle for you.
573 ****************************************************************************/
575 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
577 Printer_entry
*new_printer
;
579 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
581 if((new_printer
=SMB_MALLOC_P(Printer_entry
)) == NULL
)
584 ZERO_STRUCTP(new_printer
);
586 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
587 SAFE_FREE(new_printer
);
591 /* Add to the internal list. */
592 DLIST_ADD(printers_list
, new_printer
);
594 new_printer
->notify
.option
=NULL
;
596 if ( !(new_printer
->ctx
= talloc_init("Printer Entry [%p]", hnd
)) ) {
597 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
598 close_printer_handle(p
, hnd
);
602 if (!set_printer_hnd_printertype(new_printer
, name
)) {
603 close_printer_handle(p
, hnd
);
607 if (!set_printer_hnd_name(new_printer
, name
)) {
608 close_printer_handle(p
, hnd
);
612 new_printer
->access_granted
= access_granted
;
614 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
619 /***************************************************************************
620 check to see if the client motify handle is monitoring the notification
621 given by (notify_type, notify_field).
622 **************************************************************************/
624 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
630 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
633 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
637 * Flags should always be zero when the change notify
638 * is registered by the client's spooler. A user Win32 app
639 * might use the flags though instead of the NOTIFY_OPTION_INFO
648 return is_monitoring_event_flags(
649 p
->notify
.flags
, notify_type
, notify_field
);
651 for (i
= 0; i
< option
->count
; i
++) {
653 /* Check match for notify_type */
655 if (option
->ctr
.type
[i
].type
!= notify_type
)
658 /* Check match for field */
660 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
661 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
667 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
668 p
->servername
, p
->sharename
, notify_type
, notify_field
));
673 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
675 static void notify_one_value(struct spoolss_notify_msg
*msg
,
676 SPOOL_NOTIFY_INFO_DATA
*data
,
679 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
680 data
->notify_data
.value
[1] = 0;
683 static void notify_string(struct spoolss_notify_msg
*msg
,
684 SPOOL_NOTIFY_INFO_DATA
*data
,
689 /* The length of the message includes the trailing \0 */
691 init_unistr2(&unistr
, msg
->notify
.data
, UNI_STR_TERMINATE
);
693 data
->notify_data
.data
.length
= msg
->len
* 2;
694 data
->notify_data
.data
.string
= TALLOC_ARRAY(mem_ctx
, uint16
, msg
->len
);
696 if (!data
->notify_data
.data
.string
) {
697 data
->notify_data
.data
.length
= 0;
701 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
704 static void notify_system_time(struct spoolss_notify_msg
*msg
,
705 SPOOL_NOTIFY_INFO_DATA
*data
,
711 if (msg
->len
!= sizeof(time_t)) {
712 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
717 if (!prs_init(&ps
, RPC_MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
718 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
722 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
723 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
728 if (!spoolss_io_system_time("", &ps
, 0, &systime
)) {
733 data
->notify_data
.data
.length
= prs_offset(&ps
);
734 if (prs_offset(&ps
)) {
735 data
->notify_data
.data
.string
= (uint16
*)
736 TALLOC(mem_ctx
, prs_offset(&ps
));
737 if (!data
->notify_data
.data
.string
) {
741 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
743 data
->notify_data
.data
.string
= NULL
;
749 struct notify2_message_table
{
751 void (*fn
)(struct spoolss_notify_msg
*msg
,
752 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
755 static struct notify2_message_table printer_notify_table
[] = {
756 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
757 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
758 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
759 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
760 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
761 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
762 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
763 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
764 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
765 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
766 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
767 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
768 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
769 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
770 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
771 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
772 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
773 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
774 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
777 static struct notify2_message_table job_notify_table
[] = {
778 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
779 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
780 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
781 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
782 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
783 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
784 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
785 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
786 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
787 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
788 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
789 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
790 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
791 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
792 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
793 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
794 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
795 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
796 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
797 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
798 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
799 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
800 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
801 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
805 /***********************************************************************
806 Allocate talloc context for container object
807 **********************************************************************/
809 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
814 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
819 /***********************************************************************
820 release all allocated memory and zero out structure
821 **********************************************************************/
823 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
829 talloc_destroy(ctr
->ctx
);
836 /***********************************************************************
837 **********************************************************************/
839 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
847 /***********************************************************************
848 **********************************************************************/
850 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
852 if ( !ctr
|| !ctr
->msg_groups
)
855 if ( idx
>= ctr
->num_groups
)
858 return &ctr
->msg_groups
[idx
];
862 /***********************************************************************
863 How many groups of change messages do we have ?
864 **********************************************************************/
866 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
871 return ctr
->num_groups
;
874 /***********************************************************************
875 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
876 **********************************************************************/
878 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
880 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
881 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
882 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
888 /* loop over all groups looking for a matching printer name */
890 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
891 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
895 /* add a new group? */
897 if ( i
== ctr
->num_groups
) {
900 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
901 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
904 ctr
->msg_groups
= groups
;
906 /* clear the new entry and set the printer name */
908 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
909 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
912 /* add the change messages; 'i' is the correct index now regardless */
914 msg_grp
= &ctr
->msg_groups
[i
];
918 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
919 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
922 msg_grp
->msgs
= msg_list
;
924 new_slot
= msg_grp
->num_msgs
-1;
925 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
927 /* need to allocate own copy of data */
930 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
931 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
933 return ctr
->num_groups
;
936 /***********************************************************************
937 Send a change notication message on all handles which have a call
939 **********************************************************************/
941 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
944 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
945 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
946 SPOOLSS_NOTIFY_MSG
*messages
;
947 int sending_msg_count
;
950 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
954 messages
= msg_group
->msgs
;
957 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
961 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
963 /* loop over all printers */
965 for (p
= printers_list
; p
; p
= p
->next
) {
966 SPOOL_NOTIFY_INFO_DATA
*data
;
971 /* Is there notification on this handle? */
973 if ( !p
->notify
.client_connected
)
976 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
978 /* For this printer? Print servers always receive
981 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
982 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
985 DEBUG(10,("Our printer\n"));
987 /* allocate the max entries possible */
989 data
= TALLOC_ARRAY( mem_ctx
, SPOOL_NOTIFY_INFO_DATA
, msg_group
->num_msgs
);
996 /* build the array of change notifications */
998 sending_msg_count
= 0;
1000 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
1001 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
1003 /* Are we monitoring this event? */
1005 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1008 sending_msg_count
++;
1011 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1012 msg
->type
, msg
->field
, p
->sharename
));
1015 * if the is a printer notification handle and not a job notification
1016 * type, then set the id to 0. Other wise just use what was specified
1019 * When registering change notification on a print server handle
1020 * we always need to send back the id (snum) matching the printer
1021 * for which the change took place. For change notify registered
1022 * on a printer handle, this does not matter and the id should be 0.
1027 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1033 /* Convert unix jobid to smb jobid */
1035 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1036 id
= sysjob_to_jobid(msg
->id
);
1039 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1044 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1047 case PRINTER_NOTIFY_TYPE
:
1048 if ( printer_notify_table
[msg
->field
].fn
)
1049 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1052 case JOB_NOTIFY_TYPE
:
1053 if ( job_notify_table
[msg
->field
].fn
)
1054 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1058 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1065 if ( sending_msg_count
) {
1066 rpccli_spoolss_rrpcn( notify_cli_pipe
, mem_ctx
, &p
->notify
.client_hnd
,
1067 data_len
, data
, p
->notify
.change
, 0 );
1072 DEBUG(8,("send_notify2_changes: Exit...\n"));
1076 /***********************************************************************
1077 **********************************************************************/
1079 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1082 uint32 tv_sec
, tv_usec
;
1085 /* Unpack message */
1087 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1090 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddddd",
1092 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1095 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1096 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1098 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1099 &msg
->len
, &msg
->notify
.data
);
1101 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1102 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1104 tv
->tv_sec
= tv_sec
;
1105 tv
->tv_usec
= tv_usec
;
1108 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1109 msg
->notify
.value
[1]));
1111 dump_data(3, msg
->notify
.data
, msg
->len
);
1116 /********************************************************************
1117 Receive a notify2 message list
1118 ********************************************************************/
1120 static void receive_notify2_message_list(int msg_type
, struct process_id src
,
1121 void *msg
, size_t len
,
1124 size_t msg_count
, i
;
1125 char *buf
= (char *)msg
;
1128 SPOOLSS_NOTIFY_MSG notify
;
1129 SPOOLSS_NOTIFY_MSG_CTR messages
;
1133 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1137 msg_count
= IVAL(buf
, 0);
1140 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1142 if (msg_count
== 0) {
1143 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1147 /* initialize the container */
1149 ZERO_STRUCT( messages
);
1150 notify_msg_ctr_init( &messages
);
1153 * build message groups for each printer identified
1154 * in a change_notify msg. Remember that a PCN message
1155 * includes the handle returned for the srv_spoolss_replyopenprinter()
1156 * call. Therefore messages are grouped according to printer handle.
1159 for ( i
=0; i
<msg_count
; i
++ ) {
1160 struct timeval msg_tv
;
1162 if (msg_ptr
+ 4 - buf
> len
) {
1163 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1167 msg_len
= IVAL(msg_ptr
,0);
1170 if (msg_ptr
+ msg_len
- buf
> len
) {
1171 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1175 /* unpack messages */
1177 ZERO_STRUCT( notify
);
1178 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1181 /* add to correct list in container */
1183 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1185 /* free memory that might have been allocated by notify2_unpack_msg() */
1187 if ( notify
.len
!= 0 )
1188 SAFE_FREE( notify
.notify
.data
);
1191 /* process each group of messages */
1193 num_groups
= notify_msg_ctr_numgroups( &messages
);
1194 for ( i
=0; i
<num_groups
; i
++ )
1195 send_notify2_changes( &messages
, i
);
1200 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1202 notify_msg_ctr_destroy( &messages
);
1207 /********************************************************************
1208 Send a message to ourself about new driver being installed
1209 so we can upgrade the information for each printer bound to this
1211 ********************************************************************/
1213 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1215 int len
= strlen(drivername
);
1220 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1223 message_send_pid(pid_to_procid(sys_getpid()),
1224 MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1229 /**********************************************************************
1230 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1231 over all printers, upgrading ones as necessary
1232 **********************************************************************/
1234 void do_drv_upgrade_printer(int msg_type
, struct process_id src
,
1235 void *buf
, size_t len
, void *private_data
)
1239 int n_services
= lp_numservices();
1241 len
= MIN(len
,sizeof(drivername
)-1);
1242 strncpy(drivername
, (const char *)buf
, len
);
1244 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1246 /* Iterate the printer list */
1248 for (snum
=0; snum
<n_services
; snum
++)
1250 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1253 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1255 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1256 if (!W_ERROR_IS_OK(result
))
1259 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1261 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1263 /* all we care about currently is the change_id */
1265 result
= mod_a_printer(printer
, 2);
1266 if (!W_ERROR_IS_OK(result
)) {
1267 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1268 dos_errstr(result
)));
1272 free_a_printer(&printer
, 2);
1279 /********************************************************************
1280 Update the cache for all printq's with a registered client
1282 ********************************************************************/
1284 void update_monitored_printq_cache( void )
1286 Printer_entry
*printer
= printers_list
;
1289 /* loop through all printers and update the cache where
1290 client_connected == True */
1293 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1294 && printer
->notify
.client_connected
)
1296 snum
= print_queue_snum(printer
->sharename
);
1297 print_queue_status( snum
, NULL
, NULL
);
1300 printer
= printer
->next
;
1305 /********************************************************************
1306 Send a message to ourself about new driver being installed
1307 so we can upgrade the information for each printer bound to this
1309 ********************************************************************/
1311 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1313 int len
= strlen(drivername
);
1318 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1321 message_send_pid(pid_to_procid(sys_getpid()),
1322 MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1327 /**********************************************************************
1328 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1329 over all printers, resetting printer data as neessary
1330 **********************************************************************/
1332 void reset_all_printerdata(int msg_type
, struct process_id src
,
1333 void *buf
, size_t len
, void *private_data
)
1337 int n_services
= lp_numservices();
1339 len
= MIN( len
, sizeof(drivername
)-1 );
1340 strncpy( drivername
, (const char *)buf
, len
);
1342 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1344 /* Iterate the printer list */
1346 for ( snum
=0; snum
<n_services
; snum
++ )
1348 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1351 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1353 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1354 if ( !W_ERROR_IS_OK(result
) )
1358 * if the printer is bound to the driver,
1359 * then reset to the new driver initdata
1362 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1364 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1366 if ( !set_driver_init(printer
, 2) ) {
1367 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1368 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1371 result
= mod_a_printer( printer
, 2 );
1372 if ( !W_ERROR_IS_OK(result
) ) {
1373 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1374 get_dos_error_msg(result
)));
1378 free_a_printer( &printer
, 2 );
1387 /********************************************************************
1388 Copy routines used by convert_to_openprinterex()
1389 *******************************************************************/
1391 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1399 DEBUG (8,("dup_devmode\n"));
1401 /* bulk copy first */
1403 d
= (DEVICEMODE
*)TALLOC_MEMDUP(ctx
, devmode
, sizeof(DEVICEMODE
));
1407 /* dup the pointer members separately */
1409 len
= unistrlen(devmode
->devicename
.buffer
);
1411 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1412 if (!d
->devicename
.buffer
) {
1415 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1420 len
= unistrlen(devmode
->formname
.buffer
);
1422 d
->formname
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1423 if (!d
->formname
.buffer
) {
1426 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1430 if (devmode
->driverextra
) {
1431 d
->dev_private
= (uint8
*)TALLOC_MEMDUP(ctx
, devmode
->dev_private
,
1432 devmode
->driverextra
);
1433 if (!d
->dev_private
) {
1437 d
->dev_private
= NULL
;
1442 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1444 if (!new_ctr
|| !ctr
)
1447 DEBUG(8,("copy_devmode_ctr\n"));
1449 new_ctr
->size
= ctr
->size
;
1450 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1452 if(ctr
->devmode_ptr
)
1453 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1456 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1458 if (!new_def
|| !def
)
1461 DEBUG(8,("copy_printer_defaults\n"));
1463 new_def
->datatype_ptr
= def
->datatype_ptr
;
1465 if (def
->datatype_ptr
)
1466 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1468 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1470 new_def
->access_required
= def
->access_required
;
1473 /********************************************************************
1474 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1475 * SPOOL_Q_OPEN_PRINTER_EX structure
1476 ********************************************************************/
1478 static WERROR
convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1480 if (!q_u_ex
|| !q_u
)
1483 DEBUG(8,("convert_to_openprinterex\n"));
1485 if ( q_u
->printername
) {
1486 q_u_ex
->printername
= TALLOC_ZERO_P( ctx
, UNISTR2
);
1487 if (q_u_ex
->printername
== NULL
)
1489 copy_unistr2(q_u_ex
->printername
, q_u
->printername
);
1492 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1497 /********************************************************************
1498 * spoolss_open_printer
1500 * called from the spoolss dispatcher
1501 ********************************************************************/
1503 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1505 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1506 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1511 ZERO_STRUCT(q_u_ex
);
1512 ZERO_STRUCT(r_u_ex
);
1514 /* convert the OpenPrinter() call to OpenPrinterEx() */
1516 r_u_ex
.status
= convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1517 if (!W_ERROR_IS_OK(r_u_ex
.status
))
1518 return r_u_ex
.status
;
1520 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1522 /* convert back to OpenPrinter() */
1524 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1529 /********************************************************************
1530 ********************************************************************/
1532 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1534 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1535 POLICY_HND
*handle
= &r_u
->handle
;
1539 struct current_user user
;
1540 Printer_entry
*Printer
=NULL
;
1542 if ( !q_u
->printername
)
1543 return WERR_INVALID_PRINTER_NAME
;
1545 /* some sanity check because you can open a printer or a print server */
1546 /* aka: \\server\printer or \\server */
1548 unistr2_to_ascii(name
, q_u
->printername
, sizeof(name
)-1);
1550 DEBUGADD(3,("checking name: %s\n",name
));
1552 if (!open_printer_hnd(p
, handle
, name
, 0))
1553 return WERR_INVALID_PRINTER_NAME
;
1555 Printer
=find_printer_index_by_hnd(p
, handle
);
1557 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1558 "handle we created for printer %s\n", name
));
1559 close_printer_handle(p
,handle
);
1560 return WERR_INVALID_PRINTER_NAME
;
1563 get_current_user(&user
, p
);
1566 * First case: the user is opening the print server:
1568 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1569 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1571 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1572 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1573 * or if the user is listed in the smb.conf printer admin parameter.
1575 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1576 * client view printer folder, but does not show the MSAPW.
1578 * Note: this test needs code to check access rights here too. Jeremy
1579 * could you look at this?
1581 * Second case: the user is opening a printer:
1582 * NT doesn't let us connect to a printer if the connecting user
1583 * doesn't have print permission.
1585 * Third case: user is opening a Port Monitor
1586 * access checks same as opening a handle to the print server.
1589 switch (Printer
->printer_type
)
1592 case SPLHND_PORTMON_TCP
:
1593 case SPLHND_PORTMON_LOCAL
:
1594 /* Printserver handles use global struct... */
1598 /* Map standard access rights to object specific access rights */
1600 se_map_standard(&printer_default
->access_required
,
1601 &printserver_std_mapping
);
1603 /* Deny any object specific bits that don't apply to print
1604 servers (i.e printer and job specific bits) */
1606 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1608 if (printer_default
->access_required
&
1609 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1610 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1611 close_printer_handle(p
, handle
);
1612 return WERR_ACCESS_DENIED
;
1615 /* Allow admin access */
1617 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1619 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1621 if (!lp_ms_add_printer_wizard()) {
1622 close_printer_handle(p
, handle
);
1623 return WERR_ACCESS_DENIED
;
1626 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1627 and not a printer admin, then fail */
1629 if ((user
.ut
.uid
!= 0) &&
1630 !user_has_privileges(user
.nt_user_token
,
1632 !token_contains_name_in_list(
1633 uidtoname(user
.ut
.uid
), NULL
,
1635 lp_printer_admin(snum
))) {
1636 close_printer_handle(p
, handle
);
1637 return WERR_ACCESS_DENIED
;
1640 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1644 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1647 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1648 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1650 /* We fall through to return WERR_OK */
1653 case SPLHND_PRINTER
:
1654 /* NT doesn't let us connect to a printer if the connecting user
1655 doesn't have print permission. */
1657 if (!get_printer_snum(p
, handle
, &snum
)) {
1658 close_printer_handle(p
, handle
);
1662 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1664 /* map an empty access mask to the minimum access mask */
1665 if (printer_default
->access_required
== 0x0)
1666 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1669 * If we are not serving the printer driver for this printer,
1670 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1671 * will keep NT clients happy --jerry
1674 if (lp_use_client_driver(snum
)
1675 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1677 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1680 /* check smb.conf parameters and the the sec_desc */
1682 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1683 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1684 return WERR_ACCESS_DENIED
;
1687 if (!user_ok_token(uidtoname(user
.ut
.uid
), user
.nt_user_token
,
1689 !print_access_check(&user
, snum
,
1690 printer_default
->access_required
)) {
1691 DEBUG(3, ("access DENIED for printer open\n"));
1692 close_printer_handle(p
, handle
);
1693 return WERR_ACCESS_DENIED
;
1696 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1697 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1698 close_printer_handle(p
, handle
);
1699 return WERR_ACCESS_DENIED
;
1702 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1703 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1705 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1707 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1708 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1713 /* sanity check to prevent programmer error */
1717 Printer
->access_granted
= printer_default
->access_required
;
1720 * If the client sent a devmode in the OpenPrinter() call, then
1721 * save it here in case we get a job submission on this handle
1724 if ( (Printer
->printer_type
!= SPLHND_SERVER
)
1725 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1727 convert_devicemode( Printer
->sharename
, q_u
->printer_default
.devmode_cont
.devmode
,
1728 &Printer
->nt_devmode
);
1731 #if 0 /* JERRY -- I'm doubtful this is really effective */
1732 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1733 optimization in Windows 2000 clients --jerry */
1735 if ( (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1736 && (RA_WIN2K
== get_remote_arch()) )
1738 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1739 sys_usleep( 500000 );
1746 /****************************************************************************
1747 ****************************************************************************/
1749 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1750 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1756 /* allocate memory if needed. Messy because
1757 convert_printer_info is used to update an existing
1758 printer or build a new one */
1760 if ( !printer
->info_2
) {
1761 printer
->info_2
= TALLOC_ZERO_P( printer
, NT_PRINTER_INFO_LEVEL_2
);
1762 if ( !printer
->info_2
) {
1763 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1768 ret
= uni_2_asc_printer_info_2(uni
->info_2
, printer
->info_2
);
1769 printer
->info_2
->setuptime
= time(NULL
);
1777 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1778 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1784 printer
->info_3
=NULL
;
1785 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1789 printer
->info_6
=NULL
;
1790 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1800 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1801 NT_DEVICEMODE
**pp_nt_devmode
)
1803 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1806 * Ensure nt_devmode is a valid pointer
1807 * as we will be overwriting it.
1810 if (nt_devmode
== NULL
) {
1811 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1812 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1816 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1817 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1819 nt_devmode
->specversion
=devmode
->specversion
;
1820 nt_devmode
->driverversion
=devmode
->driverversion
;
1821 nt_devmode
->size
=devmode
->size
;
1822 nt_devmode
->fields
=devmode
->fields
;
1823 nt_devmode
->orientation
=devmode
->orientation
;
1824 nt_devmode
->papersize
=devmode
->papersize
;
1825 nt_devmode
->paperlength
=devmode
->paperlength
;
1826 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1827 nt_devmode
->scale
=devmode
->scale
;
1828 nt_devmode
->copies
=devmode
->copies
;
1829 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1830 nt_devmode
->printquality
=devmode
->printquality
;
1831 nt_devmode
->color
=devmode
->color
;
1832 nt_devmode
->duplex
=devmode
->duplex
;
1833 nt_devmode
->yresolution
=devmode
->yresolution
;
1834 nt_devmode
->ttoption
=devmode
->ttoption
;
1835 nt_devmode
->collate
=devmode
->collate
;
1837 nt_devmode
->logpixels
=devmode
->logpixels
;
1838 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1839 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1840 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1841 nt_devmode
->displayflags
=devmode
->displayflags
;
1842 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1843 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1844 nt_devmode
->icmintent
=devmode
->icmintent
;
1845 nt_devmode
->mediatype
=devmode
->mediatype
;
1846 nt_devmode
->dithertype
=devmode
->dithertype
;
1847 nt_devmode
->reserved1
=devmode
->reserved1
;
1848 nt_devmode
->reserved2
=devmode
->reserved2
;
1849 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1850 nt_devmode
->panningheight
=devmode
->panningheight
;
1853 * Only change private and driverextra if the incoming devmode
1854 * has a new one. JRA.
1857 if ((devmode
->driverextra
!= 0) && (devmode
->dev_private
!= NULL
)) {
1858 SAFE_FREE(nt_devmode
->nt_dev_private
);
1859 nt_devmode
->driverextra
=devmode
->driverextra
;
1860 if((nt_devmode
->nt_dev_private
=SMB_MALLOC_ARRAY(uint8
, nt_devmode
->driverextra
)) == NULL
)
1862 memcpy(nt_devmode
->nt_dev_private
, devmode
->dev_private
, nt_devmode
->driverextra
);
1865 *pp_nt_devmode
= nt_devmode
;
1870 /********************************************************************
1871 * _spoolss_enddocprinter_internal.
1872 ********************************************************************/
1874 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1876 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1880 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1884 if (!get_printer_snum(p
, handle
, &snum
))
1887 Printer
->document_started
=False
;
1888 print_job_end(snum
, Printer
->jobid
,NORMAL_CLOSE
);
1889 /* error codes unhandled so far ... */
1894 /********************************************************************
1895 * api_spoolss_closeprinter
1896 ********************************************************************/
1898 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1900 POLICY_HND
*handle
= &q_u
->handle
;
1902 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 if (!close_printer_handle(p
, handle
))
1910 /* clear the returned printer handle. Observed behavior
1911 from Win2k server. Don't think this really matters.
1912 Previous code just copied the value of the closed
1915 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1920 /********************************************************************
1921 * api_spoolss_deleteprinter
1923 ********************************************************************/
1925 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1927 POLICY_HND
*handle
= &q_u
->handle
;
1928 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1931 if (Printer
&& Printer
->document_started
)
1932 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1934 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1936 result
= delete_printer_handle(p
, handle
);
1938 update_c_setprinter(False
);
1943 /*******************************************************************
1944 * static function to lookup the version id corresponding to an
1945 * long architecture string
1946 ******************************************************************/
1948 static int get_version_id (char * arch
)
1951 struct table_node archi_table
[]= {
1953 {"Windows 4.0", "WIN40", 0 },
1954 {"Windows NT x86", "W32X86", 2 },
1955 {"Windows NT R4000", "W32MIPS", 2 },
1956 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1957 {"Windows NT PowerPC", "W32PPC", 2 },
1958 {"Windows IA64", "IA64", 3 },
1959 {"Windows x64", "x64", 3 },
1963 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1965 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1966 return (archi_table
[i
].version
);
1972 /********************************************************************
1973 * _spoolss_deleteprinterdriver
1974 ********************************************************************/
1976 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1980 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1981 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1983 struct current_user user
;
1985 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1986 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1988 get_current_user(&user
, p
);
1990 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1991 and not a printer admin, then fail */
1993 if ( (user
.ut
.uid
!= 0)
1994 && !user_has_privileges(user
.nt_user_token
, &se_printop
)
1995 && !token_contains_name_in_list( uidtoname(user
.ut
.uid
),
1996 NULL
, user
.nt_user_token
, lp_printer_admin(-1)) )
1998 return WERR_ACCESS_DENIED
;
2001 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2002 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2004 /* check that we have a valid driver name first */
2006 if ((version
=get_version_id(arch
)) == -1)
2007 return WERR_INVALID_ENVIRONMENT
;
2010 ZERO_STRUCT(info_win2k
);
2012 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
2014 /* try for Win2k driver if "Windows NT x86" */
2016 if ( version
== 2 ) {
2018 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2019 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2023 /* otherwise it was a failure */
2025 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2031 if (printer_driver_in_use(info
.info_3
)) {
2032 status
= WERR_PRINTER_DRIVER_IN_USE
;
2038 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2040 /* if we get to here, we now have 2 driver info structures to remove */
2041 /* remove the Win2k driver first*/
2043 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, False
);
2044 free_a_printer_driver( info_win2k
, 3 );
2046 /* this should not have failed---if it did, report to client */
2047 if ( !W_ERROR_IS_OK(status_win2k
) )
2049 status
= status_win2k
;
2055 status
= delete_printer_driver(info
.info_3
, &user
, version
, False
);
2057 /* if at least one of the deletes succeeded return OK */
2059 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2063 free_a_printer_driver( info
, 3 );
2068 /********************************************************************
2069 * spoolss_deleteprinterdriverex
2070 ********************************************************************/
2072 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
2076 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2077 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2079 uint32 flags
= q_u
->delete_flags
;
2081 struct current_user user
;
2083 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2084 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2086 get_current_user(&user
, p
);
2088 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2089 and not a printer admin, then fail */
2091 if ( (user
.ut
.uid
!= 0)
2092 && !user_has_privileges(user
.nt_user_token
, &se_printop
)
2093 && !token_contains_name_in_list( uidtoname(user
.ut
.uid
),
2094 NULL
, user
.nt_user_token
, lp_printer_admin(-1)) )
2096 return WERR_ACCESS_DENIED
;
2099 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2100 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2102 /* check that we have a valid driver name first */
2103 if ((version
=get_version_id(arch
)) == -1) {
2104 /* this is what NT returns */
2105 return WERR_INVALID_ENVIRONMENT
;
2108 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2109 version
= q_u
->version
;
2112 ZERO_STRUCT(info_win2k
);
2114 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2116 if ( !W_ERROR_IS_OK(status
) )
2119 * if the client asked for a specific version,
2120 * or this is something other than Windows NT x86,
2124 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2127 /* try for Win2k driver if "Windows NT x86" */
2130 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2131 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2136 if ( printer_driver_in_use(info
.info_3
) ) {
2137 status
= WERR_PRINTER_DRIVER_IN_USE
;
2142 * we have a couple of cases to consider.
2143 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2144 * then the delete should fail if **any** files overlap with
2146 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2147 * non-overlapping files
2148 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2149 * is set, the do not delete any files
2150 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2153 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2155 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2157 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2158 /* no idea of the correct error here */
2159 status
= WERR_ACCESS_DENIED
;
2164 /* also check for W32X86/3 if necessary; maybe we already have? */
2166 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2167 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2170 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2171 /* no idea of the correct error here */
2172 free_a_printer_driver( info_win2k
, 3 );
2173 status
= WERR_ACCESS_DENIED
;
2177 /* if we get to here, we now have 2 driver info structures to remove */
2178 /* remove the Win2k driver first*/
2180 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &user
, 3, delete_files
);
2181 free_a_printer_driver( info_win2k
, 3 );
2183 /* this should not have failed---if it did, report to client */
2185 if ( !W_ERROR_IS_OK(status_win2k
) )
2190 status
= delete_printer_driver(info
.info_3
, &user
, version
, delete_files
);
2192 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2195 free_a_printer_driver( info
, 3 );
2201 /****************************************************************************
2202 Internal routine for retreiving printerdata
2203 ***************************************************************************/
2205 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2206 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2207 uint32
*needed
, uint32 in_size
)
2209 REGISTRY_VALUE
*val
;
2213 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2214 return WERR_BADFILE
;
2216 *type
= regval_type( val
);
2218 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2220 size
= regval_size( val
);
2222 /* copy the min(in_size, len) */
2225 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2227 /* special case for 0 length values */
2229 if ( (*data
= (uint8
*)TALLOC_MEMDUP(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2233 if ( (*data
= (uint8
*)TALLOC_ZERO(ctx
, in_size
)) == NULL
)
2242 DEBUG(5,("get_printer_dataex: copy done\n"));
2247 /****************************************************************************
2248 Internal routine for removing printerdata
2249 ***************************************************************************/
2251 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2253 return delete_printer_data( printer
->info_2
, key
, value
);
2256 /****************************************************************************
2257 Internal routine for storing printerdata
2258 ***************************************************************************/
2260 WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2261 uint32 type
, uint8
*data
, int real_len
)
2263 /* the registry objects enforce uniqueness based on value name */
2265 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2268 /********************************************************************
2269 GetPrinterData on a printer server Handle.
2270 ********************************************************************/
2272 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2276 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2278 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2280 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2282 SIVAL(*data
, 0, 0x00);
2287 if (!StrCaseCmp(value
, "BeepEnabled")) {
2289 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2291 SIVAL(*data
, 0, 0x00);
2296 if (!StrCaseCmp(value
, "EventLog")) {
2298 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2300 /* formally was 0x1b */
2301 SIVAL(*data
, 0, 0x0);
2306 if (!StrCaseCmp(value
, "NetPopup")) {
2308 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2310 SIVAL(*data
, 0, 0x00);
2315 if (!StrCaseCmp(value
, "MajorVersion")) {
2317 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2320 /* Windows NT 4.0 seems to not allow uploading of drivers
2321 to a server that reports 0x3 as the MajorVersion.
2322 need to investigate more how Win2k gets around this .
2325 if ( RA_WINNT
== get_remote_arch() )
2334 if (!StrCaseCmp(value
, "MinorVersion")) {
2336 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2344 * uint32 size = 0x114
2346 * uint32 minor = [0|1]
2347 * uint32 build = [2195|2600]
2348 * extra unicode string = e.g. "Service Pack 3"
2350 if (!StrCaseCmp(value
, "OSVersion")) {
2354 if ( !(*data
= TALLOC_ZERO_ARRAY(ctx
, uint8
, (*needed
> in_size
) ? *needed
:in_size
)) )
2357 SIVAL(*data
, 0, *needed
); /* size */
2358 SIVAL(*data
, 4, 5); /* Windows 2000 == 5.0 */
2360 SIVAL(*data
, 12, 2195); /* build */
2362 /* leave extra string empty */
2368 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2369 const char *string
="C:\\PRINTERS";
2371 *needed
= 2*(strlen(string
)+1);
2372 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2374 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2376 /* it's done by hand ready to go on the wire */
2377 for (i
=0; i
<strlen(string
); i
++) {
2378 (*data
)[2*i
]=string
[i
];
2379 (*data
)[2*i
+1]='\0';
2384 if (!StrCaseCmp(value
, "Architecture")) {
2385 const char *string
="Windows NT x86";
2387 *needed
= 2*(strlen(string
)+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(string
); i
++) {
2392 (*data
)[2*i
]=string
[i
];
2393 (*data
)[2*i
+1]='\0';
2398 if (!StrCaseCmp(value
, "DsPresent")) {
2400 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2403 /* only show the publish check box if we are a
2404 memeber of a AD domain */
2406 if ( lp_security() == SEC_ADS
)
2407 SIVAL(*data
, 0, 0x01);
2409 SIVAL(*data
, 0, 0x00);
2415 if (!StrCaseCmp(value
, "DNSMachineName")) {
2418 if (!get_mydnsfullname(hostname
))
2419 return WERR_BADFILE
;
2421 *needed
= 2*(strlen(hostname
)+1);
2422 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2424 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2425 for (i
=0; i
<strlen(hostname
); i
++) {
2426 (*data
)[2*i
]=hostname
[i
];
2427 (*data
)[2*i
+1]='\0';
2433 return WERR_BADFILE
;
2436 /********************************************************************
2437 * spoolss_getprinterdata
2438 ********************************************************************/
2440 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2442 POLICY_HND
*handle
= &q_u
->handle
;
2443 UNISTR2
*valuename
= &q_u
->valuename
;
2444 uint32 in_size
= q_u
->size
;
2445 uint32
*type
= &r_u
->type
;
2446 uint32
*out_size
= &r_u
->size
;
2447 uint8
**data
= &r_u
->data
;
2448 uint32
*needed
= &r_u
->needed
;
2451 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2452 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2456 * Reminder: when it's a string, the length is in BYTES
2457 * even if UNICODE is negociated.
2462 *out_size
= in_size
;
2464 /* in case of problem, return some default values */
2469 DEBUG(4,("_spoolss_getprinterdata\n"));
2472 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2473 status
= WERR_BADFID
;
2477 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2479 if ( Printer
->printer_type
== SPLHND_SERVER
)
2480 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2483 if ( !get_printer_snum(p
,handle
, &snum
) ) {
2484 status
= WERR_BADFID
;
2488 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2489 if ( !W_ERROR_IS_OK(status
) )
2492 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2494 if ( strequal(value
, "ChangeId") ) {
2496 *needed
= sizeof(uint32
);
2497 if ( (*data
= (uint8
*)TALLOC(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2498 status
= WERR_NOMEM
;
2501 SIVAL( *data
, 0, printer
->info_2
->changeid
);
2505 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2508 if (*needed
> *out_size
)
2509 status
= WERR_MORE_DATA
;
2512 if ( !W_ERROR_IS_OK(status
) )
2514 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2516 /* reply this param doesn't exist */
2519 if((*data
=(uint8
*)TALLOC_ZERO_ARRAY(p
->mem_ctx
, uint8
, *out_size
)) == NULL
) {
2521 free_a_printer( &printer
, 2 );
2529 /* cleanup & exit */
2532 free_a_printer( &printer
, 2 );
2537 /*********************************************************
2538 Connect to the client machine.
2539 **********************************************************/
2541 static BOOL
spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2542 struct in_addr
*client_ip
, const char *remote_machine
)
2545 struct cli_state
*the_cli
;
2546 struct in_addr rm_addr
;
2548 if ( is_zero_ip(*client_ip
) ) {
2549 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20) ) {
2550 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2554 if ( ismyip( rm_addr
)) {
2555 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2559 rm_addr
.s_addr
= client_ip
->s_addr
;
2560 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2561 inet_ntoa(*client_ip
) ));
2564 /* setup the connection */
2566 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2567 &rm_addr
, 0, "IPC$", "IPC",
2571 0, lp_client_signing(), NULL
);
2573 if ( !NT_STATUS_IS_OK( ret
) ) {
2574 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2579 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2580 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2581 cli_shutdown(the_cli
);
2586 * Ok - we have an anonymous connection to the IPC$ share.
2587 * Now start the NT Domain stuff :-).
2590 if ( !(*pp_pipe
= cli_rpc_pipe_open_noauth(the_cli
, PI_SPOOLSS
, &ret
)) ) {
2591 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2592 remote_machine
, nt_errstr(ret
)));
2593 cli_shutdown(the_cli
);
2597 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2599 (*pp_pipe
)->cli
= the_cli
;
2604 /***************************************************************************
2605 Connect to the client.
2606 ****************************************************************************/
2608 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2609 uint32 localprinter
, uint32 type
,
2610 POLICY_HND
*handle
, struct in_addr
*client_ip
)
2615 * If it's the first connection, contact the client
2616 * and connect to the IPC$ share anonymously
2618 if (smb_connections
==0) {
2619 fstring unix_printer
;
2621 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2623 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ip
, unix_printer
))
2626 message_register(MSG_PRINTER_NOTIFY2
,
2627 receive_notify2_message_list
, NULL
);
2628 /* Tell the connections db we're now interested in printer
2629 * notify messages. */
2630 register_message_flags( True
, FLAG_MSG_PRINT_NOTIFY
);
2634 * Tell the specific printing tdb we want messages for this printer
2635 * by registering our PID.
2638 if (!print_notify_register_pid(snum
))
2639 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2643 result
= rpccli_spoolss_reply_open_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, printer
, localprinter
,
2646 if (!W_ERROR_IS_OK(result
))
2647 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2648 dos_errstr(result
)));
2650 return (W_ERROR_IS_OK(result
));
2653 /********************************************************************
2655 * ReplyFindFirstPrinterChangeNotifyEx
2657 * before replying OK: status=0 a rpc call is made to the workstation
2658 * asking ReplyOpenPrinter
2660 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2661 * called from api_spoolss_rffpcnex
2662 ********************************************************************/
2664 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2666 POLICY_HND
*handle
= &q_u
->handle
;
2667 uint32 flags
= q_u
->flags
;
2668 uint32 options
= q_u
->options
;
2669 UNISTR2
*localmachine
= &q_u
->localmachine
;
2670 uint32 printerlocal
= q_u
->printerlocal
;
2672 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2673 struct in_addr client_ip
;
2675 /* store the notify value in the printer struct */
2677 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2680 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2684 Printer
->notify
.flags
=flags
;
2685 Printer
->notify
.options
=options
;
2686 Printer
->notify
.printerlocal
=printerlocal
;
2688 if (Printer
->notify
.option
)
2689 free_spool_notify_option(&Printer
->notify
.option
);
2691 Printer
->notify
.option
=dup_spool_notify_option(option
);
2693 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2694 sizeof(Printer
->notify
.localmachine
)-1);
2696 /* Connect to the client machine and send a ReplyOpenPrinter */
2698 if ( Printer
->printer_type
== SPLHND_SERVER
)
2700 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2701 !get_printer_snum(p
, handle
, &snum
) )
2704 client_ip
.s_addr
= inet_addr(p
->conn
->client_address
);
2706 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2707 Printer
->notify
.printerlocal
, 1,
2708 &Printer
->notify
.client_hnd
, &client_ip
))
2709 return WERR_SERVER_UNAVAILABLE
;
2711 Printer
->notify
.client_connected
=True
;
2716 /*******************************************************************
2717 * fill a notify_info_data with the servername
2718 ********************************************************************/
2720 void spoolss_notify_server_name(int snum
,
2721 SPOOL_NOTIFY_INFO_DATA
*data
,
2722 print_queue_struct
*queue
,
2723 NT_PRINTER_INFO_LEVEL
*printer
,
2724 TALLOC_CTX
*mem_ctx
)
2729 len
= rpcstr_push(temp
, printer
->info_2
->servername
, sizeof(temp
)-2, STR_TERMINATE
);
2731 data
->notify_data
.data
.length
= len
;
2733 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2734 if (!data
->notify_data
.data
.string
) {
2735 data
->notify_data
.data
.length
= 0;
2739 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2741 data
->notify_data
.data
.string
= NULL
;
2745 /*******************************************************************
2746 * fill a notify_info_data with the printername (not including the servername).
2747 ********************************************************************/
2749 void spoolss_notify_printer_name(int snum
,
2750 SPOOL_NOTIFY_INFO_DATA
*data
,
2751 print_queue_struct
*queue
,
2752 NT_PRINTER_INFO_LEVEL
*printer
,
2753 TALLOC_CTX
*mem_ctx
)
2758 /* the notify name should not contain the \\server\ part */
2759 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2762 p
= printer
->info_2
->printername
;
2767 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2769 data
->notify_data
.data
.length
= len
;
2771 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2772 if (!data
->notify_data
.data
.string
) {
2773 data
->notify_data
.data
.length
= 0;
2776 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2778 data
->notify_data
.data
.string
= NULL
;
2782 /*******************************************************************
2783 * fill a notify_info_data with the servicename
2784 ********************************************************************/
2786 void spoolss_notify_share_name(int snum
,
2787 SPOOL_NOTIFY_INFO_DATA
*data
,
2788 print_queue_struct
*queue
,
2789 NT_PRINTER_INFO_LEVEL
*printer
,
2790 TALLOC_CTX
*mem_ctx
)
2795 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2797 data
->notify_data
.data
.length
= len
;
2799 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2800 if (!data
->notify_data
.data
.string
) {
2801 data
->notify_data
.data
.length
= 0;
2804 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2806 data
->notify_data
.data
.string
= NULL
;
2811 /*******************************************************************
2812 * fill a notify_info_data with the port name
2813 ********************************************************************/
2815 void spoolss_notify_port_name(int snum
,
2816 SPOOL_NOTIFY_INFO_DATA
*data
,
2817 print_queue_struct
*queue
,
2818 NT_PRINTER_INFO_LEVEL
*printer
,
2819 TALLOC_CTX
*mem_ctx
)
2824 /* even if it's strange, that's consistant in all the code */
2826 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2828 data
->notify_data
.data
.length
= len
;
2830 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2832 if (!data
->notify_data
.data
.string
) {
2833 data
->notify_data
.data
.length
= 0;
2837 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2839 data
->notify_data
.data
.string
= NULL
;
2843 /*******************************************************************
2844 * fill a notify_info_data with the printername
2845 * but it doesn't exist, have to see what to do
2846 ********************************************************************/
2848 void spoolss_notify_driver_name(int snum
,
2849 SPOOL_NOTIFY_INFO_DATA
*data
,
2850 print_queue_struct
*queue
,
2851 NT_PRINTER_INFO_LEVEL
*printer
,
2852 TALLOC_CTX
*mem_ctx
)
2857 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2859 data
->notify_data
.data
.length
= len
;
2861 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2863 if (!data
->notify_data
.data
.string
) {
2864 data
->notify_data
.data
.length
= 0;
2868 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2870 data
->notify_data
.data
.string
= NULL
;
2874 /*******************************************************************
2875 * fill a notify_info_data with the comment
2876 ********************************************************************/
2878 void spoolss_notify_comment(int snum
,
2879 SPOOL_NOTIFY_INFO_DATA
*data
,
2880 print_queue_struct
*queue
,
2881 NT_PRINTER_INFO_LEVEL
*printer
,
2882 TALLOC_CTX
*mem_ctx
)
2887 if (*printer
->info_2
->comment
== '\0')
2888 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2890 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2892 data
->notify_data
.data
.length
= len
;
2894 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2896 if (!data
->notify_data
.data
.string
) {
2897 data
->notify_data
.data
.length
= 0;
2901 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2903 data
->notify_data
.data
.string
= NULL
;
2907 /*******************************************************************
2908 * fill a notify_info_data with the comment
2909 * location = "Room 1, floor 2, building 3"
2910 ********************************************************************/
2912 void spoolss_notify_location(int snum
,
2913 SPOOL_NOTIFY_INFO_DATA
*data
,
2914 print_queue_struct
*queue
,
2915 NT_PRINTER_INFO_LEVEL
*printer
,
2916 TALLOC_CTX
*mem_ctx
)
2921 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2923 data
->notify_data
.data
.length
= len
;
2925 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2927 if (!data
->notify_data
.data
.string
) {
2928 data
->notify_data
.data
.length
= 0;
2932 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2934 data
->notify_data
.data
.string
= NULL
;
2938 /*******************************************************************
2939 * fill a notify_info_data with the device mode
2940 * jfm:xxxx don't to it for know but that's a real problem !!!
2941 ********************************************************************/
2943 static void spoolss_notify_devmode(int snum
,
2944 SPOOL_NOTIFY_INFO_DATA
*data
,
2945 print_queue_struct
*queue
,
2946 NT_PRINTER_INFO_LEVEL
*printer
,
2947 TALLOC_CTX
*mem_ctx
)
2949 /* for a dummy implementation we have to zero the fields */
2950 data
->notify_data
.data
.length
= 0;
2951 data
->notify_data
.data
.string
= NULL
;
2954 /*******************************************************************
2955 * fill a notify_info_data with the separator file name
2956 ********************************************************************/
2958 void spoolss_notify_sepfile(int snum
,
2959 SPOOL_NOTIFY_INFO_DATA
*data
,
2960 print_queue_struct
*queue
,
2961 NT_PRINTER_INFO_LEVEL
*printer
,
2962 TALLOC_CTX
*mem_ctx
)
2967 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2969 data
->notify_data
.data
.length
= len
;
2971 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2973 if (!data
->notify_data
.data
.string
) {
2974 data
->notify_data
.data
.length
= 0;
2978 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2980 data
->notify_data
.data
.string
= NULL
;
2984 /*******************************************************************
2985 * fill a notify_info_data with the print processor
2986 * jfm:xxxx return always winprint to indicate we don't do anything to it
2987 ********************************************************************/
2989 void spoolss_notify_print_processor(int snum
,
2990 SPOOL_NOTIFY_INFO_DATA
*data
,
2991 print_queue_struct
*queue
,
2992 NT_PRINTER_INFO_LEVEL
*printer
,
2993 TALLOC_CTX
*mem_ctx
)
2998 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
3000 data
->notify_data
.data
.length
= len
;
3002 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3004 if (!data
->notify_data
.data
.string
) {
3005 data
->notify_data
.data
.length
= 0;
3009 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3011 data
->notify_data
.data
.string
= NULL
;
3015 /*******************************************************************
3016 * fill a notify_info_data with the print processor options
3017 * jfm:xxxx send an empty string
3018 ********************************************************************/
3020 void spoolss_notify_parameters(int snum
,
3021 SPOOL_NOTIFY_INFO_DATA
*data
,
3022 print_queue_struct
*queue
,
3023 NT_PRINTER_INFO_LEVEL
*printer
,
3024 TALLOC_CTX
*mem_ctx
)
3029 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
3031 data
->notify_data
.data
.length
= len
;
3033 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3035 if (!data
->notify_data
.data
.string
) {
3036 data
->notify_data
.data
.length
= 0;
3040 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3042 data
->notify_data
.data
.string
= NULL
;
3046 /*******************************************************************
3047 * fill a notify_info_data with the data type
3048 * jfm:xxxx always send RAW as data type
3049 ********************************************************************/
3051 void spoolss_notify_datatype(int snum
,
3052 SPOOL_NOTIFY_INFO_DATA
*data
,
3053 print_queue_struct
*queue
,
3054 NT_PRINTER_INFO_LEVEL
*printer
,
3055 TALLOC_CTX
*mem_ctx
)
3060 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
3062 data
->notify_data
.data
.length
= len
;
3064 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3066 if (!data
->notify_data
.data
.string
) {
3067 data
->notify_data
.data
.length
= 0;
3071 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3073 data
->notify_data
.data
.string
= NULL
;
3077 /*******************************************************************
3078 * fill a notify_info_data with the security descriptor
3079 * jfm:xxxx send an null pointer to say no security desc
3080 * have to implement security before !
3081 ********************************************************************/
3083 static void spoolss_notify_security_desc(int snum
,
3084 SPOOL_NOTIFY_INFO_DATA
*data
,
3085 print_queue_struct
*queue
,
3086 NT_PRINTER_INFO_LEVEL
*printer
,
3087 TALLOC_CTX
*mem_ctx
)
3089 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->len
;
3090 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sec
) ;
3093 /*******************************************************************
3094 * fill a notify_info_data with the attributes
3095 * jfm:xxxx a samba printer is always shared
3096 ********************************************************************/
3098 void spoolss_notify_attributes(int snum
,
3099 SPOOL_NOTIFY_INFO_DATA
*data
,
3100 print_queue_struct
*queue
,
3101 NT_PRINTER_INFO_LEVEL
*printer
,
3102 TALLOC_CTX
*mem_ctx
)
3104 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
3105 data
->notify_data
.value
[1] = 0;
3108 /*******************************************************************
3109 * fill a notify_info_data with the priority
3110 ********************************************************************/
3112 static void spoolss_notify_priority(int snum
,
3113 SPOOL_NOTIFY_INFO_DATA
*data
,
3114 print_queue_struct
*queue
,
3115 NT_PRINTER_INFO_LEVEL
*printer
,
3116 TALLOC_CTX
*mem_ctx
)
3118 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
3119 data
->notify_data
.value
[1] = 0;
3122 /*******************************************************************
3123 * fill a notify_info_data with the default priority
3124 ********************************************************************/
3126 static void spoolss_notify_default_priority(int snum
,
3127 SPOOL_NOTIFY_INFO_DATA
*data
,
3128 print_queue_struct
*queue
,
3129 NT_PRINTER_INFO_LEVEL
*printer
,
3130 TALLOC_CTX
*mem_ctx
)
3132 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
3133 data
->notify_data
.value
[1] = 0;
3136 /*******************************************************************
3137 * fill a notify_info_data with the start time
3138 ********************************************************************/
3140 static void spoolss_notify_start_time(int snum
,
3141 SPOOL_NOTIFY_INFO_DATA
*data
,
3142 print_queue_struct
*queue
,
3143 NT_PRINTER_INFO_LEVEL
*printer
,
3144 TALLOC_CTX
*mem_ctx
)
3146 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
3147 data
->notify_data
.value
[1] = 0;
3150 /*******************************************************************
3151 * fill a notify_info_data with the until time
3152 ********************************************************************/
3154 static void spoolss_notify_until_time(int snum
,
3155 SPOOL_NOTIFY_INFO_DATA
*data
,
3156 print_queue_struct
*queue
,
3157 NT_PRINTER_INFO_LEVEL
*printer
,
3158 TALLOC_CTX
*mem_ctx
)
3160 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3161 data
->notify_data
.value
[1] = 0;
3164 /*******************************************************************
3165 * fill a notify_info_data with the status
3166 ********************************************************************/
3168 static void spoolss_notify_status(int snum
,
3169 SPOOL_NOTIFY_INFO_DATA
*data
,
3170 print_queue_struct
*queue
,
3171 NT_PRINTER_INFO_LEVEL
*printer
,
3172 TALLOC_CTX
*mem_ctx
)
3174 print_status_struct status
;
3176 print_queue_length(snum
, &status
);
3177 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3178 data
->notify_data
.value
[1] = 0;
3181 /*******************************************************************
3182 * fill a notify_info_data with the number of jobs queued
3183 ********************************************************************/
3185 void spoolss_notify_cjobs(int snum
,
3186 SPOOL_NOTIFY_INFO_DATA
*data
,
3187 print_queue_struct
*queue
,
3188 NT_PRINTER_INFO_LEVEL
*printer
,
3189 TALLOC_CTX
*mem_ctx
)
3191 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3192 data
->notify_data
.value
[1] = 0;
3195 /*******************************************************************
3196 * fill a notify_info_data with the average ppm
3197 ********************************************************************/
3199 static void spoolss_notify_average_ppm(int snum
,
3200 SPOOL_NOTIFY_INFO_DATA
*data
,
3201 print_queue_struct
*queue
,
3202 NT_PRINTER_INFO_LEVEL
*printer
,
3203 TALLOC_CTX
*mem_ctx
)
3205 /* always respond 8 pages per minutes */
3206 /* a little hard ! */
3207 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3208 data
->notify_data
.value
[1] = 0;
3211 /*******************************************************************
3212 * fill a notify_info_data with username
3213 ********************************************************************/
3215 static void spoolss_notify_username(int snum
,
3216 SPOOL_NOTIFY_INFO_DATA
*data
,
3217 print_queue_struct
*queue
,
3218 NT_PRINTER_INFO_LEVEL
*printer
,
3219 TALLOC_CTX
*mem_ctx
)
3224 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3226 data
->notify_data
.data
.length
= len
;
3228 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3230 if (!data
->notify_data
.data
.string
) {
3231 data
->notify_data
.data
.length
= 0;
3235 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3237 data
->notify_data
.data
.string
= NULL
;
3241 /*******************************************************************
3242 * fill a notify_info_data with job status
3243 ********************************************************************/
3245 static void spoolss_notify_job_status(int snum
,
3246 SPOOL_NOTIFY_INFO_DATA
*data
,
3247 print_queue_struct
*queue
,
3248 NT_PRINTER_INFO_LEVEL
*printer
,
3249 TALLOC_CTX
*mem_ctx
)
3251 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3252 data
->notify_data
.value
[1] = 0;
3255 /*******************************************************************
3256 * fill a notify_info_data with job name
3257 ********************************************************************/
3259 static void spoolss_notify_job_name(int snum
,
3260 SPOOL_NOTIFY_INFO_DATA
*data
,
3261 print_queue_struct
*queue
,
3262 NT_PRINTER_INFO_LEVEL
*printer
,
3263 TALLOC_CTX
*mem_ctx
)
3268 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3270 data
->notify_data
.data
.length
= len
;
3272 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3274 if (!data
->notify_data
.data
.string
) {
3275 data
->notify_data
.data
.length
= 0;
3279 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3281 data
->notify_data
.data
.string
= NULL
;
3285 /*******************************************************************
3286 * fill a notify_info_data with job status
3287 ********************************************************************/
3289 static void spoolss_notify_job_status_string(int snum
,
3290 SPOOL_NOTIFY_INFO_DATA
*data
,
3291 print_queue_struct
*queue
,
3292 NT_PRINTER_INFO_LEVEL
*printer
,
3293 TALLOC_CTX
*mem_ctx
)
3296 * Now we're returning job status codes we just return a "" here. JRA.
3303 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3306 switch (queue
->status
) {
3311 p
= ""; /* NT provides the paused string */
3320 #endif /* NO LONGER NEEDED. */
3322 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3324 data
->notify_data
.data
.length
= len
;
3326 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3328 if (!data
->notify_data
.data
.string
) {
3329 data
->notify_data
.data
.length
= 0;
3333 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3335 data
->notify_data
.data
.string
= NULL
;
3339 /*******************************************************************
3340 * fill a notify_info_data with job time
3341 ********************************************************************/
3343 static void spoolss_notify_job_time(int snum
,
3344 SPOOL_NOTIFY_INFO_DATA
*data
,
3345 print_queue_struct
*queue
,
3346 NT_PRINTER_INFO_LEVEL
*printer
,
3347 TALLOC_CTX
*mem_ctx
)
3349 data
->notify_data
.value
[0]=0x0;
3350 data
->notify_data
.value
[1]=0;
3353 /*******************************************************************
3354 * fill a notify_info_data with job size
3355 ********************************************************************/
3357 static void spoolss_notify_job_size(int snum
,
3358 SPOOL_NOTIFY_INFO_DATA
*data
,
3359 print_queue_struct
*queue
,
3360 NT_PRINTER_INFO_LEVEL
*printer
,
3361 TALLOC_CTX
*mem_ctx
)
3363 data
->notify_data
.value
[0]=queue
->size
;
3364 data
->notify_data
.value
[1]=0;
3367 /*******************************************************************
3368 * fill a notify_info_data with page info
3369 ********************************************************************/
3370 static void spoolss_notify_total_pages(int snum
,
3371 SPOOL_NOTIFY_INFO_DATA
*data
,
3372 print_queue_struct
*queue
,
3373 NT_PRINTER_INFO_LEVEL
*printer
,
3374 TALLOC_CTX
*mem_ctx
)
3376 data
->notify_data
.value
[0]=queue
->page_count
;
3377 data
->notify_data
.value
[1]=0;
3380 /*******************************************************************
3381 * fill a notify_info_data with pages printed info.
3382 ********************************************************************/
3383 static void spoolss_notify_pages_printed(int snum
,
3384 SPOOL_NOTIFY_INFO_DATA
*data
,
3385 print_queue_struct
*queue
,
3386 NT_PRINTER_INFO_LEVEL
*printer
,
3387 TALLOC_CTX
*mem_ctx
)
3389 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3390 data
->notify_data
.value
[1]=0;
3393 /*******************************************************************
3394 Fill a notify_info_data with job position.
3395 ********************************************************************/
3397 static void spoolss_notify_job_position(int snum
,
3398 SPOOL_NOTIFY_INFO_DATA
*data
,
3399 print_queue_struct
*queue
,
3400 NT_PRINTER_INFO_LEVEL
*printer
,
3401 TALLOC_CTX
*mem_ctx
)
3403 data
->notify_data
.value
[0]=queue
->job
;
3404 data
->notify_data
.value
[1]=0;
3407 /*******************************************************************
3408 Fill a notify_info_data with submitted time.
3409 ********************************************************************/
3411 static void spoolss_notify_submitted_time(int snum
,
3412 SPOOL_NOTIFY_INFO_DATA
*data
,
3413 print_queue_struct
*queue
,
3414 NT_PRINTER_INFO_LEVEL
*printer
,
3415 TALLOC_CTX
*mem_ctx
)
3422 t
=gmtime(&queue
->time
);
3424 len
= sizeof(SYSTEMTIME
);
3426 data
->notify_data
.data
.length
= len
;
3427 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3429 if (!data
->notify_data
.data
.string
) {
3430 data
->notify_data
.data
.length
= 0;
3434 make_systemtime(&st
, t
);
3437 * Systemtime must be linearized as a set of UINT16's.
3438 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3441 p
= (char *)data
->notify_data
.data
.string
;
3442 SSVAL(p
, 0, st
.year
);
3443 SSVAL(p
, 2, st
.month
);
3444 SSVAL(p
, 4, st
.dayofweek
);
3445 SSVAL(p
, 6, st
.day
);
3446 SSVAL(p
, 8, st
.hour
);
3447 SSVAL(p
, 10, st
.minute
);
3448 SSVAL(p
, 12, st
.second
);
3449 SSVAL(p
, 14, st
.milliseconds
);
3452 struct s_notify_info_data_table
3458 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3459 print_queue_struct
*queue
,
3460 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3463 /* A table describing the various print notification constants and
3464 whether the notification data is a pointer to a variable sized
3465 buffer, a one value uint32 or a two value uint32. */
3467 static const struct s_notify_info_data_table notify_info_data_table
[] =
3469 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3470 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3471 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3472 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3473 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3474 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3475 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3476 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3477 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3478 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3479 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3480 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3481 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3482 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3483 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3484 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3485 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3486 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3487 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3488 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3489 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3490 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3491 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3492 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3493 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3494 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3495 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3496 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3497 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3498 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3499 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3500 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3501 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3502 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3503 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3504 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3505 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3506 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3507 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3508 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3509 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3510 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3511 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3512 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3513 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3514 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3515 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3516 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3517 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3518 { PRINT_TABLE_END
, 0x0, NULL
, 0x0, NULL
},
3521 /*******************************************************************
3522 Return the size of info_data structure.
3523 ********************************************************************/
3525 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3529 for (i
= 0; i
< (sizeof(notify_info_data_table
)/sizeof(struct s_notify_info_data_table
)); i
++) {
3530 if ( (notify_info_data_table
[i
].type
== type
)
3531 && (notify_info_data_table
[i
].field
== field
) ) {
3532 switch(notify_info_data_table
[i
].size
) {
3533 case NOTIFY_ONE_VALUE
:
3534 case NOTIFY_TWO_VALUE
:
3539 /* The only pointer notify data I have seen on
3540 the wire is the submitted time and this has
3541 the notify size set to 4. -tpot */
3543 case NOTIFY_POINTER
:
3546 case NOTIFY_SECDESC
:
3552 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3557 /*******************************************************************
3558 Return the type of notify_info_data.
3559 ********************************************************************/
3561 static uint32
type_of_notify_info_data(uint16 type
, uint16 field
)
3565 for (i
= 0; i
< (sizeof(notify_info_data_table
)/sizeof(struct s_notify_info_data_table
)); i
++) {
3566 if (notify_info_data_table
[i
].type
== type
&&
3567 notify_info_data_table
[i
].field
== field
)
3568 return notify_info_data_table
[i
].size
;
3574 /****************************************************************************
3575 ****************************************************************************/
3577 static BOOL
search_notify(uint16 type
, uint16 field
, int *value
)
3581 for (i
= 0; notify_info_data_table
[i
].type
!= PRINT_TABLE_END
; i
++) {
3582 if (notify_info_data_table
[i
].type
== type
&&
3583 notify_info_data_table
[i
].field
== field
&&
3584 notify_info_data_table
[i
].fn
!= NULL
) {
3593 /****************************************************************************
3594 ****************************************************************************/
3596 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3598 info_data
->type
= type
;
3599 info_data
->field
= field
;
3600 info_data
->reserved
= 0;
3602 info_data
->size
= size_of_notify_info_data(type
, field
);
3603 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3608 /*******************************************************************
3610 * fill a notify_info struct with info asked
3612 ********************************************************************/
3614 static BOOL
construct_notify_printer_info(Printer_entry
*print_hnd
, SPOOL_NOTIFY_INFO
*info
, int
3615 snum
, SPOOL_NOTIFY_OPTION_TYPE
3616 *option_type
, uint32 id
,
3617 TALLOC_CTX
*mem_ctx
)
3623 SPOOL_NOTIFY_INFO_DATA
*current_data
;
3624 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3625 print_queue_struct
*queue
=NULL
;
3627 type
=option_type
->type
;
3629 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3630 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3631 option_type
->count
, lp_servicename(snum
)));
3633 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3636 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3637 field
= option_type
->fields
[field_num
];
3639 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3641 if (!search_notify(type
, field
, &j
) )
3644 if((info
->data
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3645 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3646 free_a_printer(&printer
, 2);
3650 current_data
= &info
->data
[info
->count
];
3652 construct_info_data(current_data
, type
, field
, id
);
3654 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3655 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3657 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3663 free_a_printer(&printer
, 2);
3667 /*******************************************************************
3669 * fill a notify_info struct with info asked
3671 ********************************************************************/
3673 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3674 SPOOL_NOTIFY_INFO
*info
,
3675 NT_PRINTER_INFO_LEVEL
*printer
,
3676 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3677 *option_type
, uint32 id
,
3678 TALLOC_CTX
*mem_ctx
)
3684 SPOOL_NOTIFY_INFO_DATA
*current_data
;
3686 DEBUG(4,("construct_notify_jobs_info\n"));
3688 type
= option_type
->type
;
3690 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3691 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3692 option_type
->count
));
3694 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3695 field
= option_type
->fields
[field_num
];
3697 if (!search_notify(type
, field
, &j
) )
3700 if((info
->data
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3701 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3705 current_data
=&(info
->data
[info
->count
]);
3707 construct_info_data(current_data
, type
, field
, id
);
3708 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3717 * JFM: The enumeration is not that simple, it's even non obvious.
3719 * let's take an example: I want to monitor the PRINTER SERVER for
3720 * the printer's name and the number of jobs currently queued.
3721 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3722 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3724 * I have 3 printers on the back of my server.
3726 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3729 * 1 printer 1 name 1
3730 * 2 printer 1 cjob 1
3731 * 3 printer 2 name 2
3732 * 4 printer 2 cjob 2
3733 * 5 printer 3 name 3
3734 * 6 printer 3 name 3
3736 * that's the print server case, the printer case is even worse.
3739 /*******************************************************************
3741 * enumerate all printers on the printserver
3742 * fill a notify_info struct with info asked
3744 ********************************************************************/
3746 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3747 SPOOL_NOTIFY_INFO
*info
,
3748 TALLOC_CTX
*mem_ctx
)
3751 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3752 int n_services
=lp_numservices();
3754 SPOOL_NOTIFY_OPTION
*option
;
3755 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3757 DEBUG(4,("printserver_notify_info\n"));
3762 option
=Printer
->notify
.option
;
3767 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3768 sending a ffpcn() request first */
3773 for (i
=0; i
<option
->count
; i
++) {
3774 option_type
=&(option
->ctr
.type
[i
]);
3776 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3779 for (snum
=0; snum
<n_services
; snum
++)
3781 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3782 construct_notify_printer_info ( Printer
, info
, snum
, option_type
, snum
, mem_ctx
);
3788 * Debugging information, don't delete.
3791 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3792 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3793 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3795 for (i
=0; i
<info
->count
; i
++) {
3796 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3797 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3798 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3805 /*******************************************************************
3807 * fill a notify_info struct with info asked
3809 ********************************************************************/
3811 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3812 TALLOC_CTX
*mem_ctx
)
3815 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3818 SPOOL_NOTIFY_OPTION
*option
;
3819 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3821 print_queue_struct
*queue
=NULL
;
3822 print_status_struct status
;
3824 DEBUG(4,("printer_notify_info\n"));
3829 option
=Printer
->notify
.option
;
3835 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3836 sending a ffpcn() request first */
3841 get_printer_snum(p
, hnd
, &snum
);
3843 for (i
=0; i
<option
->count
; i
++) {
3844 option_type
=&option
->ctr
.type
[i
];
3846 switch ( option_type
->type
) {
3847 case PRINTER_NOTIFY_TYPE
:
3848 if(construct_notify_printer_info(Printer
, info
, snum
,
3854 case JOB_NOTIFY_TYPE
: {
3855 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3857 count
= print_queue_status(snum
, &queue
, &status
);
3859 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3862 for (j
=0; j
<count
; j
++) {
3863 construct_notify_jobs_info(&queue
[j
], info
,
3870 free_a_printer(&printer
, 2);
3880 * Debugging information, don't delete.
3883 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3884 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3885 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3887 for (i=0; i<info->count; i++) {
3888 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3889 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3890 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3896 /********************************************************************
3898 ********************************************************************/
3900 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3902 POLICY_HND
*handle
= &q_u
->handle
;
3903 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3905 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3906 WERROR result
= WERR_BADFID
;
3908 /* we always have a NOTIFY_INFO struct */
3912 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3913 OUR_HANDLE(handle
)));
3917 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3920 * We are now using the change value, and
3921 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3922 * I don't have a global notification system, I'm sending back all the
3923 * informations even when _NOTHING_ has changed.
3926 /* We need to keep track of the change value to send back in
3927 RRPCN replies otherwise our updates are ignored. */
3929 Printer
->notify
.fnpcn
= True
;
3931 if (Printer
->notify
.client_connected
) {
3932 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3933 Printer
->notify
.change
= q_u
->change
;
3936 /* just ignore the SPOOL_NOTIFY_OPTION */
3938 switch (Printer
->printer_type
) {
3940 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3943 case SPLHND_PRINTER
:
3944 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3948 Printer
->notify
.fnpcn
= False
;
3954 /********************************************************************
3955 * construct_printer_info_0
3956 * fill a printer_info_0 struct
3957 ********************************************************************/
3959 static BOOL
construct_printer_info_0(Printer_entry
*print_hnd
, PRINTER_INFO_0
*printer
, int snum
)
3963 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3964 counter_printer_0
*session_counter
;
3965 uint32 global_counter
;
3968 print_status_struct status
;
3970 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
3973 count
= print_queue_length(snum
, &status
);
3975 /* check if we already have a counter for this printer */
3976 for(session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3977 if (session_counter
->snum
== snum
)
3981 /* it's the first time, add it to the list */
3982 if (session_counter
==NULL
) {
3983 if((session_counter
=SMB_MALLOC_P(counter_printer_0
)) == NULL
) {
3984 free_a_printer(&ntprinter
, 2);
3987 ZERO_STRUCTP(session_counter
);
3988 session_counter
->snum
=snum
;
3989 session_counter
->counter
=0;
3990 DLIST_ADD(counter_list
, session_counter
);
3994 session_counter
->counter
++;
3997 * the global_counter should be stored in a TDB as it's common to all the clients
3998 * and should be zeroed on samba startup
4000 global_counter
=session_counter
->counter
;
4002 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
4004 init_unistr(&printer
->printername
, chaine
);
4006 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_server_name(print_hnd
));
4007 init_unistr(&printer
->servername
, chaine
);
4009 printer
->cjobs
= count
;
4010 printer
->total_jobs
= 0;
4011 printer
->total_bytes
= 0;
4013 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
4014 t
=gmtime(&setuptime
);
4016 printer
->year
= t
->tm_year
+1900;
4017 printer
->month
= t
->tm_mon
+1;
4018 printer
->dayofweek
= t
->tm_wday
;
4019 printer
->day
= t
->tm_mday
;
4020 printer
->hour
= t
->tm_hour
;
4021 printer
->minute
= t
->tm_min
;
4022 printer
->second
= t
->tm_sec
;
4023 printer
->milliseconds
= 0;
4025 printer
->global_counter
= global_counter
;
4026 printer
->total_pages
= 0;
4028 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4029 printer
->major_version
= 0x0005; /* NT 5 */
4030 printer
->build_version
= 0x0893; /* build 2195 */
4032 printer
->unknown7
= 0x1;
4033 printer
->unknown8
= 0x0;
4034 printer
->unknown9
= 0x0;
4035 printer
->session_counter
= session_counter
->counter
;
4036 printer
->unknown11
= 0x0;
4037 printer
->printer_errors
= 0x0; /* number of print failure */
4038 printer
->unknown13
= 0x0;
4039 printer
->unknown14
= 0x1;
4040 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
4041 printer
->unknown16
= 0x0;
4042 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
4043 printer
->unknown18
= 0x0;
4044 printer
->status
= nt_printq_status(status
.status
);
4045 printer
->unknown20
= 0x0;
4046 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4047 printer
->unknown22
= 0x0;
4048 printer
->unknown23
= 0x6; /* 6 ???*/
4049 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
4050 printer
->unknown25
= 0;
4051 printer
->unknown26
= 0;
4052 printer
->unknown27
= 0;
4053 printer
->unknown28
= 0;
4054 printer
->unknown29
= 0;
4056 free_a_printer(&ntprinter
,2);
4060 /********************************************************************
4061 * construct_printer_info_1
4062 * fill a printer_info_1 struct
4063 ********************************************************************/
4064 static BOOL
construct_printer_info_1(Printer_entry
*print_hnd
, uint32 flags
, PRINTER_INFO_1
*printer
, int snum
)
4068 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4070 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4073 printer
->flags
=flags
;
4075 if (*ntprinter
->info_2
->comment
== '\0') {
4076 init_unistr(&printer
->comment
, lp_comment(snum
));
4077 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4078 ntprinter
->info_2
->drivername
, lp_comment(snum
));
4081 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4082 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4083 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
4086 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
4088 init_unistr(&printer
->description
, chaine
);
4089 init_unistr(&printer
->name
, chaine2
);
4091 free_a_printer(&ntprinter
,2);
4096 /****************************************************************************
4097 Free a DEVMODE struct.
4098 ****************************************************************************/
4100 static void free_dev_mode(DEVICEMODE
*dev
)
4105 SAFE_FREE(dev
->dev_private
);
4110 /****************************************************************************
4111 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4112 should be valid upon entry
4113 ****************************************************************************/
4115 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
4117 if ( !devmode
|| !ntdevmode
)
4120 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
4122 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
4124 devmode
->specversion
= ntdevmode
->specversion
;
4125 devmode
->driverversion
= ntdevmode
->driverversion
;
4126 devmode
->size
= ntdevmode
->size
;
4127 devmode
->driverextra
= ntdevmode
->driverextra
;
4128 devmode
->fields
= ntdevmode
->fields
;
4130 devmode
->orientation
= ntdevmode
->orientation
;
4131 devmode
->papersize
= ntdevmode
->papersize
;
4132 devmode
->paperlength
= ntdevmode
->paperlength
;
4133 devmode
->paperwidth
= ntdevmode
->paperwidth
;
4134 devmode
->scale
= ntdevmode
->scale
;
4135 devmode
->copies
= ntdevmode
->copies
;
4136 devmode
->defaultsource
= ntdevmode
->defaultsource
;
4137 devmode
->printquality
= ntdevmode
->printquality
;
4138 devmode
->color
= ntdevmode
->color
;
4139 devmode
->duplex
= ntdevmode
->duplex
;
4140 devmode
->yresolution
= ntdevmode
->yresolution
;
4141 devmode
->ttoption
= ntdevmode
->ttoption
;
4142 devmode
->collate
= ntdevmode
->collate
;
4143 devmode
->icmmethod
= ntdevmode
->icmmethod
;
4144 devmode
->icmintent
= ntdevmode
->icmintent
;
4145 devmode
->mediatype
= ntdevmode
->mediatype
;
4146 devmode
->dithertype
= ntdevmode
->dithertype
;
4148 if (ntdevmode
->nt_dev_private
!= NULL
) {
4149 if ((devmode
->dev_private
=(uint8
*)memdup(ntdevmode
->nt_dev_private
, ntdevmode
->driverextra
)) == NULL
)
4156 /****************************************************************************
4157 Create a DEVMODE struct. Returns malloced memory.
4158 ****************************************************************************/
4160 DEVICEMODE
*construct_dev_mode(const char *servicename
)
4162 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4163 DEVICEMODE
*devmode
= NULL
;
4165 DEBUG(7,("construct_dev_mode\n"));
4167 DEBUGADD(8,("getting printer characteristics\n"));
4169 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
4172 if ( !printer
->info_2
->devmode
) {
4173 DEBUG(5, ("BONG! There was no device mode!\n"));
4177 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) == NULL
) {
4178 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4182 ZERO_STRUCTP(devmode
);
4184 DEBUGADD(8,("loading DEVICEMODE\n"));
4186 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4187 free_dev_mode( devmode
);
4192 free_a_printer(&printer
,2);
4197 /********************************************************************
4198 * construct_printer_info_2
4199 * fill a printer_info_2 struct
4200 ********************************************************************/
4202 static BOOL
construct_printer_info_2(Printer_entry
*print_hnd
, PRINTER_INFO_2
*printer
, int snum
)
4205 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4207 print_status_struct status
;
4209 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4212 count
= print_queue_length(snum
, &status
);
4214 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4215 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4216 init_unistr(&printer
->sharename
, lp_servicename(snum
)); /* sharename */
4217 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4218 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4220 if (*ntprinter
->info_2
->comment
== '\0')
4221 init_unistr(&printer
->comment
, lp_comment(snum
)); /* comment */
4223 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4225 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4226 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4227 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4228 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4229 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4231 printer
->attributes
= ntprinter
->info_2
->attributes
;
4233 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4234 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4235 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4236 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4237 printer
->status
= nt_printq_status(status
.status
); /* status */
4238 printer
->cjobs
= count
; /* jobs */
4239 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4241 if ( !(printer
->devmode
= construct_dev_mode(
4242 lp_const_servicename(snum
))) )
4243 DEBUG(8, ("Returning NULL Devicemode!\n"));
4245 printer
->secdesc
= NULL
;
4247 if ( ntprinter
->info_2
->secdesc_buf
4248 && ntprinter
->info_2
->secdesc_buf
->len
!= 0 )
4250 /* don't use talloc_steal() here unless you do a deep steal of all
4251 the SEC_DESC members */
4253 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4254 ntprinter
->info_2
->secdesc_buf
->sec
);
4257 free_a_printer(&ntprinter
, 2);
4262 /********************************************************************
4263 * construct_printer_info_3
4264 * fill a printer_info_3 struct
4265 ********************************************************************/
4267 static BOOL
construct_printer_info_3(Printer_entry
*print_hnd
, PRINTER_INFO_3
**pp_printer
, int snum
)
4269 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4270 PRINTER_INFO_3
*printer
= NULL
;
4272 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4276 if ((printer
= SMB_MALLOC_P(PRINTER_INFO_3
)) == NULL
) {
4277 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4278 free_a_printer(&ntprinter
, 2);
4282 ZERO_STRUCTP(printer
);
4284 /* These are the components of the SD we are returning. */
4286 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->len
!= 0) {
4287 /* don't use talloc_steal() here unless you do a deep steal of all
4288 the SEC_DESC members */
4290 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4291 ntprinter
->info_2
->secdesc_buf
->sec
);
4294 free_a_printer(&ntprinter
, 2);
4296 *pp_printer
= printer
;
4300 /********************************************************************
4301 * construct_printer_info_4
4302 * fill a printer_info_4 struct
4303 ********************************************************************/
4305 static BOOL
construct_printer_info_4(Printer_entry
*print_hnd
, PRINTER_INFO_4
*printer
, int snum
)
4307 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4309 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4312 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4313 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4314 printer
->attributes
= ntprinter
->info_2
->attributes
;
4316 free_a_printer(&ntprinter
, 2);
4320 /********************************************************************
4321 * construct_printer_info_5
4322 * fill a printer_info_5 struct
4323 ********************************************************************/
4325 static BOOL
construct_printer_info_5(Printer_entry
*print_hnd
, PRINTER_INFO_5
*printer
, int snum
)
4327 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4329 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2, lp_const_servicename(snum
))))
4332 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4333 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4334 printer
->attributes
= ntprinter
->info_2
->attributes
;
4336 /* these two are not used by NT+ according to MSDN */
4338 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4339 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4341 free_a_printer(&ntprinter
, 2);
4346 /********************************************************************
4347 * construct_printer_info_7
4348 * fill a printer_info_7 struct
4349 ********************************************************************/
4351 static BOOL
construct_printer_info_7(Printer_entry
*print_hnd
, PRINTER_INFO_7
*printer
, int snum
)
4353 char *guid_str
= NULL
;
4356 if (is_printer_published(print_hnd
, snum
, &guid
)) {
4357 asprintf(&guid_str
, "{%s}", smb_uuid_string_static(guid
));
4358 strupper_m(guid_str
);
4359 init_unistr(&printer
->guid
, guid_str
);
4360 printer
->action
= SPOOL_DS_PUBLISH
;
4362 init_unistr(&printer
->guid
, "");
4363 printer
->action
= SPOOL_DS_UNPUBLISH
;
4369 /********************************************************************
4370 Spoolss_enumprinters.
4371 ********************************************************************/
4373 static WERROR
enum_all_printers_info_1(uint32 flags
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4377 int n_services
=lp_numservices();
4378 PRINTER_INFO_1
*printers
=NULL
;
4379 PRINTER_INFO_1 current_prt
;
4380 WERROR result
= WERR_OK
;
4382 DEBUG(4,("enum_all_printers_info_1\n"));
4384 for (snum
=0; snum
<n_services
; snum
++) {
4385 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4386 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4388 if (construct_printer_info_1(NULL
, flags
, ¤t_prt
, snum
)) {
4389 if((printers
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_1
, *returned
+1)) == NULL
) {
4390 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4394 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4396 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4402 /* check the required size. */
4403 for (i
=0; i
<*returned
; i
++)
4404 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4406 if (*needed
> offered
) {
4407 result
= WERR_INSUFFICIENT_BUFFER
;
4411 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4412 result
= WERR_NOMEM
;
4416 /* fill the buffer with the structures */
4417 for (i
=0; i
<*returned
; i
++)
4418 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4423 SAFE_FREE(printers
);
4425 if ( !W_ERROR_IS_OK(result
) )
4431 /********************************************************************
4432 enum_all_printers_info_1_local.
4433 *********************************************************************/
4435 static WERROR
enum_all_printers_info_1_local(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4437 DEBUG(4,("enum_all_printers_info_1_local\n"));
4439 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4442 /********************************************************************
4443 enum_all_printers_info_1_name.
4444 *********************************************************************/
4446 static WERROR
enum_all_printers_info_1_name(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4450 DEBUG(4,("enum_all_printers_info_1_name\n"));
4452 if ((name
[0] == '\\') && (name
[1] == '\\'))
4455 if (is_myname_or_ipaddr(s
)) {
4456 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4459 return WERR_INVALID_NAME
;
4462 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4463 /********************************************************************
4464 enum_all_printers_info_1_remote.
4465 *********************************************************************/
4467 static WERROR
enum_all_printers_info_1_remote(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4469 PRINTER_INFO_1
*printer
;
4470 fstring printername
;
4473 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4474 WERROR result
= WERR_OK
;
4476 /* JFM: currently it's more a place holder than anything else.
4477 * In the spooler world there is a notion of server registration.
4478 * the print servers are registered on the PDC (in the same domain)
4480 * We should have a TDB here. The registration is done thru an
4481 * undocumented RPC call.
4484 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4489 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", name
);
4490 slprintf(desc
, sizeof(desc
)-1,"%s", name
);
4491 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4493 init_unistr(&printer
->description
, desc
);
4494 init_unistr(&printer
->name
, printername
);
4495 init_unistr(&printer
->comment
, comment
);
4496 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4498 /* check the required size. */
4499 *needed
+= spoolss_size_printer_info_1(printer
);
4501 if (*needed
> offered
) {
4502 result
= WERR_INSUFFICIENT_BUFFER
;
4506 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4507 result
= WERR_NOMEM
;
4511 /* fill the buffer with the structures */
4512 smb_io_printer_info_1("", buffer
, printer
, 0);
4518 if ( !W_ERROR_IS_OK(result
) )
4526 /********************************************************************
4527 enum_all_printers_info_1_network.
4528 *********************************************************************/
4530 static WERROR
enum_all_printers_info_1_network(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4534 DEBUG(4,("enum_all_printers_info_1_network\n"));
4536 /* If we respond to a enum_printers level 1 on our name with flags
4537 set to PRINTER_ENUM_REMOTE with a list of printers then these
4538 printers incorrectly appear in the APW browse list.
4539 Specifically the printers for the server appear at the workgroup
4540 level where all the other servers in the domain are
4541 listed. Windows responds to this call with a
4542 WERR_CAN_NOT_COMPLETE so we should do the same. */
4544 if (name
[0] == '\\' && name
[1] == '\\')
4547 if (is_myname_or_ipaddr(s
))
4548 return WERR_CAN_NOT_COMPLETE
;
4550 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4553 /********************************************************************
4554 * api_spoolss_enumprinters
4556 * called from api_spoolss_enumprinters (see this to understand)
4557 ********************************************************************/
4559 static WERROR
enum_all_printers_info_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4563 int n_services
=lp_numservices();
4564 PRINTER_INFO_2
*printers
=NULL
;
4565 PRINTER_INFO_2 current_prt
;
4566 WERROR result
= WERR_OK
;
4570 for (snum
=0; snum
<n_services
; snum
++) {
4571 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4572 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4574 if (construct_printer_info_2(NULL
, ¤t_prt
, snum
)) {
4575 if ( !(printers
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_2
, *returned
+1)) ) {
4576 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4581 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
+ 1));
4583 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4590 /* check the required size. */
4591 for (i
=0; i
<*returned
; i
++)
4592 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4594 if (*needed
> offered
) {
4595 result
= WERR_INSUFFICIENT_BUFFER
;
4599 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4600 result
= WERR_NOMEM
;
4604 /* fill the buffer with the structures */
4605 for (i
=0; i
<*returned
; i
++)
4606 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4611 for (i
=0; i
<*returned
; i
++)
4612 free_devmode(printers
[i
].devmode
);
4614 SAFE_FREE(printers
);
4616 if ( !W_ERROR_IS_OK(result
) )
4622 /********************************************************************
4623 * handle enumeration of printers at level 1
4624 ********************************************************************/
4626 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4627 RPC_BUFFER
*buffer
, uint32 offered
,
4628 uint32
*needed
, uint32
*returned
)
4630 /* Not all the flags are equals */
4632 if (flags
& PRINTER_ENUM_LOCAL
)
4633 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4635 if (flags
& PRINTER_ENUM_NAME
)
4636 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4638 #if 0 /* JERRY - disabled for now */
4639 if (flags
& PRINTER_ENUM_REMOTE
)
4640 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4643 if (flags
& PRINTER_ENUM_NETWORK
)
4644 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4646 return WERR_OK
; /* NT4sp5 does that */
4649 /********************************************************************
4650 * handle enumeration of printers at level 2
4651 ********************************************************************/
4653 static WERROR
enumprinters_level2( uint32 flags
, const char *servername
,
4654 RPC_BUFFER
*buffer
, uint32 offered
,
4655 uint32
*needed
, uint32
*returned
)
4657 if (flags
& PRINTER_ENUM_LOCAL
) {
4658 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4661 if (flags
& PRINTER_ENUM_NAME
) {
4662 if (is_myname_or_ipaddr(canon_servername(servername
)))
4663 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4665 return WERR_INVALID_NAME
;
4668 if (flags
& PRINTER_ENUM_REMOTE
)
4669 return WERR_UNKNOWN_LEVEL
;
4674 /********************************************************************
4675 * handle enumeration of printers at level 5
4676 ********************************************************************/
4678 static WERROR
enumprinters_level5( uint32 flags
, const char *servername
,
4679 RPC_BUFFER
*buffer
, uint32 offered
,
4680 uint32
*needed
, uint32
*returned
)
4682 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4686 /********************************************************************
4687 * api_spoolss_enumprinters
4689 * called from api_spoolss_enumprinters (see this to understand)
4690 ********************************************************************/
4692 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4694 uint32 flags
= q_u
->flags
;
4695 UNISTR2
*servername
= &q_u
->servername
;
4696 uint32 level
= q_u
->level
;
4697 RPC_BUFFER
*buffer
= NULL
;
4698 uint32 offered
= q_u
->offered
;
4699 uint32
*needed
= &r_u
->needed
;
4700 uint32
*returned
= &r_u
->returned
;
4704 /* that's an [in out] buffer */
4706 if (!q_u
->buffer
&& (offered
!=0)) {
4707 return WERR_INVALID_PARAM
;
4710 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
4711 buffer
= r_u
->buffer
;
4713 DEBUG(4,("_spoolss_enumprinters\n"));
4720 * flags==PRINTER_ENUM_NAME
4721 * if name=="" then enumerates all printers
4722 * if name!="" then enumerate the printer
4723 * flags==PRINTER_ENUM_REMOTE
4724 * name is NULL, enumerate printers
4725 * Level 2: name!="" enumerates printers, name can't be NULL
4726 * Level 3: doesn't exist
4727 * Level 4: does a local registry lookup
4728 * Level 5: same as Level 2
4731 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4736 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4738 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4740 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4745 return WERR_UNKNOWN_LEVEL
;
4748 /****************************************************************************
4749 ****************************************************************************/
4751 static WERROR
getprinter_level_0(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4753 PRINTER_INFO_0
*printer
=NULL
;
4754 WERROR result
= WERR_OK
;
4756 if((printer
=SMB_MALLOC_P(PRINTER_INFO_0
)) == NULL
)
4759 construct_printer_info_0(print_hnd
, printer
, snum
);
4761 /* check the required size. */
4762 *needed
+= spoolss_size_printer_info_0(printer
);
4764 if (*needed
> offered
) {
4765 result
= WERR_INSUFFICIENT_BUFFER
;
4769 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4770 result
= WERR_NOMEM
;
4774 /* fill the buffer with the structures */
4775 smb_io_printer_info_0("", buffer
, printer
, 0);
4785 /****************************************************************************
4786 ****************************************************************************/
4788 static WERROR
getprinter_level_1(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4790 PRINTER_INFO_1
*printer
=NULL
;
4791 WERROR result
= WERR_OK
;
4793 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4796 construct_printer_info_1(print_hnd
, PRINTER_ENUM_ICON8
, printer
, snum
);
4798 /* check the required size. */
4799 *needed
+= spoolss_size_printer_info_1(printer
);
4801 if (*needed
> offered
) {
4802 result
= WERR_INSUFFICIENT_BUFFER
;
4806 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4807 result
= WERR_NOMEM
;
4811 /* fill the buffer with the structures */
4812 smb_io_printer_info_1("", buffer
, printer
, 0);
4821 /****************************************************************************
4822 ****************************************************************************/
4824 static WERROR
getprinter_level_2(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4826 PRINTER_INFO_2
*printer
=NULL
;
4827 WERROR result
= WERR_OK
;
4829 if((printer
=SMB_MALLOC_P(PRINTER_INFO_2
))==NULL
)
4832 construct_printer_info_2(print_hnd
, printer
, snum
);
4834 /* check the required size. */
4835 *needed
+= spoolss_size_printer_info_2(printer
);
4837 if (*needed
> offered
) {
4838 result
= WERR_INSUFFICIENT_BUFFER
;
4842 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4843 result
= WERR_NOMEM
;
4847 /* fill the buffer with the structures */
4848 if (!smb_io_printer_info_2("", buffer
, printer
, 0))
4849 result
= WERR_NOMEM
;
4853 free_printer_info_2(printer
);
4858 /****************************************************************************
4859 ****************************************************************************/
4861 static WERROR
getprinter_level_3(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4863 PRINTER_INFO_3
*printer
=NULL
;
4864 WERROR result
= WERR_OK
;
4866 if (!construct_printer_info_3(print_hnd
, &printer
, snum
))
4869 /* check the required size. */
4870 *needed
+= spoolss_size_printer_info_3(printer
);
4872 if (*needed
> offered
) {
4873 result
= WERR_INSUFFICIENT_BUFFER
;
4877 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4878 result
= WERR_NOMEM
;
4882 /* fill the buffer with the structures */
4883 smb_io_printer_info_3("", buffer
, printer
, 0);
4887 free_printer_info_3(printer
);
4892 /****************************************************************************
4893 ****************************************************************************/
4895 static WERROR
getprinter_level_4(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4897 PRINTER_INFO_4
*printer
=NULL
;
4898 WERROR result
= WERR_OK
;
4900 if((printer
=SMB_MALLOC_P(PRINTER_INFO_4
))==NULL
)
4903 if (!construct_printer_info_4(print_hnd
, printer
, snum
)) {
4908 /* check the required size. */
4909 *needed
+= spoolss_size_printer_info_4(printer
);
4911 if (*needed
> offered
) {
4912 result
= WERR_INSUFFICIENT_BUFFER
;
4916 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4917 result
= WERR_NOMEM
;
4921 /* fill the buffer with the structures */
4922 smb_io_printer_info_4("", buffer
, printer
, 0);
4926 free_printer_info_4(printer
);
4931 /****************************************************************************
4932 ****************************************************************************/
4934 static WERROR
getprinter_level_5(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4936 PRINTER_INFO_5
*printer
=NULL
;
4937 WERROR result
= WERR_OK
;
4939 if((printer
=SMB_MALLOC_P(PRINTER_INFO_5
))==NULL
)
4942 if (!construct_printer_info_5(print_hnd
, printer
, snum
)) {
4943 free_printer_info_5(printer
);
4947 /* check the required size. */
4948 *needed
+= spoolss_size_printer_info_5(printer
);
4950 if (*needed
> offered
) {
4951 result
= WERR_INSUFFICIENT_BUFFER
;
4955 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4956 result
= WERR_NOMEM
;
4960 /* fill the buffer with the structures */
4961 smb_io_printer_info_5("", buffer
, printer
, 0);
4965 free_printer_info_5(printer
);
4970 static WERROR
getprinter_level_7(Printer_entry
*print_hnd
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
4972 PRINTER_INFO_7
*printer
=NULL
;
4973 WERROR result
= WERR_OK
;
4975 if((printer
=SMB_MALLOC_P(PRINTER_INFO_7
))==NULL
)
4978 if (!construct_printer_info_7(print_hnd
, printer
, snum
))
4981 /* check the required size. */
4982 *needed
+= spoolss_size_printer_info_7(printer
);
4984 if (*needed
> offered
) {
4985 result
= WERR_INSUFFICIENT_BUFFER
;
4989 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4990 result
= WERR_NOMEM
;
4995 /* fill the buffer with the structures */
4996 smb_io_printer_info_7("", buffer
, printer
, 0);
5000 free_printer_info_7(printer
);
5005 /****************************************************************************
5006 ****************************************************************************/
5008 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
5010 POLICY_HND
*handle
= &q_u
->handle
;
5011 uint32 level
= q_u
->level
;
5012 RPC_BUFFER
*buffer
= NULL
;
5013 uint32 offered
= q_u
->offered
;
5014 uint32
*needed
= &r_u
->needed
;
5015 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
5019 /* that's an [in out] buffer */
5021 if (!q_u
->buffer
&& (offered
!=0)) {
5022 return WERR_INVALID_PARAM
;
5025 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5026 buffer
= r_u
->buffer
;
5030 if (!get_printer_snum(p
, handle
, &snum
))
5035 return getprinter_level_0(Printer
, snum
, buffer
, offered
, needed
);
5037 return getprinter_level_1(Printer
, snum
, buffer
, offered
, needed
);
5039 return getprinter_level_2(Printer
, snum
, buffer
, offered
, needed
);
5041 return getprinter_level_3(Printer
, snum
, buffer
, offered
, needed
);
5043 return getprinter_level_4(Printer
, snum
, buffer
, offered
, needed
);
5045 return getprinter_level_5(Printer
, snum
, buffer
, offered
, needed
);
5047 return getprinter_level_7(Printer
, snum
, buffer
, offered
, needed
);
5049 return WERR_UNKNOWN_LEVEL
;
5052 /********************************************************************
5053 * fill a DRIVER_INFO_1 struct
5054 ********************************************************************/
5056 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, const char *servername
, fstring architecture
)
5058 init_unistr( &info
->name
, driver
.info_3
->name
);
5061 /********************************************************************
5062 * construct_printer_driver_info_1
5063 ********************************************************************/
5065 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, const char *servername
, fstring architecture
, uint32 version
)
5067 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5068 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5070 ZERO_STRUCT(driver
);
5072 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5073 return WERR_INVALID_PRINTER_NAME
;
5075 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5076 free_a_printer(&printer
, 2);
5077 return WERR_UNKNOWN_PRINTER_DRIVER
;
5080 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
5082 free_a_printer(&printer
,2);
5087 /********************************************************************
5088 * construct_printer_driver_info_2
5089 * fill a printer_info_2 struct
5090 ********************************************************************/
5092 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, const char *servername
)
5095 const char *cservername
= canon_servername(servername
);
5097 info
->version
=driver
.info_3
->cversion
;
5099 init_unistr( &info
->name
, driver
.info_3
->name
);
5100 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5103 if (strlen(driver
.info_3
->driverpath
)) {
5104 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->driverpath
);
5105 init_unistr( &info
->driverpath
, temp
);
5107 init_unistr( &info
->driverpath
, "" );
5109 if (strlen(driver
.info_3
->datafile
)) {
5110 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->datafile
);
5111 init_unistr( &info
->datafile
, temp
);
5113 init_unistr( &info
->datafile
, "" );
5115 if (strlen(driver
.info_3
->configfile
)) {
5116 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->configfile
);
5117 init_unistr( &info
->configfile
, temp
);
5119 init_unistr( &info
->configfile
, "" );
5122 /********************************************************************
5123 * construct_printer_driver_info_2
5124 * fill a printer_info_2 struct
5125 ********************************************************************/
5127 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, const char *servername
, fstring architecture
, uint32 version
)
5129 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5130 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5132 ZERO_STRUCT(printer
);
5133 ZERO_STRUCT(driver
);
5135 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5136 return WERR_INVALID_PRINTER_NAME
;
5138 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5139 free_a_printer(&printer
, 2);
5140 return WERR_UNKNOWN_PRINTER_DRIVER
;
5143 fill_printer_driver_info_2(info
, driver
, servername
);
5145 free_a_printer(&printer
,2);
5150 /********************************************************************
5151 * copy a strings array and convert to UNICODE
5153 * convert an array of ascii string to a UNICODE string
5154 ********************************************************************/
5156 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
5163 DEBUG(6,("init_unistr_array\n"));
5174 v
= ""; /* hack to handle null lists */
5177 /* hack to allow this to be used in places other than when generating
5178 the list of dependent files */
5181 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", canon_servername(servername
), v
);
5185 DEBUGADD(6,("%d:%s:%lu\n", i
, line
, (unsigned long)strlen(line
)));
5187 /* add one extra unit16 for the second terminating NULL */
5189 if ( (*uni_array
=SMB_REALLOC_ARRAY(*uni_array
, uint16
, j
+1+strlen(line
)+2)) == NULL
) {
5190 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5197 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
5202 /* special case for ""; we need to add both NULL's here */
5204 (*uni_array
)[j
++]=0x0000;
5205 (*uni_array
)[j
]=0x0000;
5208 DEBUGADD(6,("last one:done\n"));
5210 /* return size of array in uint16's */
5215 /********************************************************************
5216 * construct_printer_info_3
5217 * fill a printer_info_3 struct
5218 ********************************************************************/
5220 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, const char *servername
)
5223 const char *cservername
= canon_servername(servername
);
5227 info
->version
=driver
.info_3
->cversion
;
5229 init_unistr( &info
->name
, driver
.info_3
->name
);
5230 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5232 if (strlen(driver
.info_3
->driverpath
)) {
5233 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->driverpath
);
5234 init_unistr( &info
->driverpath
, temp
);
5236 init_unistr( &info
->driverpath
, "" );
5238 if (strlen(driver
.info_3
->datafile
)) {
5239 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->datafile
);
5240 init_unistr( &info
->datafile
, temp
);
5242 init_unistr( &info
->datafile
, "" );
5244 if (strlen(driver
.info_3
->configfile
)) {
5245 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->configfile
);
5246 init_unistr( &info
->configfile
, temp
);
5248 init_unistr( &info
->configfile
, "" );
5250 if (strlen(driver
.info_3
->helpfile
)) {
5251 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->helpfile
);
5252 init_unistr( &info
->helpfile
, temp
);
5254 init_unistr( &info
->helpfile
, "" );
5256 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5257 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5259 info
->dependentfiles
=NULL
;
5260 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, cservername
);
5263 /********************************************************************
5264 * construct_printer_info_3
5265 * fill a printer_info_3 struct
5266 ********************************************************************/
5268 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, const char *servername
, fstring architecture
, uint32 version
)
5270 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5271 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5273 ZERO_STRUCT(driver
);
5275 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5276 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5277 if (!W_ERROR_IS_OK(status
))
5278 return WERR_INVALID_PRINTER_NAME
;
5280 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5281 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5286 * I put this code in during testing. Helpful when commenting out the
5287 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5288 * as win2k always queries the driver using an infor level of 6.
5289 * I've left it in (but ifdef'd out) because I'll probably
5290 * use it in experimentation again in the future. --jerry 22/01/2002
5293 if (!W_ERROR_IS_OK(status
)) {
5295 * Is this a W2k client ?
5298 /* Yes - try again with a WinNT driver. */
5300 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5301 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5305 if (!W_ERROR_IS_OK(status
)) {
5306 free_a_printer(&printer
,2);
5307 return WERR_UNKNOWN_PRINTER_DRIVER
;
5315 fill_printer_driver_info_3(info
, driver
, servername
);
5317 free_a_printer(&printer
,2);
5322 /********************************************************************
5323 * construct_printer_info_6
5324 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5325 ********************************************************************/
5327 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, const char *servername
)
5331 const char *cservername
= canon_servername(servername
);
5334 memset(&nullstr
, '\0', sizeof(fstring
));
5336 info
->version
=driver
.info_3
->cversion
;
5338 init_unistr( &info
->name
, driver
.info_3
->name
);
5339 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5341 if (strlen(driver
.info_3
->driverpath
)) {
5342 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->driverpath
);
5343 init_unistr( &info
->driverpath
, temp
);
5345 init_unistr( &info
->driverpath
, "" );
5347 if (strlen(driver
.info_3
->datafile
)) {
5348 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->datafile
);
5349 init_unistr( &info
->datafile
, temp
);
5351 init_unistr( &info
->datafile
, "" );
5353 if (strlen(driver
.info_3
->configfile
)) {
5354 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->configfile
);
5355 init_unistr( &info
->configfile
, temp
);
5357 init_unistr( &info
->configfile
, "" );
5359 if (strlen(driver
.info_3
->helpfile
)) {
5360 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", cservername
, driver
.info_3
->helpfile
);
5361 init_unistr( &info
->helpfile
, temp
);
5363 init_unistr( &info
->helpfile
, "" );
5365 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5366 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5368 info
->dependentfiles
= NULL
;
5369 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5371 info
->previousdrivernames
=NULL
;
5372 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5374 info
->driver_date
=0;
5377 info
->driver_version_low
=0;
5378 info
->driver_version_high
=0;
5380 init_unistr( &info
->mfgname
, "");
5381 init_unistr( &info
->oem_url
, "");
5382 init_unistr( &info
->hardware_id
, "");
5383 init_unistr( &info
->provider
, "");
5386 /********************************************************************
5387 * construct_printer_info_6
5388 * fill a printer_info_6 struct
5389 ********************************************************************/
5391 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5392 const char *servername
, fstring architecture
, uint32 version
)
5394 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5395 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5398 ZERO_STRUCT(driver
);
5400 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5402 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5404 if (!W_ERROR_IS_OK(status
))
5405 return WERR_INVALID_PRINTER_NAME
;
5407 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5409 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5411 if (!W_ERROR_IS_OK(status
))
5414 * Is this a W2k client ?
5418 free_a_printer(&printer
,2);
5419 return WERR_UNKNOWN_PRINTER_DRIVER
;
5422 /* Yes - try again with a WinNT driver. */
5424 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5425 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5426 if (!W_ERROR_IS_OK(status
)) {
5427 free_a_printer(&printer
,2);
5428 return WERR_UNKNOWN_PRINTER_DRIVER
;
5432 fill_printer_driver_info_6(info
, driver
, servername
);
5434 free_a_printer(&printer
,2);
5435 free_a_printer_driver(driver
, 3);
5440 /****************************************************************************
5441 ****************************************************************************/
5443 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5445 SAFE_FREE(info
->dependentfiles
);
5448 /****************************************************************************
5449 ****************************************************************************/
5451 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5453 SAFE_FREE(info
->dependentfiles
);
5456 /****************************************************************************
5457 ****************************************************************************/
5459 static WERROR
getprinterdriver2_level1(const char *servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5461 DRIVER_INFO_1
*info
=NULL
;
5464 if((info
=SMB_MALLOC_P(DRIVER_INFO_1
)) == NULL
)
5467 result
= construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5468 if (!W_ERROR_IS_OK(result
))
5471 /* check the required size. */
5472 *needed
+= spoolss_size_printer_driver_info_1(info
);
5474 if (*needed
> offered
) {
5475 result
= WERR_INSUFFICIENT_BUFFER
;
5479 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5480 result
= WERR_NOMEM
;
5484 /* fill the buffer with the structures */
5485 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5494 /****************************************************************************
5495 ****************************************************************************/
5497 static WERROR
getprinterdriver2_level2(const char *servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5499 DRIVER_INFO_2
*info
=NULL
;
5502 if((info
=SMB_MALLOC_P(DRIVER_INFO_2
)) == NULL
)
5505 result
= construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5506 if (!W_ERROR_IS_OK(result
))
5509 /* check the required size. */
5510 *needed
+= spoolss_size_printer_driver_info_2(info
);
5512 if (*needed
> offered
) {
5513 result
= WERR_INSUFFICIENT_BUFFER
;
5517 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5518 result
= WERR_NOMEM
;
5522 /* fill the buffer with the structures */
5523 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5532 /****************************************************************************
5533 ****************************************************************************/
5535 static WERROR
getprinterdriver2_level3(const char *servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5542 result
= construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5543 if (!W_ERROR_IS_OK(result
))
5546 /* check the required size. */
5547 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5549 if (*needed
> offered
) {
5550 result
= WERR_INSUFFICIENT_BUFFER
;
5554 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5555 result
= WERR_NOMEM
;
5559 /* fill the buffer with the structures */
5560 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5563 free_printer_driver_info_3(&info
);
5568 /****************************************************************************
5569 ****************************************************************************/
5571 static WERROR
getprinterdriver2_level6(const char *servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5578 result
= construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5579 if (!W_ERROR_IS_OK(result
))
5582 /* check the required size. */
5583 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5585 if (*needed
> offered
) {
5586 result
= WERR_INSUFFICIENT_BUFFER
;
5590 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5591 result
= WERR_NOMEM
;
5595 /* fill the buffer with the structures */
5596 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5599 free_printer_driver_info_6(&info
);
5604 /****************************************************************************
5605 ****************************************************************************/
5607 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5609 POLICY_HND
*handle
= &q_u
->handle
;
5610 UNISTR2
*uni_arch
= &q_u
->architecture
;
5611 uint32 level
= q_u
->level
;
5612 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5613 RPC_BUFFER
*buffer
= NULL
;
5614 uint32 offered
= q_u
->offered
;
5615 uint32
*needed
= &r_u
->needed
;
5616 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5617 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5618 Printer_entry
*printer
;
5621 fstring architecture
;
5624 /* that's an [in out] buffer */
5626 if (!q_u
->buffer
&& (offered
!=0)) {
5627 return WERR_INVALID_PARAM
;
5630 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5631 buffer
= r_u
->buffer
;
5633 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5635 if ( !(printer
= find_printer_index_by_hnd( p
, handle
)) ) {
5636 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5637 return WERR_INVALID_PRINTER_NAME
;
5641 *servermajorversion
= 0;
5642 *serverminorversion
= 0;
5644 fstrcpy(servername
, get_server_name( printer
));
5645 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5647 if (!get_printer_snum(p
, handle
, &snum
))
5652 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5654 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5656 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5658 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5661 /* apparently this call is the equivalent of
5662 EnumPrinterDataEx() for the DsDriver key */
5667 return WERR_UNKNOWN_LEVEL
;
5670 /****************************************************************************
5671 ****************************************************************************/
5673 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5675 POLICY_HND
*handle
= &q_u
->handle
;
5677 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5680 DEBUG(3,("Error in startpageprinter printer handle\n"));
5684 Printer
->page_started
=True
;
5688 /****************************************************************************
5689 ****************************************************************************/
5691 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5693 POLICY_HND
*handle
= &q_u
->handle
;
5696 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5699 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5703 if (!get_printer_snum(p
, handle
, &snum
))
5706 Printer
->page_started
=False
;
5707 print_job_endpage(snum
, Printer
->jobid
);
5712 /********************************************************************
5713 * api_spoolss_getprinter
5714 * called from the spoolss dispatcher
5716 ********************************************************************/
5718 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5720 POLICY_HND
*handle
= &q_u
->handle
;
5721 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5722 uint32
*jobid
= &r_u
->jobid
;
5724 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5728 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5729 struct current_user user
;
5732 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5736 get_current_user(&user
, p
);
5739 * a nice thing with NT is it doesn't listen to what you tell it.
5740 * when asked to send _only_ RAW datas, it tries to send datas
5743 * So I add checks like in NT Server ...
5746 if (info_1
->p_datatype
!= 0) {
5747 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5748 if (strcmp(datatype
, "RAW") != 0) {
5750 return WERR_INVALID_DATATYPE
;
5754 /* get the share number of the printer */
5755 if (!get_printer_snum(p
, handle
, &snum
)) {
5759 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5761 Printer
->jobid
= print_job_start(&user
, snum
, jobname
, Printer
->nt_devmode
);
5763 /* An error occured in print_job_start() so return an appropriate
5766 if (Printer
->jobid
== -1) {
5767 return map_werror_from_unix(errno
);
5770 Printer
->document_started
=True
;
5771 (*jobid
) = Printer
->jobid
;
5776 /********************************************************************
5777 * api_spoolss_getprinter
5778 * called from the spoolss dispatcher
5780 ********************************************************************/
5782 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5784 POLICY_HND
*handle
= &q_u
->handle
;
5786 return _spoolss_enddocprinter_internal(p
, handle
);
5789 /****************************************************************************
5790 ****************************************************************************/
5792 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5794 POLICY_HND
*handle
= &q_u
->handle
;
5795 uint32 buffer_size
= q_u
->buffer_size
;
5796 uint8
*buffer
= q_u
->buffer
;
5797 uint32
*buffer_written
= &q_u
->buffer_size2
;
5799 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5802 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5803 r_u
->buffer_written
= q_u
->buffer_size2
;
5807 if (!get_printer_snum(p
, handle
, &snum
))
5810 (*buffer_written
) = (uint32
)print_job_write(snum
, Printer
->jobid
, (const char *)buffer
,
5811 (SMB_OFF_T
)-1, (size_t)buffer_size
);
5812 if (*buffer_written
== (uint32
)-1) {
5813 r_u
->buffer_written
= 0;
5814 if (errno
== ENOSPC
)
5815 return WERR_NO_SPOOL_SPACE
;
5817 return WERR_ACCESS_DENIED
;
5820 r_u
->buffer_written
= q_u
->buffer_size2
;
5825 /********************************************************************
5826 * api_spoolss_getprinter
5827 * called from the spoolss dispatcher
5829 ********************************************************************/
5831 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5834 struct current_user user
;
5836 WERROR errcode
= WERR_BADFUNC
;
5837 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5839 get_current_user(&user
, p
);
5842 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5846 if (!get_printer_snum(p
, handle
, &snum
))
5850 case PRINTER_CONTROL_PAUSE
:
5851 if (print_queue_pause(&user
, snum
, &errcode
)) {
5855 case PRINTER_CONTROL_RESUME
:
5856 case PRINTER_CONTROL_UNPAUSE
:
5857 if (print_queue_resume(&user
, snum
, &errcode
)) {
5861 case PRINTER_CONTROL_PURGE
:
5862 if (print_queue_purge(&user
, snum
, &errcode
)) {
5867 return WERR_UNKNOWN_LEVEL
;
5873 /********************************************************************
5874 * api_spoolss_abortprinter
5875 * From MSDN: "Deletes printer's spool file if printer is configured
5877 ********************************************************************/
5879 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5881 POLICY_HND
*handle
= &q_u
->handle
;
5882 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5884 struct current_user user
;
5885 WERROR errcode
= WERR_OK
;
5888 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5892 if (!get_printer_snum(p
, handle
, &snum
))
5895 get_current_user( &user
, p
);
5897 print_job_delete( &user
, snum
, Printer
->jobid
, &errcode
);
5902 /********************************************************************
5903 * called by spoolss_api_setprinter
5904 * when updating a printer description
5905 ********************************************************************/
5907 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5908 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5909 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5911 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5915 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5917 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
)) {
5918 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5919 OUR_HANDLE(handle
)));
5921 result
= WERR_BADFID
;
5926 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5927 result
= WERR_INVALID_PARAM
;
5931 /* Check the user has permissions to change the security
5932 descriptor. By experimentation with two NT machines, the user
5933 requires Full Access to the printer to change security
5936 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5937 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5938 result
= WERR_ACCESS_DENIED
;
5942 /* NT seems to like setting the security descriptor even though
5943 nothing may have actually changed. */
5945 nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
);
5947 if (DEBUGLEVEL
>= 10) {
5951 the_acl
= old_secdesc_ctr
->sec
->dacl
;
5952 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5953 PRINTERNAME(snum
), the_acl
->num_aces
));
5955 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5958 sid_to_string(sid_str
, &the_acl
->aces
[i
].trustee
);
5960 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5961 the_acl
->aces
[i
].access_mask
));
5964 the_acl
= secdesc_ctr
->sec
->dacl
;
5967 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5968 PRINTERNAME(snum
), the_acl
->num_aces
));
5970 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5973 sid_to_string(sid_str
, &the_acl
->aces
[i
].trustee
);
5975 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5976 the_acl
->aces
[i
].access_mask
));
5979 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5983 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5984 if (!new_secdesc_ctr
) {
5985 result
= WERR_NOMEM
;
5989 if (sec_desc_equal(new_secdesc_ctr
->sec
, old_secdesc_ctr
->sec
)) {
5994 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
6001 /********************************************************************
6002 Canonicalize printer info from a client
6004 ATTN: It does not matter what we set the servername to hear
6005 since we do the necessary work in get_a_printer() to set it to
6006 the correct value based on what the client sent in the
6007 _spoolss_open_printer_ex().
6008 ********************************************************************/
6010 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
6012 fstring printername
;
6015 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6016 "portname=%s drivername=%s comment=%s location=%s\n",
6017 info
->servername
, info
->printername
, info
->sharename
,
6018 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
6020 /* we force some elements to "correct" values */
6021 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
6022 fstrcpy(info
->sharename
, lp_servicename(snum
));
6024 /* check to see if we allow printername != sharename */
6026 if ( lp_force_printername(snum
) ) {
6027 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
6028 global_myname(), info
->sharename
);
6031 /* make sure printername is in \\server\printername format */
6033 fstrcpy( printername
, info
->printername
);
6035 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
6036 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
6040 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
6041 global_myname(), p
);
6044 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
6045 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
6052 /****************************************************************************
6053 ****************************************************************************/
6055 WERROR
add_port_hook(NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
6057 char *cmd
= lp_addport_cmd();
6061 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
6062 BOOL is_print_op
= False
;
6065 return WERR_ACCESS_DENIED
;
6068 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
6071 is_print_op
= user_has_privileges( token
, &se_printop
);
6073 DEBUG(10,("Running [%s]\n", command
));
6075 /********* BEGIN SePrintOperatorPrivilege **********/
6080 ret
= smbrun(command
, &fd
);
6085 /********* END SePrintOperatorPrivilege **********/
6087 DEBUGADD(10,("returned [%d]\n", ret
));
6092 return WERR_ACCESS_DENIED
;
6098 /****************************************************************************
6099 ****************************************************************************/
6101 BOOL
add_printer_hook(NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
6103 char *cmd
= lp_addprinter_cmd();
6109 fstring remote_machine
= "%m";
6110 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
6111 BOOL is_print_op
= False
;
6113 standard_sub_basic(current_user_info
.smb_name
,
6114 current_user_info
.domain
,
6115 remote_machine
,sizeof(remote_machine
));
6117 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6118 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
6119 printer
->info_2
->portname
, printer
->info_2
->drivername
,
6120 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
6123 is_print_op
= user_has_privileges( token
, &se_printop
);
6125 DEBUG(10,("Running [%s]\n", command
));
6127 /********* BEGIN SePrintOperatorPrivilege **********/
6132 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6133 /* Tell everyone we updated smb.conf. */
6134 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
6140 /********* END SePrintOperatorPrivilege **********/
6142 DEBUGADD(10,("returned [%d]\n", ret
));
6150 /* reload our services immediately */
6151 reload_services( False
);
6154 /* Get lines and convert them back to dos-codepage */
6155 qlines
= fd_lines_load(fd
, &numlines
, 0);
6156 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6159 /* Set the portname to what the script says the portname should be. */
6160 /* but don't require anything to be return from the script exit a good error code */
6163 /* Set the portname to what the script says the portname should be. */
6164 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
6165 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6168 file_lines_free(qlines
);
6173 /********************************************************************
6174 * Called by spoolss_api_setprinter
6175 * when updating a printer description.
6176 ********************************************************************/
6178 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
6179 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6180 DEVICEMODE
*devmode
)
6183 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6184 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6189 DEBUG(8,("update_printer\n"));
6194 result
= WERR_BADFID
;
6198 if (!get_printer_snum(p
, handle
, &snum
)) {
6199 result
= WERR_BADFID
;
6203 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6204 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6205 result
= WERR_BADFID
;
6209 DEBUGADD(8,("Converting info_2 struct\n"));
6212 * convert_printer_info converts the incoming
6213 * info from the client and overwrites the info
6214 * just read from the tdb in the pointer 'printer'.
6217 if (!convert_printer_info(info
, printer
, level
)) {
6218 result
= WERR_NOMEM
;
6223 /* we have a valid devmode
6224 convert it and link it*/
6226 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6227 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6228 &printer
->info_2
->devmode
)) {
6229 result
= WERR_NOMEM
;
6234 /* Do sanity check on the requested changes for Samba */
6236 if (!check_printer_ok(printer
->info_2
, snum
)) {
6237 result
= WERR_INVALID_PARAM
;
6241 /* FIXME!!! If the driver has changed we really should verify that
6242 it is installed before doing much else --jerry */
6244 /* Check calling user has permission to update printer description */
6246 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6247 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6248 result
= WERR_ACCESS_DENIED
;
6252 /* Call addprinter hook */
6253 /* Check changes to see if this is really needed */
6255 if ( *lp_addprinter_cmd()
6256 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6257 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6258 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6259 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6261 /* add_printer_hook() will call reload_services() */
6263 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
6264 result
= WERR_ACCESS_DENIED
;
6270 * When a *new* driver is bound to a printer, the drivername is used to
6271 * lookup previously saved driver initialization info, which is then
6272 * bound to the printer, simulating what happens in the Windows arch.
6274 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6276 if (!set_driver_init(printer
, 2))
6278 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6279 printer
->info_2
->drivername
));
6282 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6283 printer
->info_2
->drivername
));
6285 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6289 * flag which changes actually occured. This is a small subset of
6290 * all the possible changes. We also have to update things in the
6294 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6295 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6296 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6297 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6299 notify_printer_comment(snum
, printer
->info_2
->comment
);
6302 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6303 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6304 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6305 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6307 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6310 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6313 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6316 pname
= printer
->info_2
->printername
;
6319 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6320 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6321 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6323 notify_printer_printername( snum
, pname
);
6326 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6327 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6328 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6329 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6331 notify_printer_port(snum
, printer
->info_2
->portname
);
6334 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6335 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6336 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6337 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6339 notify_printer_location(snum
, printer
->info_2
->location
);
6342 /* here we need to update some more DsSpooler keys */
6343 /* uNCName, serverName, shortServerName */
6345 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6346 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6347 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6348 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6349 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6351 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6352 global_myname(), printer
->info_2
->sharename
);
6353 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6354 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6355 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6357 /* Update printer info */
6358 result
= mod_a_printer(printer
, 2);
6361 free_a_printer(&printer
, 2);
6362 free_a_printer(&old_printer
, 2);
6368 /****************************************************************************
6369 ****************************************************************************/
6370 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6371 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6374 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6376 Printer_entry
*Printer
;
6378 if ( lp_security() != SEC_ADS
) {
6379 return WERR_UNKNOWN_LEVEL
;
6382 Printer
= find_printer_index_by_hnd(p
, handle
);
6384 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6389 if (!get_printer_snum(p
, handle
, &snum
))
6392 nt_printer_publish(Printer
, snum
, info7
->action
);
6396 return WERR_UNKNOWN_LEVEL
;
6399 /****************************************************************************
6400 ****************************************************************************/
6402 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6404 POLICY_HND
*handle
= &q_u
->handle
;
6405 uint32 level
= q_u
->level
;
6406 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6407 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6408 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6409 uint32 command
= q_u
->command
;
6412 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6415 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6419 /* check the level */
6422 return control_printer(handle
, command
, p
);
6424 result
= update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6425 if (!W_ERROR_IS_OK(result
))
6428 result
= update_printer_sec(handle
, level
, info
, p
, secdesc_ctr
);
6431 return update_printer_sec(handle
, level
, info
, p
,
6434 return publish_or_unpublish_printer(p
, handle
, info
);
6436 return WERR_UNKNOWN_LEVEL
;
6440 /****************************************************************************
6441 ****************************************************************************/
6443 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6445 POLICY_HND
*handle
= &q_u
->handle
;
6446 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6449 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6453 if (Printer
->notify
.client_connected
==True
) {
6456 if ( Printer
->printer_type
== SPLHND_SERVER
)
6458 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
6459 !get_printer_snum(p
, handle
, &snum
) )
6462 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6465 Printer
->notify
.flags
=0;
6466 Printer
->notify
.options
=0;
6467 Printer
->notify
.localmachine
[0]='\0';
6468 Printer
->notify
.printerlocal
=0;
6469 if (Printer
->notify
.option
)
6470 free_spool_notify_option(&Printer
->notify
.option
);
6471 Printer
->notify
.client_connected
=False
;
6476 /****************************************************************************
6477 ****************************************************************************/
6479 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6481 /* that's an [in out] buffer */
6483 if (!q_u
->buffer
&& (q_u
->offered
!=0)) {
6484 return WERR_INVALID_PARAM
;
6487 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6490 return WERR_INVALID_PARAM
; /* this is what a NT server
6491 returns for AddJob. AddJob
6492 must fail on non-local
6496 /****************************************************************************
6497 ****************************************************************************/
6499 static void fill_job_info_1(JOB_INFO_1
*job_info
, const print_queue_struct
*queue
,
6500 int position
, int snum
,
6501 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
6505 t
=gmtime(&queue
->time
);
6507 job_info
->jobid
=queue
->job
;
6508 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6509 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6510 init_unistr(&job_info
->username
, queue
->fs_user
);
6511 init_unistr(&job_info
->document
, queue
->fs_file
);
6512 init_unistr(&job_info
->datatype
, "RAW");
6513 init_unistr(&job_info
->text_status
, "");
6514 job_info
->status
=nt_printj_status(queue
->status
);
6515 job_info
->priority
=queue
->priority
;
6516 job_info
->position
=position
;
6517 job_info
->totalpages
=queue
->page_count
;
6518 job_info
->pagesprinted
=0;
6520 make_systemtime(&job_info
->submitted
, t
);
6523 /****************************************************************************
6524 ****************************************************************************/
6526 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, const print_queue_struct
*queue
,
6527 int position
, int snum
,
6528 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6529 DEVICEMODE
*devmode
)
6533 t
=gmtime(&queue
->time
);
6535 job_info
->jobid
=queue
->job
;
6537 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6539 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6540 init_unistr(&job_info
->username
, queue
->fs_user
);
6541 init_unistr(&job_info
->document
, queue
->fs_file
);
6542 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6543 init_unistr(&job_info
->datatype
, "RAW");
6544 init_unistr(&job_info
->printprocessor
, "winprint");
6545 init_unistr(&job_info
->parameters
, "");
6546 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6547 init_unistr(&job_info
->text_status
, "");
6549 /* and here the security descriptor */
6551 job_info
->status
=nt_printj_status(queue
->status
);
6552 job_info
->priority
=queue
->priority
;
6553 job_info
->position
=position
;
6554 job_info
->starttime
=0;
6555 job_info
->untiltime
=0;
6556 job_info
->totalpages
=queue
->page_count
;
6557 job_info
->size
=queue
->size
;
6558 make_systemtime(&(job_info
->submitted
), t
);
6559 job_info
->timeelapsed
=0;
6560 job_info
->pagesprinted
=0;
6562 job_info
->devmode
= devmode
;
6567 /****************************************************************************
6568 Enumjobs at level 1.
6569 ****************************************************************************/
6571 static WERROR
enumjobs_level1(const print_queue_struct
*queue
, int snum
,
6572 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6573 RPC_BUFFER
*buffer
, uint32 offered
,
6574 uint32
*needed
, uint32
*returned
)
6578 WERROR result
= WERR_OK
;
6580 info
=SMB_MALLOC_ARRAY(JOB_INFO_1
,*returned
);
6586 for (i
=0; i
<*returned
; i
++)
6587 fill_job_info_1( &info
[i
], &queue
[i
], i
, snum
, ntprinter
);
6589 /* check the required size. */
6590 for (i
=0; i
<*returned
; i
++)
6591 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6593 if (*needed
> offered
) {
6594 result
= WERR_INSUFFICIENT_BUFFER
;
6598 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6599 result
= WERR_NOMEM
;
6603 /* fill the buffer with the structures */
6604 for (i
=0; i
<*returned
; i
++)
6605 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6611 if ( !W_ERROR_IS_OK(result
) )
6617 /****************************************************************************
6618 Enumjobs at level 2.
6619 ****************************************************************************/
6621 static WERROR
enumjobs_level2(const print_queue_struct
*queue
, int snum
,
6622 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6623 RPC_BUFFER
*buffer
, uint32 offered
,
6624 uint32
*needed
, uint32
*returned
)
6626 JOB_INFO_2
*info
= NULL
;
6628 WERROR result
= WERR_OK
;
6629 DEVICEMODE
*devmode
= NULL
;
6631 if ( !(info
= SMB_MALLOC_ARRAY(JOB_INFO_2
,*returned
)) ) {
6636 /* this should not be a failure condition if the devmode is NULL */
6638 devmode
= construct_dev_mode(lp_const_servicename(snum
));
6640 for (i
=0; i
<*returned
; i
++)
6641 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
, devmode
);
6643 /* check the required size. */
6644 for (i
=0; i
<*returned
; i
++)
6645 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6647 if (*needed
> offered
) {
6648 result
= WERR_INSUFFICIENT_BUFFER
;
6652 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6653 result
= WERR_NOMEM
;
6657 /* fill the buffer with the structures */
6658 for (i
=0; i
<*returned
; i
++)
6659 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6662 free_devmode(devmode
);
6665 if ( !W_ERROR_IS_OK(result
) )
6672 /****************************************************************************
6674 ****************************************************************************/
6676 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6678 POLICY_HND
*handle
= &q_u
->handle
;
6679 uint32 level
= q_u
->level
;
6680 RPC_BUFFER
*buffer
= NULL
;
6681 uint32 offered
= q_u
->offered
;
6682 uint32
*needed
= &r_u
->needed
;
6683 uint32
*returned
= &r_u
->returned
;
6685 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6687 print_status_struct prt_status
;
6688 print_queue_struct
*queue
=NULL
;
6690 /* that's an [in out] buffer */
6692 if (!q_u
->buffer
&& (offered
!=0)) {
6693 return WERR_INVALID_PARAM
;
6696 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6697 buffer
= r_u
->buffer
;
6699 DEBUG(4,("_spoolss_enumjobs\n"));
6704 /* lookup the printer snum and tdb entry */
6706 if (!get_printer_snum(p
, handle
, &snum
))
6709 wret
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6710 if ( !W_ERROR_IS_OK(wret
) )
6713 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6714 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6716 if (*returned
== 0) {
6718 free_a_printer(&ntprinter
, 2);
6724 wret
= enumjobs_level1(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6727 wret
= enumjobs_level2(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6731 wret
= WERR_UNKNOWN_LEVEL
;
6736 free_a_printer( &ntprinter
, 2 );
6740 /****************************************************************************
6741 ****************************************************************************/
6743 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6748 /****************************************************************************
6749 ****************************************************************************/
6751 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6753 POLICY_HND
*handle
= &q_u
->handle
;
6754 uint32 jobid
= q_u
->jobid
;
6755 uint32 command
= q_u
->command
;
6757 struct current_user user
;
6759 WERROR errcode
= WERR_BADFUNC
;
6761 if (!get_printer_snum(p
, handle
, &snum
)) {
6765 if (!print_job_exists(lp_const_servicename(snum
), jobid
)) {
6766 return WERR_INVALID_PRINTER_NAME
;
6769 get_current_user(&user
, p
);
6772 case JOB_CONTROL_CANCEL
:
6773 case JOB_CONTROL_DELETE
:
6774 if (print_job_delete(&user
, snum
, jobid
, &errcode
)) {
6778 case JOB_CONTROL_PAUSE
:
6779 if (print_job_pause(&user
, snum
, jobid
, &errcode
)) {
6783 case JOB_CONTROL_RESTART
:
6784 case JOB_CONTROL_RESUME
:
6785 if (print_job_resume(&user
, snum
, jobid
, &errcode
)) {
6790 return WERR_UNKNOWN_LEVEL
;
6796 /****************************************************************************
6797 Enumerates all printer drivers at level 1.
6798 ****************************************************************************/
6800 static WERROR
enumprinterdrivers_level1(const char *servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6805 fstring
*list
= NULL
;
6806 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6807 DRIVER_INFO_1
*driver_info_1
=NULL
;
6808 WERROR result
= WERR_OK
;
6812 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6814 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6815 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6817 if(ndrivers
== -1) {
6818 SAFE_FREE(driver_info_1
);
6823 if((driver_info_1
=SMB_REALLOC_ARRAY(driver_info_1
, DRIVER_INFO_1
, *returned
+ndrivers
)) == NULL
) {
6824 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6830 for (i
=0; i
<ndrivers
; i
++) {
6832 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6833 ZERO_STRUCT(driver
);
6834 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6835 architecture
, version
);
6836 if (!W_ERROR_IS_OK(status
)) {
6838 SAFE_FREE(driver_info_1
);
6841 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6842 free_a_printer_driver(driver
, 3);
6845 *returned
+=ndrivers
;
6849 /* check the required size. */
6850 for (i
=0; i
<*returned
; i
++) {
6851 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6852 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6855 if (*needed
> offered
) {
6856 result
= WERR_INSUFFICIENT_BUFFER
;
6860 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6861 result
= WERR_NOMEM
;
6865 /* fill the buffer with the driver structures */
6866 for (i
=0; i
<*returned
; i
++) {
6867 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6868 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6872 SAFE_FREE(driver_info_1
);
6874 if ( !W_ERROR_IS_OK(result
) )
6880 /****************************************************************************
6881 Enumerates all printer drivers at level 2.
6882 ****************************************************************************/
6884 static WERROR
enumprinterdrivers_level2(const char *servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6889 fstring
*list
= NULL
;
6890 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6891 DRIVER_INFO_2
*driver_info_2
=NULL
;
6892 WERROR result
= WERR_OK
;
6896 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6898 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6899 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6901 if(ndrivers
== -1) {
6902 SAFE_FREE(driver_info_2
);
6907 if((driver_info_2
=SMB_REALLOC_ARRAY(driver_info_2
, DRIVER_INFO_2
, *returned
+ndrivers
)) == NULL
) {
6908 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6914 for (i
=0; i
<ndrivers
; i
++) {
6917 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6918 ZERO_STRUCT(driver
);
6919 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6920 architecture
, version
);
6921 if (!W_ERROR_IS_OK(status
)) {
6923 SAFE_FREE(driver_info_2
);
6926 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6927 free_a_printer_driver(driver
, 3);
6930 *returned
+=ndrivers
;
6934 /* check the required size. */
6935 for (i
=0; i
<*returned
; i
++) {
6936 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6937 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6940 if (*needed
> offered
) {
6941 result
= WERR_INSUFFICIENT_BUFFER
;
6945 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6946 result
= WERR_NOMEM
;
6950 /* fill the buffer with the form structures */
6951 for (i
=0; i
<*returned
; i
++) {
6952 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6953 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6957 SAFE_FREE(driver_info_2
);
6959 if ( !W_ERROR_IS_OK(result
) )
6965 /****************************************************************************
6966 Enumerates all printer drivers at level 3.
6967 ****************************************************************************/
6969 static WERROR
enumprinterdrivers_level3(const char *servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6974 fstring
*list
= NULL
;
6975 DRIVER_INFO_3
*driver_info_3
=NULL
;
6976 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6977 WERROR result
= WERR_OK
;
6981 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6983 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6984 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6986 if(ndrivers
== -1) {
6987 SAFE_FREE(driver_info_3
);
6992 if((driver_info_3
=SMB_REALLOC_ARRAY(driver_info_3
, DRIVER_INFO_3
, *returned
+ndrivers
)) == NULL
) {
6993 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
6999 for (i
=0; i
<ndrivers
; i
++) {
7002 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
7003 ZERO_STRUCT(driver
);
7004 status
= get_a_printer_driver(&driver
, 3, list
[i
],
7005 architecture
, version
);
7006 if (!W_ERROR_IS_OK(status
)) {
7008 SAFE_FREE(driver_info_3
);
7011 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
7012 free_a_printer_driver(driver
, 3);
7015 *returned
+=ndrivers
;
7019 /* check the required size. */
7020 for (i
=0; i
<*returned
; i
++) {
7021 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
7022 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
7025 if (*needed
> offered
) {
7026 result
= WERR_INSUFFICIENT_BUFFER
;
7030 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7031 result
= WERR_NOMEM
;
7035 /* fill the buffer with the driver structures */
7036 for (i
=0; i
<*returned
; i
++) {
7037 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
7038 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
7042 for (i
=0; i
<*returned
; i
++) {
7043 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
7046 SAFE_FREE(driver_info_3
);
7048 if ( !W_ERROR_IS_OK(result
) )
7054 /****************************************************************************
7055 Enumerates all printer drivers.
7056 ****************************************************************************/
7058 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
7060 uint32 level
= q_u
->level
;
7061 RPC_BUFFER
*buffer
= NULL
;
7062 uint32 offered
= q_u
->offered
;
7063 uint32
*needed
= &r_u
->needed
;
7064 uint32
*returned
= &r_u
->returned
;
7065 const char *cservername
;
7067 fstring architecture
;
7069 /* that's an [in out] buffer */
7071 if (!q_u
->buffer
&& (offered
!=0)) {
7072 return WERR_INVALID_PARAM
;
7075 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7076 buffer
= r_u
->buffer
;
7078 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7083 unistr2_to_ascii(architecture
, &q_u
->environment
, sizeof(architecture
)-1);
7084 unistr2_to_ascii(servername
, &q_u
->name
, sizeof(servername
)-1);
7086 cservername
= canon_servername(servername
);
7088 if (!is_myname_or_ipaddr(cservername
))
7089 return WERR_UNKNOWN_PRINTER_DRIVER
;
7093 return enumprinterdrivers_level1(cservername
, architecture
, buffer
, offered
, needed
, returned
);
7095 return enumprinterdrivers_level2(cservername
, architecture
, buffer
, offered
, needed
, returned
);
7097 return enumprinterdrivers_level3(cservername
, architecture
, buffer
, offered
, needed
, returned
);
7099 return WERR_UNKNOWN_LEVEL
;
7103 /****************************************************************************
7104 ****************************************************************************/
7106 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
7108 form
->flag
=list
->flag
;
7109 init_unistr(&form
->name
, list
->name
);
7110 form
->width
=list
->width
;
7111 form
->length
=list
->length
;
7112 form
->left
=list
->left
;
7113 form
->top
=list
->top
;
7114 form
->right
=list
->right
;
7115 form
->bottom
=list
->bottom
;
7118 /****************************************************************************
7119 ****************************************************************************/
7121 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
7123 uint32 level
= q_u
->level
;
7124 RPC_BUFFER
*buffer
= NULL
;
7125 uint32 offered
= q_u
->offered
;
7126 uint32
*needed
= &r_u
->needed
;
7127 uint32
*numofforms
= &r_u
->numofforms
;
7128 uint32 numbuiltinforms
;
7130 nt_forms_struct
*list
=NULL
;
7131 nt_forms_struct
*builtinlist
=NULL
;
7136 /* that's an [in out] buffer */
7138 if (!q_u
->buffer
&& (offered
!=0) ) {
7139 return WERR_INVALID_PARAM
;
7142 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7143 buffer
= r_u
->buffer
;
7145 DEBUG(4,("_spoolss_enumforms\n"));
7146 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7147 DEBUGADD(5,("Info level [%d]\n", level
));
7149 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
7150 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
7151 *numofforms
= get_ntforms(&list
);
7152 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
7153 *numofforms
+= numbuiltinforms
;
7155 if (*numofforms
== 0) {
7156 SAFE_FREE(builtinlist
);
7158 return WERR_NO_MORE_ITEMS
;
7163 if ((forms_1
=SMB_MALLOC_ARRAY(FORM_1
, *numofforms
)) == NULL
) {
7164 SAFE_FREE(builtinlist
);
7170 /* construct the list of form structures */
7171 for (i
=0; i
<numbuiltinforms
; i
++) {
7172 DEBUGADD(6,("Filling form number [%d]\n",i
));
7173 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
7176 SAFE_FREE(builtinlist
);
7178 for (; i
<*numofforms
; i
++) {
7179 DEBUGADD(6,("Filling form number [%d]\n",i
));
7180 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
7185 /* check the required size. */
7186 for (i
=0; i
<numbuiltinforms
; i
++) {
7187 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7188 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7190 for (; i
<*numofforms
; i
++) {
7191 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7192 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7195 *needed
=buffer_size
;
7197 if (*needed
> offered
) {
7200 return WERR_INSUFFICIENT_BUFFER
;
7203 if (!rpcbuf_alloc_size(buffer
, buffer_size
)){
7209 /* fill the buffer with the form structures */
7210 for (i
=0; i
<numbuiltinforms
; i
++) {
7211 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7212 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7214 for (; i
<*numofforms
; i
++) {
7215 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7216 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7225 SAFE_FREE(builtinlist
);
7226 return WERR_UNKNOWN_LEVEL
;
7230 /****************************************************************************
7231 ****************************************************************************/
7233 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
7235 uint32 level
= q_u
->level
;
7236 UNISTR2
*uni_formname
= &q_u
->formname
;
7237 RPC_BUFFER
*buffer
= NULL
;
7238 uint32 offered
= q_u
->offered
;
7239 uint32
*needed
= &r_u
->needed
;
7241 nt_forms_struct
*list
=NULL
;
7242 nt_forms_struct builtin_form
;
7247 int numofforms
=0, i
=0;
7249 /* that's an [in out] buffer */
7251 if (!q_u
->buffer
&& (offered
!=0)) {
7252 return WERR_INVALID_PARAM
;
7255 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7256 buffer
= r_u
->buffer
;
7258 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
7260 DEBUG(4,("_spoolss_getform\n"));
7261 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7262 DEBUGADD(5,("Info level [%d]\n", level
));
7264 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
7265 if (!foundBuiltin
) {
7266 numofforms
= get_ntforms(&list
);
7267 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
7269 if (numofforms
== 0)
7276 fill_form_1(&form_1
, &builtin_form
);
7279 /* Check if the requested name is in the list of form structures */
7280 for (i
=0; i
<numofforms
; i
++) {
7282 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
7284 if (strequal(form_name
, list
[i
].name
)) {
7285 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
7286 fill_form_1(&form_1
, &list
[i
]);
7292 if (i
== numofforms
) {
7296 /* check the required size. */
7298 *needed
=spoolss_size_form_1(&form_1
);
7300 if (*needed
> offered
)
7301 return WERR_INSUFFICIENT_BUFFER
;
7303 if (!rpcbuf_alloc_size(buffer
, buffer_size
))
7306 /* fill the buffer with the form structures */
7307 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
7308 smb_io_form_1("", buffer
, &form_1
, 0);
7314 return WERR_UNKNOWN_LEVEL
;
7318 /****************************************************************************
7319 ****************************************************************************/
7321 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
7323 init_unistr(&port
->port_name
, name
);
7326 /****************************************************************************
7327 TODO: This probably needs distinguish between TCP/IP and Local ports
7329 ****************************************************************************/
7331 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
7333 init_unistr(&port
->port_name
, name
);
7334 init_unistr(&port
->monitor_name
, "Local Monitor");
7335 init_unistr(&port
->description
, SPL_LOCAL_PORT
);
7336 port
->port_type
=PORT_TYPE_WRITE
;
7341 /****************************************************************************
7342 wrapper around the enumer ports command
7343 ****************************************************************************/
7345 WERROR
enumports_hook( int *count
, char ***lines
)
7347 char *cmd
= lp_enumports_cmd();
7357 /* if no hook then just fill in the default port */
7360 qlines
= SMB_MALLOC_ARRAY( char*, 2 );
7361 qlines
[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME
);
7366 /* we have a valid enumport command */
7368 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
7370 DEBUG(10,("Running [%s]\n", command
));
7371 ret
= smbrun(command
, &fd
);
7372 DEBUG(10,("Returned [%d]\n", ret
));
7377 return WERR_ACCESS_DENIED
;
7381 qlines
= fd_lines_load(fd
, &numlines
, 0);
7382 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7392 /****************************************************************************
7394 ****************************************************************************/
7396 static WERROR
enumports_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7398 PORT_INFO_1
*ports
=NULL
;
7400 WERROR result
= WERR_OK
;
7401 char **qlines
= NULL
;
7404 result
= enumports_hook( &numlines
, &qlines
);
7405 if (!W_ERROR_IS_OK(result
)) {
7406 file_lines_free(qlines
);
7411 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_1
, numlines
)) == NULL
) {
7412 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7413 dos_errstr(WERR_NOMEM
)));
7414 file_lines_free(qlines
);
7418 for (i
=0; i
<numlines
; i
++) {
7419 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7420 fill_port_1(&ports
[i
], qlines
[i
]);
7423 file_lines_free(qlines
);
7425 *returned
= numlines
;
7427 /* check the required size. */
7428 for (i
=0; i
<*returned
; i
++) {
7429 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7430 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7433 if (*needed
> offered
) {
7434 result
= WERR_INSUFFICIENT_BUFFER
;
7438 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7439 result
= WERR_NOMEM
;
7443 /* fill the buffer with the ports structures */
7444 for (i
=0; i
<*returned
; i
++) {
7445 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7446 smb_io_port_1("", buffer
, &ports
[i
], 0);
7452 if ( !W_ERROR_IS_OK(result
) )
7458 /****************************************************************************
7460 ****************************************************************************/
7462 static WERROR
enumports_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7464 PORT_INFO_2
*ports
=NULL
;
7466 WERROR result
= WERR_OK
;
7467 char **qlines
= NULL
;
7470 result
= enumports_hook( &numlines
, &qlines
);
7471 if ( !W_ERROR_IS_OK(result
)) {
7472 file_lines_free(qlines
);
7477 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_2
, numlines
)) == NULL
) {
7478 file_lines_free(qlines
);
7482 for (i
=0; i
<numlines
; i
++) {
7483 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7484 fill_port_2(&(ports
[i
]), qlines
[i
]);
7488 file_lines_free(qlines
);
7490 *returned
= numlines
;
7492 /* check the required size. */
7493 for (i
=0; i
<*returned
; i
++) {
7494 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7495 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7498 if (*needed
> offered
) {
7499 result
= WERR_INSUFFICIENT_BUFFER
;
7503 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7504 result
= WERR_NOMEM
;
7508 /* fill the buffer with the ports structures */
7509 for (i
=0; i
<*returned
; i
++) {
7510 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7511 smb_io_port_2("", buffer
, &ports
[i
], 0);
7517 if ( !W_ERROR_IS_OK(result
) )
7523 /****************************************************************************
7525 ****************************************************************************/
7527 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7529 uint32 level
= q_u
->level
;
7530 RPC_BUFFER
*buffer
= NULL
;
7531 uint32 offered
= q_u
->offered
;
7532 uint32
*needed
= &r_u
->needed
;
7533 uint32
*returned
= &r_u
->returned
;
7535 /* that's an [in out] buffer */
7537 if (!q_u
->buffer
&& (offered
!=0)) {
7538 return WERR_INVALID_PARAM
;
7541 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7542 buffer
= r_u
->buffer
;
7544 DEBUG(4,("_spoolss_enumports\n"));
7551 return enumports_level_1(buffer
, offered
, needed
, returned
);
7553 return enumports_level_2(buffer
, offered
, needed
, returned
);
7555 return WERR_UNKNOWN_LEVEL
;
7559 /****************************************************************************
7560 ****************************************************************************/
7562 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7563 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7564 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7565 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7568 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7571 WERROR err
= WERR_OK
;
7573 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7574 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7578 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7579 if (!convert_printer_info(info
, printer
, 2)) {
7580 free_a_printer(&printer
, 2);
7584 /* check to see if the printer already exists */
7586 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7587 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7588 printer
->info_2
->sharename
));
7589 free_a_printer(&printer
, 2);
7590 return WERR_PRINTER_ALREADY_EXISTS
;
7593 /* FIXME!!! smbd should check to see if the driver is installed before
7594 trying to add a printer like this --jerry */
7596 if (*lp_addprinter_cmd() ) {
7597 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
7598 free_a_printer(&printer
,2);
7599 return WERR_ACCESS_DENIED
;
7602 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7603 "smb.conf parameter \"addprinter command\" is defined. This"
7604 "parameter must exist for this call to succeed\n",
7605 printer
->info_2
->sharename
));
7608 /* use our primary netbios name since get_a_printer() will convert
7609 it to what the client expects on a case by case basis */
7611 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7612 printer
->info_2
->sharename
);
7615 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7616 free_a_printer(&printer
,2);
7617 return WERR_ACCESS_DENIED
;
7620 /* you must be a printer admin to add a new printer */
7621 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7622 free_a_printer(&printer
,2);
7623 return WERR_ACCESS_DENIED
;
7627 * Do sanity check on the requested changes for Samba.
7630 if (!check_printer_ok(printer
->info_2
, snum
)) {
7631 free_a_printer(&printer
,2);
7632 return WERR_INVALID_PARAM
;
7636 * When a printer is created, the drivername bound to the printer is used
7637 * to lookup previously saved driver initialization info, which is then
7638 * bound to the new printer, simulating what happens in the Windows arch.
7643 set_driver_init(printer
, 2);
7647 /* A valid devmode was included, convert and link it
7649 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7651 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7652 &printer
->info_2
->devmode
))
7656 /* write the ASCII on disk */
7657 err
= mod_a_printer(printer
, 2);
7658 if (!W_ERROR_IS_OK(err
)) {
7659 free_a_printer(&printer
,2);
7663 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7664 /* Handle open failed - remove addition. */
7665 del_a_printer(printer
->info_2
->sharename
);
7666 free_a_printer(&printer
,2);
7667 return WERR_ACCESS_DENIED
;
7670 update_c_setprinter(False
);
7671 free_a_printer(&printer
,2);
7676 /****************************************************************************
7677 ****************************************************************************/
7679 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7681 UNISTR2
*uni_srv_name
= q_u
->server_name
;
7682 uint32 level
= q_u
->level
;
7683 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7684 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7685 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7686 uint32 user_switch
= q_u
->user_switch
;
7687 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7688 POLICY_HND
*handle
= &r_u
->handle
;
7692 /* we don't handle yet */
7693 /* but I know what to do ... */
7694 return WERR_UNKNOWN_LEVEL
;
7696 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7698 user_switch
, user
, handle
);
7700 return WERR_UNKNOWN_LEVEL
;
7704 /****************************************************************************
7705 ****************************************************************************/
7707 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7709 uint32 level
= q_u
->level
;
7710 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7711 WERROR err
= WERR_OK
;
7712 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7713 struct current_user user
;
7714 fstring driver_name
;
7717 ZERO_STRUCT(driver
);
7719 get_current_user(&user
, p
);
7721 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7726 DEBUG(5,("Cleaning driver's information\n"));
7727 err
= clean_up_driver_struct(driver
, level
, &user
);
7728 if (!W_ERROR_IS_OK(err
))
7731 DEBUG(5,("Moving driver to final destination\n"));
7732 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(driver
, level
, &user
, &err
)) ) {
7736 if (add_a_printer_driver(driver
, level
)!=0) {
7737 err
= WERR_ACCESS_DENIED
;
7742 * I think this is where he DrvUpgradePrinter() hook would be
7743 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7744 * server. Right now, we just need to send ourselves a message
7745 * to update each printer bound to this driver. --jerry
7748 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7749 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7754 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7755 * decide if the driver init data should be deleted. The rules are:
7756 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7757 * 2) delete init data only if there is no 2k/Xp driver
7758 * 3) always delete init data
7759 * The generalized rule is always use init data from the highest order driver.
7760 * It is necessary to follow the driver install by an initialization step to
7761 * finish off this process.
7764 version
= driver
.info_3
->cversion
;
7765 else if (level
== 6)
7766 version
= driver
.info_6
->version
;
7771 * 9x printer driver - never delete init data
7774 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7779 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7780 * there is no 2k/Xp driver init data for this driver name.
7784 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7786 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7788 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7790 if (!del_driver_init(driver_name
))
7791 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7794 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7796 free_a_printer_driver(driver1
,3);
7797 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7804 * 2k or Xp printer driver - always delete init data
7807 if (!del_driver_init(driver_name
))
7808 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7812 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7818 free_a_printer_driver(driver
, level
);
7822 /********************************************************************
7823 * spoolss_addprinterdriverex
7824 ********************************************************************/
7826 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7828 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7829 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7832 * we only support the semantics of AddPrinterDriver()
7833 * i.e. only copy files that are newer than existing ones
7836 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7837 return WERR_ACCESS_DENIED
;
7839 ZERO_STRUCT(q_u_local
);
7840 ZERO_STRUCT(r_u_local
);
7842 /* just pass the information off to _spoolss_addprinterdriver() */
7843 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7844 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7845 q_u_local
.level
= q_u
->level
;
7846 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7848 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7851 /****************************************************************************
7852 ****************************************************************************/
7854 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7856 init_unistr(&info
->name
, name
);
7859 /****************************************************************************
7860 ****************************************************************************/
7862 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7867 const char *pservername
;
7868 const char *short_archi
;
7869 DRIVER_DIRECTORY_1
*info
=NULL
;
7870 WERROR result
= WERR_OK
;
7872 unistr2_to_ascii(servername
, name
, sizeof(servername
)-1);
7873 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7875 pservername
= canon_servername(servername
);
7877 if ( !is_myname_or_ipaddr( pservername
) )
7878 return WERR_INVALID_PARAM
;
7880 if (!(short_archi
= get_short_archi(long_archi
)))
7881 return WERR_INVALID_ENVIRONMENT
;
7883 if((info
=SMB_MALLOC_P(DRIVER_DIRECTORY_1
)) == NULL
)
7886 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", pservername
, short_archi
);
7888 DEBUG(4,("printer driver directory: [%s]\n", path
));
7890 fill_driverdir_1(info
, path
);
7892 *needed
+= spoolss_size_driverdir_info_1(info
);
7894 if (*needed
> offered
) {
7895 result
= WERR_INSUFFICIENT_BUFFER
;
7899 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7900 result
= WERR_NOMEM
;
7904 smb_io_driverdir_1("", buffer
, info
, 0);
7912 /****************************************************************************
7913 ****************************************************************************/
7915 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7917 UNISTR2
*name
= &q_u
->name
;
7918 UNISTR2
*uni_environment
= &q_u
->environment
;
7919 uint32 level
= q_u
->level
;
7920 RPC_BUFFER
*buffer
= NULL
;
7921 uint32 offered
= q_u
->offered
;
7922 uint32
*needed
= &r_u
->needed
;
7924 /* that's an [in out] buffer */
7926 if (!q_u
->buffer
&& (offered
!=0)) {
7927 return WERR_INVALID_PARAM
;
7930 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7931 buffer
= r_u
->buffer
;
7933 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7939 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7941 return WERR_UNKNOWN_LEVEL
;
7945 /****************************************************************************
7946 ****************************************************************************/
7948 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7950 POLICY_HND
*handle
= &q_u
->handle
;
7951 uint32 idx
= q_u
->index
;
7952 uint32 in_value_len
= q_u
->valuesize
;
7953 uint32 in_data_len
= q_u
->datasize
;
7954 uint32
*out_max_value_len
= &r_u
->valuesize
;
7955 uint16
**out_value
= &r_u
->value
;
7956 uint32
*out_value_len
= &r_u
->realvaluesize
;
7957 uint32
*out_type
= &r_u
->type
;
7958 uint32
*out_max_data_len
= &r_u
->datasize
;
7959 uint8
**data_out
= &r_u
->data
;
7960 uint32
*out_data_len
= &r_u
->realdatasize
;
7962 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7964 uint32 biggest_valuesize
;
7965 uint32 biggest_datasize
;
7967 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
7970 REGISTRY_VALUE
*val
= NULL
;
7971 NT_PRINTER_DATA
*p_data
;
7972 int i
, key_index
, num_values
;
7977 *out_max_data_len
= 0;
7981 DEBUG(5,("spoolss_enumprinterdata\n"));
7984 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
7988 if (!get_printer_snum(p
,handle
, &snum
))
7991 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7992 if (!W_ERROR_IS_OK(result
))
7995 p_data
= printer
->info_2
->data
;
7996 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
8001 * The NT machine wants to know the biggest size of value and data
8003 * cf: MSDN EnumPrinterData remark section
8006 if ( !in_value_len
&& !in_data_len
&& (key_index
!= -1) )
8008 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8010 biggest_valuesize
= 0;
8011 biggest_datasize
= 0;
8013 num_values
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
8015 for ( i
=0; i
<num_values
; i
++ )
8017 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
8019 name_length
= strlen(val
->valuename
);
8020 if ( strlen(val
->valuename
) > biggest_valuesize
)
8021 biggest_valuesize
= name_length
;
8023 if ( val
->size
> biggest_datasize
)
8024 biggest_datasize
= val
->size
;
8026 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
8030 /* the value is an UNICODE string but real_value_size is the length
8031 in bytes including the trailing 0 */
8033 *out_value_len
= 2 * (1+biggest_valuesize
);
8034 *out_data_len
= biggest_datasize
;
8036 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
8042 * the value len is wrong in NT sp3
8043 * that's the number of bytes not the number of unicode chars
8046 if ( key_index
!= -1 )
8047 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, idx
);
8052 /* out_value should default to "" or else NT4 has
8053 problems unmarshalling the response */
8055 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
8058 if((*out_value
=(uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
8060 result
= WERR_NOMEM
;
8063 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
8069 /* the data is counted in bytes */
8071 *out_max_data_len
= in_data_len
;
8072 *out_data_len
= in_data_len
;
8074 /* only allocate when given a non-zero data_len */
8076 if ( in_data_len
&& ((*data_out
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
8078 result
= WERR_NOMEM
;
8082 result
= WERR_NO_MORE_ITEMS
;
8088 * - counted in bytes in the request
8089 * - counted in UNICODE chars in the max reply
8090 * - counted in bytes in the real size
8092 * take a pause *before* coding not *during* coding
8096 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
8098 if ( (*out_value
= (uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
8100 result
= WERR_NOMEM
;
8104 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), (size_t)in_value_len
, 0);
8112 *out_type
= regval_type( val
);
8114 /* data - counted in bytes */
8116 *out_max_data_len
= in_data_len
;
8117 if ( in_data_len
&& (*data_out
= (uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
8119 result
= WERR_NOMEM
;
8122 data_len
= regval_size(val
);
8123 if ( *data_out
&& data_len
)
8124 memcpy( *data_out
, regval_data_p(val
), data_len
);
8125 *out_data_len
= data_len
;
8129 free_a_printer(&printer
, 2);
8133 /****************************************************************************
8134 ****************************************************************************/
8136 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
8138 POLICY_HND
*handle
= &q_u
->handle
;
8139 UNISTR2
*value
= &q_u
->value
;
8140 uint32 type
= q_u
->type
;
8141 uint8
*data
= q_u
->data
;
8142 uint32 real_len
= q_u
->real_len
;
8144 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8146 WERROR status
= WERR_OK
;
8147 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8150 DEBUG(5,("spoolss_setprinterdata\n"));
8153 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8157 if ( Printer
->printer_type
== SPLHND_SERVER
) {
8158 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8159 return WERR_INVALID_PARAM
;
8162 if (!get_printer_snum(p
,handle
, &snum
))
8166 * Access check : NT returns "access denied" if you make a
8167 * SetPrinterData call without the necessary privildge.
8168 * we were originally returning OK if nothing changed
8169 * which made Win2k issue **a lot** of SetPrinterData
8170 * when connecting to a printer --jerry
8173 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8175 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8176 status
= WERR_ACCESS_DENIED
;
8180 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8181 if (!W_ERROR_IS_OK(status
))
8184 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8187 * When client side code sets a magic printer data key, detect it and save
8188 * the current printer data and the magic key's data (its the DEVMODE) for
8189 * future printer/driver initializations.
8191 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
8193 /* Set devmode and printer initialization info */
8194 status
= save_driver_init( printer
, 2, data
, real_len
);
8196 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
8200 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
8201 type
, data
, real_len
);
8202 if ( W_ERROR_IS_OK(status
) )
8203 status
= mod_a_printer(printer
, 2);
8207 free_a_printer(&printer
, 2);
8212 /****************************************************************************
8213 ****************************************************************************/
8215 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
8217 POLICY_HND
*handle
= &q_u
->handle
;
8218 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8221 DEBUG(5,("_spoolss_resetprinter\n"));
8224 * All we do is to check to see if the handle and queue is valid.
8225 * This call really doesn't mean anything to us because we only
8226 * support RAW printing. --jerry
8230 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8234 if (!get_printer_snum(p
,handle
, &snum
))
8238 /* blindly return success */
8243 /****************************************************************************
8244 ****************************************************************************/
8246 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
8248 POLICY_HND
*handle
= &q_u
->handle
;
8249 UNISTR2
*value
= &q_u
->valuename
;
8251 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8253 WERROR status
= WERR_OK
;
8254 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8257 DEBUG(5,("spoolss_deleteprinterdata\n"));
8260 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8264 if (!get_printer_snum(p
, handle
, &snum
))
8267 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8268 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8269 return WERR_ACCESS_DENIED
;
8272 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8273 if (!W_ERROR_IS_OK(status
))
8276 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8278 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
8280 if ( W_ERROR_IS_OK(status
) )
8281 mod_a_printer( printer
, 2 );
8283 free_a_printer(&printer
, 2);
8288 /****************************************************************************
8289 ****************************************************************************/
8291 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
8293 POLICY_HND
*handle
= &q_u
->handle
;
8294 FORM
*form
= &q_u
->form
;
8295 nt_forms_struct tmpForm
;
8297 WERROR status
= WERR_OK
;
8298 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8301 nt_forms_struct
*list
=NULL
;
8302 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8304 DEBUG(5,("spoolss_addform\n"));
8307 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8312 /* forms can be added on printer of on the print server handle */
8314 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8316 if (!get_printer_snum(p
,handle
, &snum
))
8319 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8320 if (!W_ERROR_IS_OK(status
))
8324 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8325 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8326 status
= WERR_ACCESS_DENIED
;
8330 /* can't add if builtin */
8332 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8333 status
= WERR_ALREADY_EXISTS
;
8337 count
= get_ntforms(&list
);
8339 if(!add_a_form(&list
, form
, &count
)) {
8340 status
= WERR_NOMEM
;
8344 write_ntforms(&list
, count
);
8347 * ChangeID must always be set if this is a printer
8350 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8351 status
= mod_a_printer(printer
, 2);
8355 free_a_printer(&printer
, 2);
8361 /****************************************************************************
8362 ****************************************************************************/
8364 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
8366 POLICY_HND
*handle
= &q_u
->handle
;
8367 UNISTR2
*form_name
= &q_u
->name
;
8368 nt_forms_struct tmpForm
;
8370 nt_forms_struct
*list
=NULL
;
8371 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8373 WERROR status
= WERR_OK
;
8374 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8376 DEBUG(5,("spoolss_deleteform\n"));
8379 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8383 /* forms can be deleted on printer of on the print server handle */
8385 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8387 if (!get_printer_snum(p
,handle
, &snum
))
8390 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8391 if (!W_ERROR_IS_OK(status
))
8395 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8396 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8397 status
= WERR_ACCESS_DENIED
;
8401 /* can't delete if builtin */
8403 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
8404 status
= WERR_INVALID_PARAM
;
8408 count
= get_ntforms(&list
);
8410 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8414 * ChangeID must always be set if this is a printer
8417 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8418 status
= mod_a_printer(printer
, 2);
8422 free_a_printer(&printer
, 2);
8428 /****************************************************************************
8429 ****************************************************************************/
8431 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8433 POLICY_HND
*handle
= &q_u
->handle
;
8434 FORM
*form
= &q_u
->form
;
8435 nt_forms_struct tmpForm
;
8437 WERROR status
= WERR_OK
;
8438 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8441 nt_forms_struct
*list
=NULL
;
8442 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8444 DEBUG(5,("spoolss_setform\n"));
8447 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8451 /* forms can be modified on printer of on the print server handle */
8453 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8455 if (!get_printer_snum(p
,handle
, &snum
))
8458 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8459 if (!W_ERROR_IS_OK(status
))
8463 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8464 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8465 status
= WERR_ACCESS_DENIED
;
8469 /* can't set if builtin */
8470 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8471 status
= WERR_INVALID_PARAM
;
8475 count
= get_ntforms(&list
);
8476 update_a_form(&list
, form
, count
);
8477 write_ntforms(&list
, count
);
8480 * ChangeID must always be set if this is a printer
8483 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8484 status
= mod_a_printer(printer
, 2);
8489 free_a_printer(&printer
, 2);
8495 /****************************************************************************
8496 enumprintprocessors level 1.
8497 ****************************************************************************/
8499 static WERROR
enumprintprocessors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8501 PRINTPROCESSOR_1
*info_1
=NULL
;
8502 WERROR result
= WERR_OK
;
8504 if((info_1
= SMB_MALLOC_P(PRINTPROCESSOR_1
)) == NULL
)
8509 init_unistr(&info_1
->name
, "winprint");
8511 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8513 if (*needed
> offered
) {
8514 result
= WERR_INSUFFICIENT_BUFFER
;
8518 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8519 result
= WERR_NOMEM
;
8523 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8528 if ( !W_ERROR_IS_OK(result
) )
8534 /****************************************************************************
8535 ****************************************************************************/
8537 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8539 uint32 level
= q_u
->level
;
8540 RPC_BUFFER
*buffer
= NULL
;
8541 uint32 offered
= q_u
->offered
;
8542 uint32
*needed
= &r_u
->needed
;
8543 uint32
*returned
= &r_u
->returned
;
8545 /* that's an [in out] buffer */
8547 if (!q_u
->buffer
&& (offered
!=0)) {
8548 return WERR_INVALID_PARAM
;
8551 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8552 buffer
= r_u
->buffer
;
8554 DEBUG(5,("spoolss_enumprintprocessors\n"));
8557 * Enumerate the print processors ...
8559 * Just reply with "winprint", to keep NT happy
8560 * and I can use my nice printer checker.
8568 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8570 return WERR_UNKNOWN_LEVEL
;
8574 /****************************************************************************
8575 enumprintprocdatatypes level 1.
8576 ****************************************************************************/
8578 static WERROR
enumprintprocdatatypes_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8580 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8581 WERROR result
= WERR_OK
;
8583 if((info_1
= SMB_MALLOC_P(PRINTPROCDATATYPE_1
)) == NULL
)
8588 init_unistr(&info_1
->name
, "RAW");
8590 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8592 if (*needed
> offered
) {
8593 result
= WERR_INSUFFICIENT_BUFFER
;
8597 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8598 result
= WERR_NOMEM
;
8602 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8607 if ( !W_ERROR_IS_OK(result
) )
8613 /****************************************************************************
8614 ****************************************************************************/
8616 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8618 uint32 level
= q_u
->level
;
8619 RPC_BUFFER
*buffer
= NULL
;
8620 uint32 offered
= q_u
->offered
;
8621 uint32
*needed
= &r_u
->needed
;
8622 uint32
*returned
= &r_u
->returned
;
8624 /* that's an [in out] buffer */
8626 if (!q_u
->buffer
&& (offered
!=0)) {
8627 return WERR_INVALID_PARAM
;
8630 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8631 buffer
= r_u
->buffer
;
8633 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8640 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8642 return WERR_UNKNOWN_LEVEL
;
8646 /****************************************************************************
8647 enumprintmonitors level 1.
8648 ****************************************************************************/
8650 static WERROR
enumprintmonitors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8652 PRINTMONITOR_1
*info_1
;
8653 WERROR result
= WERR_OK
;
8656 if((info_1
= SMB_MALLOC_ARRAY(PRINTMONITOR_1
, 2)) == NULL
)
8661 init_unistr(&(info_1
[0].name
), SPL_LOCAL_PORT
);
8662 init_unistr(&(info_1
[1].name
), SPL_TCPIP_PORT
);
8664 for ( i
=0; i
<*returned
; i
++ ) {
8665 *needed
+= spoolss_size_printmonitor_info_1(&info_1
[i
]);
8668 if (*needed
> offered
) {
8669 result
= WERR_INSUFFICIENT_BUFFER
;
8673 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8674 result
= WERR_NOMEM
;
8678 for ( i
=0; i
<*returned
; i
++ ) {
8679 smb_io_printmonitor_info_1("", buffer
, &info_1
[i
], 0);
8685 if ( !W_ERROR_IS_OK(result
) )
8691 /****************************************************************************
8692 enumprintmonitors level 2.
8693 ****************************************************************************/
8695 static WERROR
enumprintmonitors_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8697 PRINTMONITOR_2
*info_2
;
8698 WERROR result
= WERR_OK
;
8701 if((info_2
= SMB_MALLOC_ARRAY(PRINTMONITOR_2
, 2)) == NULL
)
8706 init_unistr( &(info_2
[0].name
), SPL_LOCAL_PORT
);
8707 init_unistr( &(info_2
[0].environment
), "Windows NT X86" );
8708 init_unistr( &(info_2
[0].dll_name
), "localmon.dll" );
8710 init_unistr( &(info_2
[1].name
), SPL_TCPIP_PORT
);
8711 init_unistr( &(info_2
[1].environment
), "Windows NT X86" );
8712 init_unistr( &(info_2
[1].dll_name
), "tcpmon.dll" );
8714 for ( i
=0; i
<*returned
; i
++ ) {
8715 *needed
+= spoolss_size_printmonitor_info_2(&info_2
[i
]);
8718 if (*needed
> offered
) {
8719 result
= WERR_INSUFFICIENT_BUFFER
;
8723 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8724 result
= WERR_NOMEM
;
8728 for ( i
=0; i
<*returned
; i
++ ) {
8729 smb_io_printmonitor_info_2("", buffer
, &info_2
[i
], 0);
8735 if ( !W_ERROR_IS_OK(result
) )
8741 /****************************************************************************
8742 ****************************************************************************/
8744 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8746 uint32 level
= q_u
->level
;
8747 RPC_BUFFER
*buffer
= NULL
;
8748 uint32 offered
= q_u
->offered
;
8749 uint32
*needed
= &r_u
->needed
;
8750 uint32
*returned
= &r_u
->returned
;
8752 /* that's an [in out] buffer */
8754 if (!q_u
->buffer
&& (offered
!=0)) {
8755 return WERR_INVALID_PARAM
;
8758 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8759 buffer
= r_u
->buffer
;
8761 DEBUG(5,("spoolss_enumprintmonitors\n"));
8764 * Enumerate the print monitors ...
8766 * Just reply with "Local Port", to keep NT happy
8767 * and I can use my nice printer checker.
8775 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8777 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8779 return WERR_UNKNOWN_LEVEL
;
8783 /****************************************************************************
8784 ****************************************************************************/
8786 static WERROR
getjob_level_1(print_queue_struct
**queue
, int count
, int snum
,
8787 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8788 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8793 JOB_INFO_1
*info_1
=NULL
;
8794 WERROR result
= WERR_OK
;
8796 info_1
=SMB_MALLOC_P(JOB_INFO_1
);
8798 if (info_1
== NULL
) {
8802 for (i
=0; i
<count
&& found
==False
; i
++) {
8803 if ((*queue
)[i
].job
==(int)jobid
)
8809 /* NT treats not found as bad param... yet another bad choice */
8810 return WERR_INVALID_PARAM
;
8813 fill_job_info_1( info_1
, &((*queue
)[i
-1]), i
, snum
, ntprinter
);
8815 *needed
+= spoolss_size_job_info_1(info_1
);
8817 if (*needed
> offered
) {
8818 result
= WERR_INSUFFICIENT_BUFFER
;
8822 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8823 result
= WERR_NOMEM
;
8827 smb_io_job_info_1("", buffer
, info_1
, 0);
8835 /****************************************************************************
8836 ****************************************************************************/
8838 static WERROR
getjob_level_2(print_queue_struct
**queue
, int count
, int snum
,
8839 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8840 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8847 DEVICEMODE
*devmode
= NULL
;
8848 NT_DEVICEMODE
*nt_devmode
= NULL
;
8850 if ( !(info_2
=SMB_MALLOC_P(JOB_INFO_2
)) )
8853 ZERO_STRUCTP(info_2
);
8855 for ( i
=0; i
<count
&& found
==False
; i
++ )
8857 if ((*queue
)[i
].job
== (int)jobid
)
8862 /* NT treats not found as bad param... yet another bad
8864 result
= WERR_INVALID_PARAM
;
8869 * if the print job does not have a DEVMODE associated with it,
8870 * just use the one for the printer. A NULL devicemode is not
8871 * a failure condition
8874 if ( !(nt_devmode
=print_job_devmode( lp_const_servicename(snum
), jobid
)) )
8875 devmode
= construct_dev_mode(lp_const_servicename(snum
));
8877 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) != NULL
) {
8878 ZERO_STRUCTP( devmode
);
8879 convert_nt_devicemode( devmode
, nt_devmode
);
8883 fill_job_info_2(info_2
, &((*queue
)[i
-1]), i
, snum
, ntprinter
, devmode
);
8885 *needed
+= spoolss_size_job_info_2(info_2
);
8887 if (*needed
> offered
) {
8888 result
= WERR_INSUFFICIENT_BUFFER
;
8892 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8893 result
= WERR_NOMEM
;
8897 smb_io_job_info_2("", buffer
, info_2
, 0);
8902 /* Cleanup allocated memory */
8904 free_job_info_2(info_2
); /* Also frees devmode */
8910 /****************************************************************************
8911 ****************************************************************************/
8913 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8915 POLICY_HND
*handle
= &q_u
->handle
;
8916 uint32 jobid
= q_u
->jobid
;
8917 uint32 level
= q_u
->level
;
8918 RPC_BUFFER
*buffer
= NULL
;
8919 uint32 offered
= q_u
->offered
;
8920 uint32
*needed
= &r_u
->needed
;
8921 WERROR wstatus
= WERR_OK
;
8922 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8925 print_queue_struct
*queue
= NULL
;
8926 print_status_struct prt_status
;
8928 /* that's an [in out] buffer */
8930 if (!q_u
->buffer
&& (offered
!=0)) {
8931 return WERR_INVALID_PARAM
;
8934 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8935 buffer
= r_u
->buffer
;
8937 DEBUG(5,("spoolss_getjob\n"));
8941 if (!get_printer_snum(p
, handle
, &snum
))
8944 wstatus
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8945 if ( !W_ERROR_IS_OK(wstatus
) )
8948 count
= print_queue_status(snum
, &queue
, &prt_status
);
8950 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8951 count
, prt_status
.status
, prt_status
.message
));
8955 wstatus
= getjob_level_1(&queue
, count
, snum
, ntprinter
, jobid
,
8956 buffer
, offered
, needed
);
8959 wstatus
= getjob_level_2(&queue
, count
, snum
, ntprinter
, jobid
,
8960 buffer
, offered
, needed
);
8963 wstatus
= WERR_UNKNOWN_LEVEL
;
8968 free_a_printer( &ntprinter
, 2 );
8973 /********************************************************************
8974 spoolss_getprinterdataex
8976 From MSDN documentation of GetPrinterDataEx: pass request
8977 to GetPrinterData if key is "PrinterDriverData".
8978 ********************************************************************/
8980 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
8982 POLICY_HND
*handle
= &q_u
->handle
;
8983 uint32 in_size
= q_u
->size
;
8984 uint32
*type
= &r_u
->type
;
8985 uint32
*out_size
= &r_u
->size
;
8986 uint8
**data
= &r_u
->data
;
8987 uint32
*needed
= &r_u
->needed
;
8988 fstring keyname
, valuename
;
8990 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8992 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8994 WERROR status
= WERR_OK
;
8996 DEBUG(4,("_spoolss_getprinterdataex\n"));
8998 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
8999 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
9001 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9002 keyname
, valuename
));
9004 /* in case of problem, return some default values */
9008 *out_size
= in_size
;
9011 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9012 status
= WERR_BADFID
;
9016 /* Is the handle to a printer or to the server? */
9018 if (Printer
->printer_type
== SPLHND_SERVER
) {
9019 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9020 status
= WERR_INVALID_PARAM
;
9024 if ( !get_printer_snum(p
,handle
, &snum
) )
9027 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9028 if ( !W_ERROR_IS_OK(status
) )
9031 /* check to see if the keyname is valid */
9032 if ( !strlen(keyname
) ) {
9033 status
= WERR_INVALID_PARAM
;
9037 if ( lookup_printerkey( printer
->info_2
->data
, keyname
) == -1 ) {
9038 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
9039 free_a_printer( &printer
, 2 );
9040 status
= WERR_BADFILE
;
9044 /* When given a new keyname, we should just create it */
9046 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
9048 if (*needed
> *out_size
)
9049 status
= WERR_MORE_DATA
;
9052 if ( !W_ERROR_IS_OK(status
) )
9054 DEBUG(5, ("error: allocating %d\n", *out_size
));
9056 /* reply this param doesn't exist */
9060 if( (*data
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
9061 status
= WERR_NOMEM
;
9070 free_a_printer( &printer
, 2 );
9075 /********************************************************************
9076 * spoolss_setprinterdataex
9077 ********************************************************************/
9079 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
9081 POLICY_HND
*handle
= &q_u
->handle
;
9082 uint32 type
= q_u
->type
;
9083 uint8
*data
= q_u
->data
;
9084 uint32 real_len
= q_u
->real_len
;
9086 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9088 WERROR status
= WERR_OK
;
9089 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9094 DEBUG(4,("_spoolss_setprinterdataex\n"));
9096 /* From MSDN documentation of SetPrinterDataEx: pass request to
9097 SetPrinterData if key is "PrinterDriverData" */
9100 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9104 if ( Printer
->printer_type
== SPLHND_SERVER
) {
9105 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9106 return WERR_INVALID_PARAM
;
9109 if ( !get_printer_snum(p
,handle
, &snum
) )
9113 * Access check : NT returns "access denied" if you make a
9114 * SetPrinterData call without the necessary privildge.
9115 * we were originally returning OK if nothing changed
9116 * which made Win2k issue **a lot** of SetPrinterData
9117 * when connecting to a printer --jerry
9120 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
9122 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9123 return WERR_ACCESS_DENIED
;
9126 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9127 if (!W_ERROR_IS_OK(status
))
9130 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
9131 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
9133 /* check for OID in valuename */
9135 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
9141 /* save the registry data */
9143 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
9145 if ( W_ERROR_IS_OK(status
) )
9147 /* save the OID if one was specified */
9149 fstrcat( keyname
, "\\" );
9150 fstrcat( keyname
, SPOOL_OID_KEY
);
9153 * I'm not checking the status here on purpose. Don't know
9154 * if this is right, but I'm returning the status from the
9155 * previous set_printer_dataex() call. I have no idea if
9156 * this is right. --jerry
9159 set_printer_dataex( printer
, keyname
, valuename
,
9160 REG_SZ
, (void*)oid_string
, strlen(oid_string
)+1 );
9163 status
= mod_a_printer(printer
, 2);
9166 free_a_printer(&printer
, 2);
9172 /********************************************************************
9173 * spoolss_deleteprinterdataex
9174 ********************************************************************/
9176 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
9178 POLICY_HND
*handle
= &q_u
->handle
;
9179 UNISTR2
*value
= &q_u
->valuename
;
9180 UNISTR2
*key
= &q_u
->keyname
;
9182 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9184 WERROR status
= WERR_OK
;
9185 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
9186 pstring valuename
, keyname
;
9188 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9191 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9195 if (!get_printer_snum(p
, handle
, &snum
))
9198 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9199 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9200 return WERR_ACCESS_DENIED
;
9203 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9204 if (!W_ERROR_IS_OK(status
))
9207 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
9208 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
9210 status
= delete_printer_dataex( printer
, keyname
, valuename
);
9212 if ( W_ERROR_IS_OK(status
) )
9213 mod_a_printer( printer
, 2 );
9215 free_a_printer(&printer
, 2);
9220 /********************************************************************
9221 * spoolss_enumprinterkey
9222 ********************************************************************/
9225 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
9228 fstring
*keynames
= NULL
;
9229 uint16
*enumkeys
= NULL
;
9232 POLICY_HND
*handle
= &q_u
->handle
;
9233 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9234 NT_PRINTER_DATA
*data
;
9235 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9237 WERROR status
= WERR_BADFILE
;
9240 DEBUG(4,("_spoolss_enumprinterkey\n"));
9243 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9247 if ( !get_printer_snum(p
,handle
, &snum
) )
9250 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9251 if (!W_ERROR_IS_OK(status
))
9254 /* get the list of subkey names */
9256 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
9257 data
= printer
->info_2
->data
;
9259 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
9261 if ( num_keys
== -1 ) {
9262 status
= WERR_BADFILE
;
9266 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
9268 r_u
->needed
= printerkey_len
*2;
9270 if ( q_u
->size
< r_u
->needed
) {
9271 status
= WERR_MORE_DATA
;
9275 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
9276 status
= WERR_NOMEM
;
9282 if ( q_u
->size
< r_u
->needed
)
9283 status
= WERR_MORE_DATA
;
9286 free_a_printer( &printer
, 2 );
9287 SAFE_FREE( keynames
);
9292 /********************************************************************
9293 * spoolss_deleteprinterkey
9294 ********************************************************************/
9296 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
9298 POLICY_HND
*handle
= &q_u
->handle
;
9299 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9301 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9305 DEBUG(5,("spoolss_deleteprinterkey\n"));
9308 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9312 /* if keyname == NULL, return error */
9314 if ( !q_u
->keyname
.buffer
)
9315 return WERR_INVALID_PARAM
;
9317 if (!get_printer_snum(p
, handle
, &snum
))
9320 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9321 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9322 return WERR_ACCESS_DENIED
;
9325 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9326 if (!W_ERROR_IS_OK(status
))
9329 /* delete the key and all subneys */
9331 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
9333 status
= delete_all_printer_data( printer
->info_2
, key
);
9335 if ( W_ERROR_IS_OK(status
) )
9336 status
= mod_a_printer(printer
, 2);
9338 free_a_printer( &printer
, 2 );
9344 /********************************************************************
9345 * spoolss_enumprinterdataex
9346 ********************************************************************/
9348 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9350 POLICY_HND
*handle
= &q_u
->handle
;
9351 uint32 in_size
= q_u
->size
;
9354 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9355 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9356 NT_PRINTER_DATA
*p_data
;
9358 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9363 REGISTRY_VALUE
*val
;
9368 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9371 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9376 * first check for a keyname of NULL or "". Win2k seems to send
9377 * this a lot and we should send back WERR_INVALID_PARAM
9378 * no need to spend time looking up the printer in this case.
9382 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9383 if ( !strlen(key
) ) {
9384 result
= WERR_INVALID_PARAM
;
9388 /* get the printer off of disk */
9390 if (!get_printer_snum(p
,handle
, &snum
))
9393 ZERO_STRUCT(printer
);
9394 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9395 if (!W_ERROR_IS_OK(result
))
9398 /* now look for a match on the key name */
9400 p_data
= printer
->info_2
->data
;
9402 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9403 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9405 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9406 result
= WERR_INVALID_PARAM
;
9413 /* allocate the memory for the array of pointers -- if necessary */
9415 num_entries
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
9418 if ( (enum_values
=TALLOC_ARRAY(p
->mem_ctx
, PRINTER_ENUM_VALUES
, num_entries
)) == NULL
)
9420 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9421 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9422 result
= WERR_NOMEM
;
9426 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9430 * loop through all params and build the array to pass
9431 * back to the client
9434 for ( i
=0; i
<num_entries
; i
++ )
9436 /* lookup the registry value */
9438 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
9439 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9443 value_name
= regval_name( val
);
9444 init_unistr( &enum_values
[i
].valuename
, value_name
);
9445 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9446 enum_values
[i
].type
= regval_type( val
);
9448 data_len
= regval_size( val
);
9450 if ( !(enum_values
[i
].data
= TALLOC_MEMDUP(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9452 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9454 result
= WERR_NOMEM
;
9458 enum_values
[i
].data_len
= data_len
;
9460 /* keep track of the size of the array in bytes */
9462 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9465 /* housekeeping information in the reply */
9467 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9468 * the hand marshalled container size is a multiple
9469 * of 4 bytes for RPC alignment.
9473 needed
+= 4-(needed
% 4);
9476 r_u
->needed
= needed
;
9477 r_u
->returned
= num_entries
;
9479 if (needed
> in_size
) {
9480 result
= WERR_MORE_DATA
;
9484 /* copy data into the reply */
9486 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9487 response buffer size is != the offered buffer size
9489 r_u->ctr.size = r_u->needed;
9491 r_u
->ctr
.size
= in_size
;
9493 r_u
->ctr
.size_of_array
= r_u
->returned
;
9494 r_u
->ctr
.values
= enum_values
;
9500 free_a_printer(&printer
, 2);
9505 /****************************************************************************
9506 ****************************************************************************/
9508 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9510 init_unistr(&info
->name
, name
);
9513 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9514 UNISTR2
*environment
,
9521 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9522 WERROR result
= WERR_OK
;
9524 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9526 if (!get_short_archi(long_archi
))
9527 return WERR_INVALID_ENVIRONMENT
;
9529 if((info
=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1
)) == NULL
)
9532 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9534 fill_printprocessordirectory_1(info
, path
);
9536 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9538 if (*needed
> offered
) {
9539 result
= WERR_INSUFFICIENT_BUFFER
;
9543 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
9544 result
= WERR_INSUFFICIENT_BUFFER
;
9548 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9556 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9558 uint32 level
= q_u
->level
;
9559 RPC_BUFFER
*buffer
= NULL
;
9560 uint32 offered
= q_u
->offered
;
9561 uint32
*needed
= &r_u
->needed
;
9564 /* that's an [in out] buffer */
9566 if (!q_u
->buffer
&& (offered
!=0)) {
9567 return WERR_INVALID_PARAM
;
9570 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
9571 buffer
= r_u
->buffer
;
9573 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9579 result
= getprintprocessordirectory_level_1
9580 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9583 result
= WERR_UNKNOWN_LEVEL
;
9589 /*******************************************************************
9590 Streams the monitor UI DLL name in UNICODE
9591 *******************************************************************/
9593 static WERROR
xcvtcp_monitorui( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9594 RPC_BUFFER
*out
, uint32
*needed
)
9596 const char *dllname
= "tcpmonui.dll";
9598 *needed
= (strlen(dllname
)+1) * 2;
9600 if ( rpcbuf_get_size(out
) < *needed
) {
9601 return WERR_INSUFFICIENT_BUFFER
;
9604 if ( !make_monitorui_buf( out
, dllname
) ) {
9611 /*******************************************************************
9612 Create a new TCP/IP port
9613 *******************************************************************/
9615 static WERROR
xcvtcp_addport( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9616 RPC_BUFFER
*out
, uint32
*needed
)
9618 NT_PORT_DATA_1 port1
;
9621 ZERO_STRUCT( port1
);
9623 /* convert to our internal port data structure */
9625 if ( !convert_port_data_1( &port1
, in
) ) {
9629 /* create the device URI and call the add_port_hook() */
9631 switch ( port1
.protocol
) {
9632 case PORT_PROTOCOL_DIRECT
:
9633 pstr_sprintf( device_uri
, "socket://%s:%d/", port1
.hostaddr
, port1
.port
);
9636 case PORT_PROTOCOL_LPR
:
9637 pstr_sprintf( device_uri
, "lpr://%s/%s", port1
.hostaddr
, port1
.queue
);
9641 return WERR_UNKNOWN_PORT
;
9644 return add_port_hook( token
, port1
.name
, device_uri
);
9647 /*******************************************************************
9648 *******************************************************************/
9650 struct xcv_api_table xcvtcp_cmds
[] = {
9651 { "MonitorUI", xcvtcp_monitorui
},
9652 { "AddPort", xcvtcp_addport
},
9656 static WERROR
process_xcvtcp_command( NT_USER_TOKEN
*token
, const char *command
,
9657 RPC_BUFFER
*inbuf
, RPC_BUFFER
*outbuf
,
9662 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9664 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9665 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9666 return xcvtcp_cmds
[i
].fn( token
, inbuf
, outbuf
, needed
);
9669 return WERR_BADFUNC
;
9672 /*******************************************************************
9673 *******************************************************************/
9674 #if 0 /* don't support management using the "Local Port" monitor */
9676 static WERROR
xcvlocal_monitorui( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9677 RPC_BUFFER
*out
, uint32
*needed
)
9679 const char *dllname
= "localui.dll";
9681 *needed
= (strlen(dllname
)+1) * 2;
9683 if ( rpcbuf_get_size(out
) < *needed
) {
9684 return WERR_INSUFFICIENT_BUFFER
;
9687 if ( !make_monitorui_buf( out
, dllname
)) {
9694 /*******************************************************************
9695 *******************************************************************/
9697 struct xcv_api_table xcvlocal_cmds
[] = {
9698 { "MonitorUI", xcvlocal_monitorui
},
9702 struct xcv_api_table xcvlocal_cmds
[] = {
9709 /*******************************************************************
9710 *******************************************************************/
9712 static WERROR
process_xcvlocal_command( NT_USER_TOKEN
*token
, const char *command
,
9713 RPC_BUFFER
*inbuf
, RPC_BUFFER
*outbuf
,
9718 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9720 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9721 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9722 return xcvlocal_cmds
[i
].fn( token
, inbuf
, outbuf
, needed
);
9724 return WERR_BADFUNC
;
9727 /*******************************************************************
9728 *******************************************************************/
9730 WERROR
_spoolss_xcvdataport(pipes_struct
*p
, SPOOL_Q_XCVDATAPORT
*q_u
, SPOOL_R_XCVDATAPORT
*r_u
)
9732 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9736 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u
->handle
)));
9740 /* Has to be a handle to the TCP/IP port monitor */
9742 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9743 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9747 /* requires administrative access to the server */
9749 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9750 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9751 return WERR_ACCESS_DENIED
;
9754 /* Get the command name. There's numerous commands supported by the
9755 TCPMON interface. */
9757 rpcstr_pull(command
, q_u
->dataname
.buffer
, sizeof(command
),
9758 q_u
->dataname
.uni_str_len
*2, 0);
9760 /* Allocate the outgoing buffer */
9762 rpcbuf_init( &r_u
->outdata
, q_u
->offered
, p
->mem_ctx
);
9764 switch ( Printer
->printer_type
) {
9765 case SPLHND_PORTMON_TCP
:
9766 return process_xcvtcp_command( p
->pipe_user
.nt_user_token
, command
,
9767 &q_u
->indata
, &r_u
->outdata
, &r_u
->needed
);
9768 case SPLHND_PORTMON_LOCAL
:
9769 return process_xcvlocal_command( p
->pipe_user
.nt_user_token
, command
,
9770 &q_u
->indata
, &r_u
->outdata
, &r_u
->needed
);
9773 return WERR_INVALID_PRINT_MONITOR
;