2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
31 extern userdom_struct current_user_info
;
34 #define DBGC_CLASS DBGC_RPC_SRV
36 #ifndef MAX_OPEN_PRINTER_EXS
37 #define MAX_OPEN_PRINTER_EXS 50
40 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
41 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
44 const char *long_archi
;
45 const char *short_archi
;
49 static Printer_entry
*printers_list
;
51 typedef struct _counter_printer_0
{
52 struct _counter_printer_0
*next
;
53 struct _counter_printer_0
*prev
;
59 static counter_printer_0
*counter_list
;
61 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
62 static uint32 smb_connections
=0;
65 /* in printing/nt_printing.c */
67 extern STANDARD_MAPPING printer_std_mapping
, printserver_std_mapping
;
69 /* API table for Xcv Monitor functions */
71 struct xcv_api_table
{
73 WERROR(*fn
) (NT_USER_TOKEN
*token
, RPC_BUFFER
*in
, RPC_BUFFER
*out
, uint32
*needed
);
77 /* translate between internal status numbers and NT status numbers */
78 static int nt_printj_status(int v
)
84 return JOB_STATUS_PAUSED
;
86 return JOB_STATUS_SPOOLING
;
88 return JOB_STATUS_PRINTING
;
90 return JOB_STATUS_ERROR
;
92 return JOB_STATUS_DELETING
;
94 return JOB_STATUS_OFFLINE
;
96 return JOB_STATUS_PAPEROUT
;
98 return JOB_STATUS_PRINTED
;
100 return JOB_STATUS_DELETED
;
102 return JOB_STATUS_BLOCKED
;
103 case LPQ_USER_INTERVENTION
:
104 return JOB_STATUS_USER_INTERVENTION
;
109 static int nt_printq_status(int v
)
113 return PRINTER_STATUS_PAUSED
;
122 /****************************************************************************
123 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
124 ****************************************************************************/
126 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION
**pp
)
131 SAFE_FREE((*pp
)->ctr
.type
);
135 /***************************************************************************
136 Disconnect from the client
137 ****************************************************************************/
139 static void srv_spoolss_replycloseprinter(int snum
, POLICY_HND
*handle
)
144 * Tell the specific printing tdb we no longer want messages for this printer
145 * by deregistering our PID.
148 if (!print_notify_deregister_pid(snum
))
149 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
151 /* weird if the test succeds !!! */
152 if (smb_connections
==0) {
153 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
157 result
= rpccli_spoolss_reply_close_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, handle
);
159 if (!W_ERROR_IS_OK(result
))
160 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
161 dos_errstr(result
)));
163 /* if it's the last connection, deconnect the IPC$ share */
164 if (smb_connections
==1) {
166 cli_shutdown( notify_cli_pipe
->cli
);
167 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
169 message_deregister(MSG_PRINTER_NOTIFY2
);
171 /* Tell the connections db we're no longer interested in
172 * printer notify messages. */
174 register_message_flags( False
, FLAG_MSG_PRINT_NOTIFY
);
180 /****************************************************************************
181 Functions to free a printer entry datastruct.
182 ****************************************************************************/
184 static void free_printer_entry(void *ptr
)
186 Printer_entry
*Printer
= (Printer_entry
*)ptr
;
188 if (Printer
->notify
.client_connected
==True
) {
191 if ( Printer
->printer_type
== SPLHND_SERVER
) {
193 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
194 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
195 snum
= print_queue_snum(Printer
->sharename
);
197 srv_spoolss_replycloseprinter(snum
,
198 &Printer
->notify
.client_hnd
);
202 Printer
->notify
.flags
=0;
203 Printer
->notify
.options
=0;
204 Printer
->notify
.localmachine
[0]='\0';
205 Printer
->notify
.printerlocal
=0;
206 free_spool_notify_option(&Printer
->notify
.option
);
207 Printer
->notify
.option
=NULL
;
208 Printer
->notify
.client_connected
=False
;
210 free_nt_devicemode( &Printer
->nt_devmode
);
211 free_a_printer( &Printer
->printer_info
, 2 );
213 talloc_destroy( Printer
->ctx
);
215 /* Remove from the internal list. */
216 DLIST_REMOVE(printers_list
, Printer
);
221 /****************************************************************************
222 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
223 ****************************************************************************/
225 static SPOOL_NOTIFY_OPTION
*dup_spool_notify_option(SPOOL_NOTIFY_OPTION
*sp
)
227 SPOOL_NOTIFY_OPTION
*new_sp
= NULL
;
232 new_sp
= SMB_MALLOC_P(SPOOL_NOTIFY_OPTION
);
239 new_sp
->ctr
.type
= (SPOOL_NOTIFY_OPTION_TYPE
*)memdup(sp
->ctr
.type
, sizeof(SPOOL_NOTIFY_OPTION_TYPE
) * sp
->ctr
.count
);
241 if (!new_sp
->ctr
.type
) {
250 /****************************************************************************
251 find printer index by handle
252 ****************************************************************************/
254 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
, POLICY_HND
*hnd
)
256 Printer_entry
*find_printer
= NULL
;
258 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
259 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
266 /****************************************************************************
267 Close printer index by handle.
268 ****************************************************************************/
270 static BOOL
close_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
272 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
275 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
279 close_policy_hnd(p
, hnd
);
284 /****************************************************************************
285 Delete a printer given a handle.
286 ****************************************************************************/
287 WERROR
delete_printer_hook( NT_USER_TOKEN
*token
, const char *sharename
)
289 char *cmd
= lp_deleteprinter_cmd();
292 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
293 BOOL is_print_op
= False
;
295 /* can't fail if we don't try */
300 pstr_sprintf(command
, "%s \"%s\"", cmd
, sharename
);
303 is_print_op
= user_has_privileges( token
, &se_printop
);
305 DEBUG(10,("Running [%s]\n", command
));
307 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
312 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
313 /* Tell everyone we updated smb.conf. */
314 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
320 /********** END SePrintOperatorPrivlege BLOCK **********/
322 DEBUGADD(10,("returned [%d]\n", ret
));
325 return WERR_BADFID
; /* What to return here? */
327 /* go ahead and re-read the services immediately */
328 reload_services( False
);
330 if ( share_defined( sharename
) )
331 return WERR_ACCESS_DENIED
;
336 /****************************************************************************
337 Delete a printer given a handle.
338 ****************************************************************************/
340 static WERROR
delete_printer_handle(pipes_struct
*p
, POLICY_HND
*hnd
)
342 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
345 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
350 * It turns out that Windows allows delete printer on a handle
351 * opened by an admin user, then used on a pipe handle created
352 * by an anonymous user..... but they're working on security.... riiight !
356 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
357 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
358 return WERR_ACCESS_DENIED
;
361 /* this does not need a become root since the access check has been
362 done on the handle already */
364 if (del_a_printer( Printer
->sharename
) != 0) {
365 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
369 return delete_printer_hook( p
->pipe_user
.nt_user_token
, Printer
->sharename
);
372 /****************************************************************************
373 Return the snum of a printer corresponding to an handle.
374 ****************************************************************************/
376 static BOOL
get_printer_snum(pipes_struct
*p
, POLICY_HND
*hnd
, int *number
,
377 struct share_params
**params
)
379 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
382 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd
)));
386 switch (Printer
->printer_type
) {
388 DEBUG(4,("short name:%s\n", Printer
->sharename
));
389 *number
= print_queue_snum(Printer
->sharename
);
390 if ((*number
!= -1) && (params
!= NULL
)) {
391 *params
= get_share_params(tmp_talloc_ctx(),
393 if (*params
== NULL
) {
397 return (*number
!= -1);
405 /****************************************************************************
406 Set printer handle type.
407 Check if it's \\server or \\server\printer
408 ****************************************************************************/
410 static BOOL
set_printer_hnd_printertype(Printer_entry
*Printer
, char *handlename
)
412 DEBUG(3,("Setting printer type=%s\n", handlename
));
414 if ( strlen(handlename
) < 3 ) {
415 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
419 /* it's a print server */
420 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
421 DEBUGADD(4,("Printer is a print server\n"));
422 Printer
->printer_type
= SPLHND_SERVER
;
424 /* it's a printer (set_printer_hnd_name() will handle port monitors */
426 DEBUGADD(4,("Printer is a printer\n"));
427 Printer
->printer_type
= SPLHND_PRINTER
;
433 /****************************************************************************
434 Set printer handle name.. Accept names like \\server, \\server\printer,
435 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
436 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
437 XcvDataPort() interface.
438 ****************************************************************************/
440 static BOOL
set_printer_hnd_name(Printer_entry
*Printer
, char *handlename
)
443 int n_services
=lp_numservices();
444 char *aprinter
, *printername
;
445 const char *servername
;
448 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
451 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
, (unsigned long)strlen(handlename
)));
453 aprinter
= handlename
;
454 if ( *handlename
== '\\' ) {
455 servername
= handlename
+ 2;
456 if ( (aprinter
= strchr_m( handlename
+2, '\\' )) != NULL
) {
465 /* save the servername to fill in replies on this handle */
467 if ( !is_myname_or_ipaddr( servername
) )
470 fstrcpy( Printer
->servername
, servername
);
472 if ( Printer
->printer_type
== SPLHND_SERVER
)
475 if ( Printer
->printer_type
!= SPLHND_PRINTER
)
478 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
480 /* check for the Port Monitor Interface */
482 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
483 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
484 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
487 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
488 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
489 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
493 /* Search all sharenames first as this is easier than pulling
494 the printer_info_2 off of disk. Don't use find_service() since
495 that calls out to map_username() */
497 /* do another loop to look for printernames */
499 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
501 /* no point going on if this is not a printer */
503 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
506 fstrcpy(sname
, lp_servicename(snum
));
507 if ( strequal( aprinter
, sname
) ) {
512 /* no point looking up the printer object if
513 we aren't allowing printername != sharename */
515 if ( lp_force_printername(snum
) )
518 fstrcpy(sname
, lp_servicename(snum
));
521 result
= get_a_printer( NULL
, &printer
, 2, sname
);
522 if ( !W_ERROR_IS_OK(result
) ) {
523 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
524 sname
, dos_errstr(result
)));
528 /* printername is always returned as \\server\printername */
529 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
530 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
531 printer
->info_2
->printername
));
532 free_a_printer( &printer
, 2);
538 if ( strequal(printername
, aprinter
) ) {
539 free_a_printer( &printer
, 2);
544 DEBUGADD(10, ("printername: %s\n", printername
));
546 free_a_printer( &printer
, 2);
549 free_a_printer( &printer
, 2);
552 DEBUGADD(4,("Printer not found\n"));
556 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
558 fstrcpy(Printer
->sharename
, sname
);
563 /****************************************************************************
564 Find first available printer slot. creates a printer handle for you.
565 ****************************************************************************/
567 static BOOL
open_printer_hnd(pipes_struct
*p
, POLICY_HND
*hnd
, char *name
, uint32 access_granted
)
569 Printer_entry
*new_printer
;
571 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
573 if((new_printer
=SMB_MALLOC_P(Printer_entry
)) == NULL
)
576 ZERO_STRUCTP(new_printer
);
578 if (!create_policy_hnd(p
, hnd
, free_printer_entry
, new_printer
)) {
579 SAFE_FREE(new_printer
);
583 /* Add to the internal list. */
584 DLIST_ADD(printers_list
, new_printer
);
586 new_printer
->notify
.option
=NULL
;
588 if ( !(new_printer
->ctx
= talloc_init("Printer Entry [%p]", hnd
)) ) {
589 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
590 close_printer_handle(p
, hnd
);
594 if (!set_printer_hnd_printertype(new_printer
, name
)) {
595 close_printer_handle(p
, hnd
);
599 if (!set_printer_hnd_name(new_printer
, name
)) {
600 close_printer_handle(p
, hnd
);
604 new_printer
->access_granted
= access_granted
;
606 DEBUG(5, ("%d printer handles active\n", (int)p
->pipe_handles
->count
));
611 /***************************************************************************
612 check to see if the client motify handle is monitoring the notification
613 given by (notify_type, notify_field).
614 **************************************************************************/
616 static BOOL
is_monitoring_event_flags(uint32 flags
, uint16 notify_type
,
622 static BOOL
is_monitoring_event(Printer_entry
*p
, uint16 notify_type
,
625 SPOOL_NOTIFY_OPTION
*option
= p
->notify
.option
;
629 * Flags should always be zero when the change notify
630 * is registered by the client's spooler. A user Win32 app
631 * might use the flags though instead of the NOTIFY_OPTION_INFO
640 return is_monitoring_event_flags(
641 p
->notify
.flags
, notify_type
, notify_field
);
643 for (i
= 0; i
< option
->count
; i
++) {
645 /* Check match for notify_type */
647 if (option
->ctr
.type
[i
].type
!= notify_type
)
650 /* Check match for field */
652 for (j
= 0; j
< option
->ctr
.type
[i
].count
; j
++) {
653 if (option
->ctr
.type
[i
].fields
[j
] == notify_field
) {
659 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
660 p
->servername
, p
->sharename
, notify_type
, notify_field
));
665 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
667 static void notify_one_value(struct spoolss_notify_msg
*msg
,
668 SPOOL_NOTIFY_INFO_DATA
*data
,
671 data
->notify_data
.value
[0] = msg
->notify
.value
[0];
672 data
->notify_data
.value
[1] = 0;
675 static void notify_string(struct spoolss_notify_msg
*msg
,
676 SPOOL_NOTIFY_INFO_DATA
*data
,
681 /* The length of the message includes the trailing \0 */
683 init_unistr2(&unistr
, msg
->notify
.data
, UNI_STR_TERMINATE
);
685 data
->notify_data
.data
.length
= msg
->len
* 2;
686 data
->notify_data
.data
.string
= TALLOC_ARRAY(mem_ctx
, uint16
, msg
->len
);
688 if (!data
->notify_data
.data
.string
) {
689 data
->notify_data
.data
.length
= 0;
693 memcpy(data
->notify_data
.data
.string
, unistr
.buffer
, msg
->len
* 2);
696 static void notify_system_time(struct spoolss_notify_msg
*msg
,
697 SPOOL_NOTIFY_INFO_DATA
*data
,
703 if (msg
->len
!= sizeof(time_t)) {
704 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
709 if (!prs_init(&ps
, RPC_MAX_PDU_FRAG_LEN
, mem_ctx
, MARSHALL
)) {
710 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
714 if (!make_systemtime(&systime
, gmtime((time_t *)msg
->notify
.data
))) {
715 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
720 if (!spoolss_io_system_time("", &ps
, 0, &systime
)) {
725 data
->notify_data
.data
.length
= prs_offset(&ps
);
726 data
->notify_data
.data
.string
= (uint16
*)
727 TALLOC(mem_ctx
, prs_offset(&ps
));
728 if (!data
->notify_data
.data
.string
) {
733 prs_copy_all_data_out((char *)data
->notify_data
.data
.string
, &ps
);
738 struct notify2_message_table
{
740 void (*fn
)(struct spoolss_notify_msg
*msg
,
741 SPOOL_NOTIFY_INFO_DATA
*data
, TALLOC_CTX
*mem_ctx
);
744 static struct notify2_message_table printer_notify_table
[] = {
745 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string
},
746 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string
},
747 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string
},
748 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string
},
749 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string
},
750 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string
},
751 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string
},
752 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL
},
753 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string
},
754 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string
},
755 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL
},
756 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string
},
757 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
758 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value
},
759 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value
},
760 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL
},
761 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL
},
762 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL
},
763 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value
},
766 static struct notify2_message_table job_notify_table
[] = {
767 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL
},
768 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL
},
769 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL
},
770 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string
},
771 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL
},
772 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL
},
773 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL
},
774 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL
},
775 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL
},
776 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL
},
777 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value
},
778 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL
},
779 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL
},
780 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string
},
781 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL
},
782 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL
},
783 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time
},
784 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL
},
785 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL
},
786 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL
},
787 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value
},
788 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL
},
789 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value
},
790 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL
},
794 /***********************************************************************
795 Allocate talloc context for container object
796 **********************************************************************/
798 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
803 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
808 /***********************************************************************
809 release all allocated memory and zero out structure
810 **********************************************************************/
812 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
818 talloc_destroy(ctr
->ctx
);
825 /***********************************************************************
826 **********************************************************************/
828 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
836 /***********************************************************************
837 **********************************************************************/
839 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
841 if ( !ctr
|| !ctr
->msg_groups
)
844 if ( idx
>= ctr
->num_groups
)
847 return &ctr
->msg_groups
[idx
];
851 /***********************************************************************
852 How many groups of change messages do we have ?
853 **********************************************************************/
855 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
860 return ctr
->num_groups
;
863 /***********************************************************************
864 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
865 **********************************************************************/
867 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
869 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
870 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
871 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
877 /* loop over all groups looking for a matching printer name */
879 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
880 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
884 /* add a new group? */
886 if ( i
== ctr
->num_groups
) {
889 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
890 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
893 ctr
->msg_groups
= groups
;
895 /* clear the new entry and set the printer name */
897 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
898 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
901 /* add the change messages; 'i' is the correct index now regardless */
903 msg_grp
= &ctr
->msg_groups
[i
];
907 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
908 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
911 msg_grp
->msgs
= msg_list
;
913 new_slot
= msg_grp
->num_msgs
-1;
914 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
916 /* need to allocate own copy of data */
919 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
920 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
922 return ctr
->num_groups
;
925 /***********************************************************************
926 Send a change notication message on all handles which have a call
928 **********************************************************************/
930 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32 idx
)
933 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
934 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
935 SPOOLSS_NOTIFY_MSG
*messages
;
936 int sending_msg_count
;
939 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
943 messages
= msg_group
->msgs
;
946 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
950 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
952 /* loop over all printers */
954 for (p
= printers_list
; p
; p
= p
->next
) {
955 SPOOL_NOTIFY_INFO_DATA
*data
;
960 /* Is there notification on this handle? */
962 if ( !p
->notify
.client_connected
)
965 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
967 /* For this printer? Print servers always receive
970 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
971 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
974 DEBUG(10,("Our printer\n"));
976 /* allocate the max entries possible */
978 data
= TALLOC_ARRAY( mem_ctx
, SPOOL_NOTIFY_INFO_DATA
, msg_group
->num_msgs
);
985 /* build the array of change notifications */
987 sending_msg_count
= 0;
989 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
990 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
992 /* Are we monitoring this event? */
994 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1000 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1001 msg
->type
, msg
->field
, p
->sharename
));
1004 * if the is a printer notification handle and not a job notification
1005 * type, then set the id to 0. Other wise just use what was specified
1008 * When registering change notification on a print server handle
1009 * we always need to send back the id (snum) matching the printer
1010 * for which the change took place. For change notify registered
1011 * on a printer handle, this does not matter and the id should be 0.
1016 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1022 /* Convert unix jobid to smb jobid */
1024 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1025 id
= sysjob_to_jobid(msg
->id
);
1028 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1033 construct_info_data( &data
[data_len
], msg
->type
, msg
->field
, id
);
1036 case PRINTER_NOTIFY_TYPE
:
1037 if ( printer_notify_table
[msg
->field
].fn
)
1038 printer_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1041 case JOB_NOTIFY_TYPE
:
1042 if ( job_notify_table
[msg
->field
].fn
)
1043 job_notify_table
[msg
->field
].fn(msg
, &data
[data_len
], mem_ctx
);
1047 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1054 if ( sending_msg_count
) {
1055 rpccli_spoolss_rrpcn( notify_cli_pipe
, mem_ctx
, &p
->notify
.client_hnd
,
1056 data_len
, data
, p
->notify
.change
, 0 );
1061 DEBUG(8,("send_notify2_changes: Exit...\n"));
1065 /***********************************************************************
1066 **********************************************************************/
1068 static BOOL
notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1071 uint32 tv_sec
, tv_usec
;
1074 /* Unpack message */
1076 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "f",
1079 offset
+= tdb_unpack((char *)buf
+ offset
, len
- offset
, "ddddddd",
1081 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1084 tdb_unpack((char *)buf
+ offset
, len
- offset
, "dd",
1085 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1087 tdb_unpack((char *)buf
+ offset
, len
- offset
, "B",
1088 &msg
->len
, &msg
->notify
.data
);
1090 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1091 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1093 tv
->tv_sec
= tv_sec
;
1094 tv
->tv_usec
= tv_usec
;
1097 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1098 msg
->notify
.value
[1]));
1100 dump_data(3, msg
->notify
.data
, msg
->len
);
1105 /********************************************************************
1106 Receive a notify2 message list
1107 ********************************************************************/
1109 static void receive_notify2_message_list(int msg_type
, struct process_id src
,
1110 void *msg
, size_t len
)
1112 size_t msg_count
, i
;
1113 char *buf
= (char *)msg
;
1116 SPOOLSS_NOTIFY_MSG notify
;
1117 SPOOLSS_NOTIFY_MSG_CTR messages
;
1121 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1125 msg_count
= IVAL(buf
, 0);
1128 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1130 if (msg_count
== 0) {
1131 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1135 /* initialize the container */
1137 ZERO_STRUCT( messages
);
1138 notify_msg_ctr_init( &messages
);
1141 * build message groups for each printer identified
1142 * in a change_notify msg. Remember that a PCN message
1143 * includes the handle returned for the srv_spoolss_replyopenprinter()
1144 * call. Therefore messages are grouped according to printer handle.
1147 for ( i
=0; i
<msg_count
; i
++ ) {
1148 struct timeval msg_tv
;
1150 if (msg_ptr
+ 4 - buf
> len
) {
1151 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1155 msg_len
= IVAL(msg_ptr
,0);
1158 if (msg_ptr
+ msg_len
- buf
> len
) {
1159 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1163 /* unpack messages */
1165 ZERO_STRUCT( notify
);
1166 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1169 /* add to correct list in container */
1171 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1173 /* free memory that might have been allocated by notify2_unpack_msg() */
1175 if ( notify
.len
!= 0 )
1176 SAFE_FREE( notify
.notify
.data
);
1179 /* process each group of messages */
1181 num_groups
= notify_msg_ctr_numgroups( &messages
);
1182 for ( i
=0; i
<num_groups
; i
++ )
1183 send_notify2_changes( &messages
, i
);
1188 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32
)msg_count
));
1190 notify_msg_ctr_destroy( &messages
);
1195 /********************************************************************
1196 Send a message to ourself about new driver being installed
1197 so we can upgrade the information for each printer bound to this
1199 ********************************************************************/
1201 static BOOL
srv_spoolss_drv_upgrade_printer(char* drivername
)
1203 int len
= strlen(drivername
);
1208 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1211 message_send_pid(pid_to_procid(sys_getpid()),
1212 MSG_PRINTER_DRVUPGRADE
, drivername
, len
+1, False
);
1217 /**********************************************************************
1218 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1219 over all printers, upgrading ones as necessary
1220 **********************************************************************/
1222 void do_drv_upgrade_printer(int msg_type
, struct process_id src
, void *buf
, size_t len
)
1226 int n_services
= lp_numservices();
1228 len
= MIN(len
,sizeof(drivername
)-1);
1229 strncpy(drivername
, (const char *)buf
, len
);
1231 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1233 /* Iterate the printer list */
1235 for (snum
=0; snum
<n_services
; snum
++)
1237 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1240 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1242 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1243 if (!W_ERROR_IS_OK(result
))
1246 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1248 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1250 /* all we care about currently is the change_id */
1252 result
= mod_a_printer(printer
, 2);
1253 if (!W_ERROR_IS_OK(result
)) {
1254 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1255 dos_errstr(result
)));
1259 free_a_printer(&printer
, 2);
1266 /********************************************************************
1267 Update the cache for all printq's with a registered client
1269 ********************************************************************/
1271 void update_monitored_printq_cache( void )
1273 Printer_entry
*printer
= printers_list
;
1276 /* loop through all printers and update the cache where
1277 client_connected == True */
1280 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1281 && printer
->notify
.client_connected
)
1283 snum
= print_queue_snum(printer
->sharename
);
1284 print_queue_status( snum
, NULL
, NULL
);
1287 printer
= printer
->next
;
1292 /********************************************************************
1293 Send a message to ourself about new driver being installed
1294 so we can upgrade the information for each printer bound to this
1296 ********************************************************************/
1298 static BOOL
srv_spoolss_reset_printerdata(char* drivername
)
1300 int len
= strlen(drivername
);
1305 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1308 message_send_pid(pid_to_procid(sys_getpid()),
1309 MSG_PRINTERDATA_INIT_RESET
, drivername
, len
+1, False
);
1314 /**********************************************************************
1315 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1316 over all printers, resetting printer data as neessary
1317 **********************************************************************/
1319 void reset_all_printerdata(int msg_type
, struct process_id src
,
1320 void *buf
, size_t len
)
1324 int n_services
= lp_numservices();
1326 len
= MIN( len
, sizeof(drivername
)-1 );
1327 strncpy( drivername
, (const char *)buf
, len
);
1329 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername
));
1331 /* Iterate the printer list */
1333 for ( snum
=0; snum
<n_services
; snum
++ )
1335 if ( lp_snum_ok(snum
) && lp_print_ok(snum
) )
1338 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1340 result
= get_a_printer( NULL
, &printer
, 2, lp_const_servicename(snum
) );
1341 if ( !W_ERROR_IS_OK(result
) )
1345 * if the printer is bound to the driver,
1346 * then reset to the new driver initdata
1349 if ( printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
) )
1351 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer
->info_2
->printername
));
1353 if ( !set_driver_init(printer
, 2) ) {
1354 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1355 printer
->info_2
->printername
, printer
->info_2
->drivername
));
1358 result
= mod_a_printer( printer
, 2 );
1359 if ( !W_ERROR_IS_OK(result
) ) {
1360 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1361 get_dos_error_msg(result
)));
1365 free_a_printer( &printer
, 2 );
1374 /********************************************************************
1375 Copy routines used by convert_to_openprinterex()
1376 *******************************************************************/
1378 static DEVICEMODE
* dup_devicemode(TALLOC_CTX
*ctx
, DEVICEMODE
*devmode
)
1386 DEBUG (8,("dup_devmode\n"));
1388 /* bulk copy first */
1390 d
= (DEVICEMODE
*)TALLOC_MEMDUP(ctx
, devmode
, sizeof(DEVICEMODE
));
1394 /* dup the pointer members separately */
1396 len
= unistrlen(devmode
->devicename
.buffer
);
1398 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1399 if (!d
->devicename
.buffer
) {
1402 if (unistrcpy(d
->devicename
.buffer
, devmode
->devicename
.buffer
) != len
)
1407 len
= unistrlen(devmode
->formname
.buffer
);
1409 d
->devicename
.buffer
= TALLOC_ARRAY(ctx
, uint16
, len
);
1410 if (!d
->devicename
.buffer
) {
1413 if (unistrcpy(d
->formname
.buffer
, devmode
->formname
.buffer
) != len
)
1417 d
->dev_private
= (uint8
*)TALLOC_MEMDUP(ctx
, devmode
->dev_private
,
1418 devmode
->driverextra
);
1419 if (!d
->dev_private
) {
1425 static void copy_devmode_ctr(TALLOC_CTX
*ctx
, DEVMODE_CTR
*new_ctr
, DEVMODE_CTR
*ctr
)
1427 if (!new_ctr
|| !ctr
)
1430 DEBUG(8,("copy_devmode_ctr\n"));
1432 new_ctr
->size
= ctr
->size
;
1433 new_ctr
->devmode_ptr
= ctr
->devmode_ptr
;
1435 if(ctr
->devmode_ptr
)
1436 new_ctr
->devmode
= dup_devicemode(ctx
, ctr
->devmode
);
1439 static void copy_printer_default(TALLOC_CTX
*ctx
, PRINTER_DEFAULT
*new_def
, PRINTER_DEFAULT
*def
)
1441 if (!new_def
|| !def
)
1444 DEBUG(8,("copy_printer_defaults\n"));
1446 new_def
->datatype_ptr
= def
->datatype_ptr
;
1448 if (def
->datatype_ptr
)
1449 copy_unistr2(&new_def
->datatype
, &def
->datatype
);
1451 copy_devmode_ctr(ctx
, &new_def
->devmode_cont
, &def
->devmode_cont
);
1453 new_def
->access_required
= def
->access_required
;
1456 /********************************************************************
1457 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1458 * SPOOL_Q_OPEN_PRINTER_EX structure
1459 ********************************************************************/
1461 static WERROR
convert_to_openprinterex(TALLOC_CTX
*ctx
, SPOOL_Q_OPEN_PRINTER_EX
*q_u_ex
, SPOOL_Q_OPEN_PRINTER
*q_u
)
1463 if (!q_u_ex
|| !q_u
)
1466 DEBUG(8,("convert_to_openprinterex\n"));
1468 if ( q_u
->printername
) {
1469 q_u_ex
->printername
= TALLOC_ZERO_P( ctx
, UNISTR2
);
1470 if (q_u_ex
->printername
== NULL
)
1472 copy_unistr2(q_u_ex
->printername
, q_u
->printername
);
1475 copy_printer_default(ctx
, &q_u_ex
->printer_default
, &q_u
->printer_default
);
1480 /********************************************************************
1481 * spoolss_open_printer
1483 * called from the spoolss dispatcher
1484 ********************************************************************/
1486 WERROR
_spoolss_open_printer(pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER
*q_u
, SPOOL_R_OPEN_PRINTER
*r_u
)
1488 SPOOL_Q_OPEN_PRINTER_EX q_u_ex
;
1489 SPOOL_R_OPEN_PRINTER_EX r_u_ex
;
1494 ZERO_STRUCT(q_u_ex
);
1495 ZERO_STRUCT(r_u_ex
);
1497 /* convert the OpenPrinter() call to OpenPrinterEx() */
1499 r_u_ex
.status
= convert_to_openprinterex(p
->mem_ctx
, &q_u_ex
, q_u
);
1500 if (!W_ERROR_IS_OK(r_u_ex
.status
))
1501 return r_u_ex
.status
;
1503 r_u_ex
.status
= _spoolss_open_printer_ex(p
, &q_u_ex
, &r_u_ex
);
1505 /* convert back to OpenPrinter() */
1507 memcpy(r_u
, &r_u_ex
, sizeof(*r_u
));
1512 /********************************************************************
1513 ********************************************************************/
1515 WERROR
_spoolss_open_printer_ex( pipes_struct
*p
, SPOOL_Q_OPEN_PRINTER_EX
*q_u
, SPOOL_R_OPEN_PRINTER_EX
*r_u
)
1517 PRINTER_DEFAULT
*printer_default
= &q_u
->printer_default
;
1518 POLICY_HND
*handle
= &r_u
->handle
;
1522 Printer_entry
*Printer
=NULL
;
1524 if ( !q_u
->printername
)
1525 return WERR_INVALID_PRINTER_NAME
;
1527 /* some sanity check because you can open a printer or a print server */
1528 /* aka: \\server\printer or \\server */
1530 unistr2_to_ascii(name
, q_u
->printername
, sizeof(name
)-1);
1532 DEBUGADD(3,("checking name: %s\n",name
));
1534 if (!open_printer_hnd(p
, handle
, name
, 0))
1535 return WERR_INVALID_PRINTER_NAME
;
1537 Printer
=find_printer_index_by_hnd(p
, handle
);
1539 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1540 "handle we created for printer %s\n", name
));
1541 close_printer_handle(p
,handle
);
1542 return WERR_INVALID_PRINTER_NAME
;
1546 * First case: the user is opening the print server:
1548 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1549 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1551 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1552 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1553 * or if the user is listed in the smb.conf printer admin parameter.
1555 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1556 * client view printer folder, but does not show the MSAPW.
1558 * Note: this test needs code to check access rights here too. Jeremy
1559 * could you look at this?
1561 * Second case: the user is opening a printer:
1562 * NT doesn't let us connect to a printer if the connecting user
1563 * doesn't have print permission.
1565 * Third case: user is opening a Port Monitor
1566 * access checks same as opening a handle to the print server.
1569 switch (Printer
->printer_type
)
1572 case SPLHND_PORTMON_TCP
:
1573 case SPLHND_PORTMON_LOCAL
:
1574 /* Printserver handles use global struct... */
1578 /* Map standard access rights to object specific access rights */
1580 se_map_standard(&printer_default
->access_required
,
1581 &printserver_std_mapping
);
1583 /* Deny any object specific bits that don't apply to print
1584 servers (i.e printer and job specific bits) */
1586 printer_default
->access_required
&= SPECIFIC_RIGHTS_MASK
;
1588 if (printer_default
->access_required
&
1589 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1590 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1591 close_printer_handle(p
, handle
);
1592 return WERR_ACCESS_DENIED
;
1595 /* Allow admin access */
1597 if ( printer_default
->access_required
& SERVER_ACCESS_ADMINISTER
)
1599 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1601 if (!lp_ms_add_printer_wizard()) {
1602 close_printer_handle(p
, handle
);
1603 return WERR_ACCESS_DENIED
;
1606 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1607 and not a printer admin, then fail */
1609 if ((p
->pipe_user
.ut
.uid
!= 0) &&
1610 !user_has_privileges(p
->pipe_user
.nt_user_token
,
1612 !token_contains_name_in_list(
1613 uidtoname(p
->pipe_user
.ut
.uid
), NULL
,
1614 p
->pipe_user
.nt_user_token
,
1615 lp_printer_admin(snum
))) {
1616 close_printer_handle(p
, handle
);
1617 return WERR_ACCESS_DENIED
;
1620 printer_default
->access_required
= SERVER_ACCESS_ADMINISTER
;
1624 printer_default
->access_required
= SERVER_ACCESS_ENUMERATE
;
1627 DEBUG(4,("Setting print server access = %s\n", (printer_default
->access_required
== SERVER_ACCESS_ADMINISTER
)
1628 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1630 /* We fall through to return WERR_OK */
1633 case SPLHND_PRINTER
:
1634 /* NT doesn't let us connect to a printer if the connecting user
1635 doesn't have print permission. */
1637 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
1638 close_printer_handle(p
, handle
);
1642 se_map_standard(&printer_default
->access_required
, &printer_std_mapping
);
1644 /* map an empty access mask to the minimum access mask */
1645 if (printer_default
->access_required
== 0x0)
1646 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1649 * If we are not serving the printer driver for this printer,
1650 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1651 * will keep NT clients happy --jerry
1654 if (lp_use_client_driver(snum
)
1655 && (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
))
1657 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1660 /* check smb.conf parameters and the the sec_desc */
1662 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1663 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1664 return WERR_ACCESS_DENIED
;
1667 if (!user_ok_token(uidtoname(p
->pipe_user
.ut
.uid
),
1668 p
->pipe_user
.nt_user_token
, snum
) ||
1669 !print_access_check(&p
->pipe_user
, snum
,
1670 printer_default
->access_required
)) {
1671 DEBUG(3, ("access DENIED for printer open\n"));
1672 close_printer_handle(p
, handle
);
1673 return WERR_ACCESS_DENIED
;
1676 if ((printer_default
->access_required
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1677 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1678 close_printer_handle(p
, handle
);
1679 return WERR_ACCESS_DENIED
;
1682 if (printer_default
->access_required
& PRINTER_ACCESS_ADMINISTER
)
1683 printer_default
->access_required
= PRINTER_ACCESS_ADMINISTER
;
1685 printer_default
->access_required
= PRINTER_ACCESS_USE
;
1687 DEBUG(4,("Setting printer access = %s\n", (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1688 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1693 /* sanity check to prevent programmer error */
1697 Printer
->access_granted
= printer_default
->access_required
;
1700 * If the client sent a devmode in the OpenPrinter() call, then
1701 * save it here in case we get a job submission on this handle
1704 if ( (Printer
->printer_type
!= SPLHND_SERVER
)
1705 && q_u
->printer_default
.devmode_cont
.devmode_ptr
)
1707 convert_devicemode( Printer
->sharename
, q_u
->printer_default
.devmode_cont
.devmode
,
1708 &Printer
->nt_devmode
);
1711 #if 0 /* JERRY -- I'm doubtful this is really effective */
1712 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1713 optimization in Windows 2000 clients --jerry */
1715 if ( (printer_default
->access_required
== PRINTER_ACCESS_ADMINISTER
)
1716 && (RA_WIN2K
== get_remote_arch()) )
1718 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1719 sys_usleep( 500000 );
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static BOOL
convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL
*uni
,
1730 NT_PRINTER_INFO_LEVEL
*printer
, uint32 level
)
1736 /* allocate memory if needed. Messy because
1737 convert_printer_info is used to update an existing
1738 printer or build a new one */
1740 if ( !printer
->info_2
) {
1741 printer
->info_2
= TALLOC_ZERO_P( printer
, NT_PRINTER_INFO_LEVEL_2
);
1742 if ( !printer
->info_2
) {
1743 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1748 ret
= uni_2_asc_printer_info_2(uni
->info_2
, printer
->info_2
);
1749 printer
->info_2
->setuptime
= time(NULL
);
1757 static BOOL
convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL
*uni
,
1758 NT_PRINTER_DRIVER_INFO_LEVEL
*printer
, uint32 level
)
1764 printer
->info_3
=NULL
;
1765 if (!uni_2_asc_printer_driver_3(uni
->info_3
, &printer
->info_3
))
1769 printer
->info_6
=NULL
;
1770 if (!uni_2_asc_printer_driver_6(uni
->info_6
, &printer
->info_6
))
1780 BOOL
convert_devicemode(const char *printername
, const DEVICEMODE
*devmode
,
1781 NT_DEVICEMODE
**pp_nt_devmode
)
1783 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1786 * Ensure nt_devmode is a valid pointer
1787 * as we will be overwriting it.
1790 if (nt_devmode
== NULL
) {
1791 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1792 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1796 rpcstr_pull(nt_devmode
->devicename
,devmode
->devicename
.buffer
, 31, -1, 0);
1797 rpcstr_pull(nt_devmode
->formname
,devmode
->formname
.buffer
, 31, -1, 0);
1799 nt_devmode
->specversion
=devmode
->specversion
;
1800 nt_devmode
->driverversion
=devmode
->driverversion
;
1801 nt_devmode
->size
=devmode
->size
;
1802 nt_devmode
->fields
=devmode
->fields
;
1803 nt_devmode
->orientation
=devmode
->orientation
;
1804 nt_devmode
->papersize
=devmode
->papersize
;
1805 nt_devmode
->paperlength
=devmode
->paperlength
;
1806 nt_devmode
->paperwidth
=devmode
->paperwidth
;
1807 nt_devmode
->scale
=devmode
->scale
;
1808 nt_devmode
->copies
=devmode
->copies
;
1809 nt_devmode
->defaultsource
=devmode
->defaultsource
;
1810 nt_devmode
->printquality
=devmode
->printquality
;
1811 nt_devmode
->color
=devmode
->color
;
1812 nt_devmode
->duplex
=devmode
->duplex
;
1813 nt_devmode
->yresolution
=devmode
->yresolution
;
1814 nt_devmode
->ttoption
=devmode
->ttoption
;
1815 nt_devmode
->collate
=devmode
->collate
;
1817 nt_devmode
->logpixels
=devmode
->logpixels
;
1818 nt_devmode
->bitsperpel
=devmode
->bitsperpel
;
1819 nt_devmode
->pelswidth
=devmode
->pelswidth
;
1820 nt_devmode
->pelsheight
=devmode
->pelsheight
;
1821 nt_devmode
->displayflags
=devmode
->displayflags
;
1822 nt_devmode
->displayfrequency
=devmode
->displayfrequency
;
1823 nt_devmode
->icmmethod
=devmode
->icmmethod
;
1824 nt_devmode
->icmintent
=devmode
->icmintent
;
1825 nt_devmode
->mediatype
=devmode
->mediatype
;
1826 nt_devmode
->dithertype
=devmode
->dithertype
;
1827 nt_devmode
->reserved1
=devmode
->reserved1
;
1828 nt_devmode
->reserved2
=devmode
->reserved2
;
1829 nt_devmode
->panningwidth
=devmode
->panningwidth
;
1830 nt_devmode
->panningheight
=devmode
->panningheight
;
1833 * Only change private and driverextra if the incoming devmode
1834 * has a new one. JRA.
1837 if ((devmode
->driverextra
!= 0) && (devmode
->dev_private
!= NULL
)) {
1838 SAFE_FREE(nt_devmode
->nt_dev_private
);
1839 nt_devmode
->driverextra
=devmode
->driverextra
;
1840 if((nt_devmode
->nt_dev_private
=SMB_MALLOC_ARRAY(uint8
, nt_devmode
->driverextra
)) == NULL
)
1842 memcpy(nt_devmode
->nt_dev_private
, devmode
->dev_private
, nt_devmode
->driverextra
);
1845 *pp_nt_devmode
= nt_devmode
;
1850 /********************************************************************
1851 * _spoolss_enddocprinter_internal.
1852 ********************************************************************/
1854 static WERROR
_spoolss_enddocprinter_internal(pipes_struct
*p
, POLICY_HND
*handle
)
1856 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1860 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
1864 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
1867 Printer
->document_started
=False
;
1868 print_job_end(snum
, Printer
->jobid
,NORMAL_CLOSE
);
1869 /* error codes unhandled so far ... */
1874 /********************************************************************
1875 * api_spoolss_closeprinter
1876 ********************************************************************/
1878 WERROR
_spoolss_closeprinter(pipes_struct
*p
, SPOOL_Q_CLOSEPRINTER
*q_u
, SPOOL_R_CLOSEPRINTER
*r_u
)
1880 POLICY_HND
*handle
= &q_u
->handle
;
1882 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1884 if (Printer
&& Printer
->document_started
)
1885 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1887 if (!close_printer_handle(p
, handle
))
1890 /* clear the returned printer handle. Observed behavior
1891 from Win2k server. Don't think this really matters.
1892 Previous code just copied the value of the closed
1895 memset(&r_u
->handle
, '\0', sizeof(r_u
->handle
));
1900 /********************************************************************
1901 * api_spoolss_deleteprinter
1903 ********************************************************************/
1905 WERROR
_spoolss_deleteprinter(pipes_struct
*p
, SPOOL_Q_DELETEPRINTER
*q_u
, SPOOL_R_DELETEPRINTER
*r_u
)
1907 POLICY_HND
*handle
= &q_u
->handle
;
1908 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
1911 if (Printer
&& Printer
->document_started
)
1912 _spoolss_enddocprinter_internal(p
, handle
); /* print job was not closed */
1914 memcpy(&r_u
->handle
, &q_u
->handle
, sizeof(r_u
->handle
));
1916 result
= delete_printer_handle(p
, handle
);
1918 update_c_setprinter(False
);
1923 /*******************************************************************
1924 * static function to lookup the version id corresponding to an
1925 * long architecture string
1926 ******************************************************************/
1928 static int get_version_id (char * arch
)
1931 struct table_node archi_table
[]= {
1933 {"Windows 4.0", "WIN40", 0 },
1934 {"Windows NT x86", "W32X86", 2 },
1935 {"Windows NT R4000", "W32MIPS", 2 },
1936 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1937 {"Windows NT PowerPC", "W32PPC", 2 },
1938 {"Windows IA64", "IA64", 3 },
1939 {"Windows x64", "x64", 3 },
1943 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1945 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1946 return (archi_table
[i
].version
);
1952 /********************************************************************
1953 * _spoolss_deleteprinterdriver
1954 ********************************************************************/
1956 WERROR
_spoolss_deleteprinterdriver(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVER
*q_u
, SPOOL_R_DELETEPRINTERDRIVER
*r_u
)
1960 NT_PRINTER_DRIVER_INFO_LEVEL info
;
1961 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
1964 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1965 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1967 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1968 and not a printer admin, then fail */
1970 if ( (p
->pipe_user
.ut
.uid
!= 0)
1971 && !user_has_privileges(p
->pipe_user
.nt_user_token
, &se_printop
)
1972 && !token_contains_name_in_list( uidtoname(p
->pipe_user
.ut
.uid
),
1973 NULL
, p
->pipe_user
.nt_user_token
, lp_printer_admin(-1)) )
1975 return WERR_ACCESS_DENIED
;
1978 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
1979 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
1981 /* check that we have a valid driver name first */
1983 if ((version
=get_version_id(arch
)) == -1)
1984 return WERR_INVALID_ENVIRONMENT
;
1987 ZERO_STRUCT(info_win2k
);
1989 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
)))
1991 /* try for Win2k driver if "Windows NT x86" */
1993 if ( version
== 2 ) {
1995 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
1996 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2000 /* otherwise it was a failure */
2002 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2008 if (printer_driver_in_use(info
.info_3
)) {
2009 status
= WERR_PRINTER_DRIVER_IN_USE
;
2015 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2017 /* if we get to here, we now have 2 driver info structures to remove */
2018 /* remove the Win2k driver first*/
2020 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &p
->pipe_user
, 3, False
);
2021 free_a_printer_driver( info_win2k
, 3 );
2023 /* this should not have failed---if it did, report to client */
2024 if ( !W_ERROR_IS_OK(status_win2k
) )
2026 status
= status_win2k
;
2032 status
= delete_printer_driver(info
.info_3
, &p
->pipe_user
, version
, False
);
2034 /* if at least one of the deletes succeeded return OK */
2036 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2040 free_a_printer_driver( info
, 3 );
2045 /********************************************************************
2046 * spoolss_deleteprinterdriverex
2047 ********************************************************************/
2049 WERROR
_spoolss_deleteprinterdriverex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDRIVEREX
*q_u
, SPOOL_R_DELETEPRINTERDRIVEREX
*r_u
)
2053 NT_PRINTER_DRIVER_INFO_LEVEL info
;
2054 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k
;
2056 uint32 flags
= q_u
->delete_flags
;
2059 WERROR status_win2k
= WERR_ACCESS_DENIED
;
2060 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
2062 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2063 and not a printer admin, then fail */
2065 if ( (p
->pipe_user
.ut
.uid
!= 0)
2066 && !user_has_privileges(p
->pipe_user
.nt_user_token
, &se_printop
)
2067 && !token_contains_name_in_list( uidtoname(p
->pipe_user
.ut
.uid
),
2068 NULL
, p
->pipe_user
.nt_user_token
, lp_printer_admin(-1)) )
2070 return WERR_ACCESS_DENIED
;
2073 unistr2_to_ascii(driver
, &q_u
->driver
, sizeof(driver
)-1 );
2074 unistr2_to_ascii(arch
, &q_u
->arch
, sizeof(arch
)-1 );
2076 /* check that we have a valid driver name first */
2077 if ((version
=get_version_id(arch
)) == -1) {
2078 /* this is what NT returns */
2079 return WERR_INVALID_ENVIRONMENT
;
2082 if ( flags
& DPD_DELETE_SPECIFIC_VERSION
)
2083 version
= q_u
->version
;
2086 ZERO_STRUCT(info_win2k
);
2088 status
= get_a_printer_driver(&info
, 3, driver
, arch
, version
);
2090 if ( !W_ERROR_IS_OK(status
) )
2093 * if the client asked for a specific version,
2094 * or this is something other than Windows NT x86,
2098 if ( (flags
&DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2101 /* try for Win2k driver if "Windows NT x86" */
2104 if (!W_ERROR_IS_OK(get_a_printer_driver(&info
, 3, driver
, arch
, version
))) {
2105 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2110 if ( printer_driver_in_use(info
.info_3
) ) {
2111 status
= WERR_PRINTER_DRIVER_IN_USE
;
2116 * we have a couple of cases to consider.
2117 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2118 * then the delete should fail if **any** files overlap with
2120 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2121 * non-overlapping files
2122 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2123 * is set, the do not delete any files
2124 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2127 delete_files
= flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2129 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2131 if ( delete_files
&& printer_driver_files_in_use(info
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2132 /* no idea of the correct error here */
2133 status
= WERR_ACCESS_DENIED
;
2138 /* also check for W32X86/3 if necessary; maybe we already have? */
2140 if ( (version
== 2) && ((flags
&DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2141 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k
, 3, driver
, arch
, 3)))
2144 if ( delete_files
&& printer_driver_files_in_use(info_win2k
.info_3
) & (flags
&DPD_DELETE_ALL_FILES
) ) {
2145 /* no idea of the correct error here */
2146 free_a_printer_driver( info_win2k
, 3 );
2147 status
= WERR_ACCESS_DENIED
;
2151 /* if we get to here, we now have 2 driver info structures to remove */
2152 /* remove the Win2k driver first*/
2154 status_win2k
= delete_printer_driver(info_win2k
.info_3
, &p
->pipe_user
, 3, delete_files
);
2155 free_a_printer_driver( info_win2k
, 3 );
2157 /* this should not have failed---if it did, report to client */
2159 if ( !W_ERROR_IS_OK(status_win2k
) )
2164 status
= delete_printer_driver(info
.info_3
, &p
->pipe_user
, version
, delete_files
);
2166 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2169 free_a_printer_driver( info
, 3 );
2175 /****************************************************************************
2176 Internal routine for retreiving printerdata
2177 ***************************************************************************/
2179 static WERROR
get_printer_dataex( TALLOC_CTX
*ctx
, NT_PRINTER_INFO_LEVEL
*printer
,
2180 const char *key
, const char *value
, uint32
*type
, uint8
**data
,
2181 uint32
*needed
, uint32 in_size
)
2183 REGISTRY_VALUE
*val
;
2187 if ( !(val
= get_printer_data( printer
->info_2
, key
, value
)) )
2188 return WERR_BADFILE
;
2190 *type
= regval_type( val
);
2192 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size
));
2194 size
= regval_size( val
);
2196 /* copy the min(in_size, len) */
2199 data_len
= (size
> in_size
) ? in_size
: size
*sizeof(uint8
);
2201 /* special case for 0 length values */
2203 if ( (*data
= (uint8
*)TALLOC_MEMDUP(ctx
, regval_data_p(val
), data_len
)) == NULL
)
2207 if ( (*data
= (uint8
*)TALLOC_ZERO(ctx
, in_size
)) == NULL
)
2216 DEBUG(5,("get_printer_dataex: copy done\n"));
2221 /****************************************************************************
2222 Internal routine for removing printerdata
2223 ***************************************************************************/
2225 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2227 return delete_printer_data( printer
->info_2
, key
, value
);
2230 /****************************************************************************
2231 Internal routine for storing printerdata
2232 ***************************************************************************/
2234 WERROR
set_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
,
2235 uint32 type
, uint8
*data
, int real_len
)
2237 /* the registry objects enforce uniqueness based on value name */
2239 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2242 /********************************************************************
2243 GetPrinterData on a printer server Handle.
2244 ********************************************************************/
2246 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*ctx
, fstring value
, uint32
*type
, uint8
**data
, uint32
*needed
, uint32 in_size
)
2250 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2252 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2254 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2260 if (!StrCaseCmp(value
, "BeepEnabled")) {
2262 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2264 SIVAL(*data
, 0, 0x00);
2269 if (!StrCaseCmp(value
, "EventLog")) {
2271 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2273 /* formally was 0x1b */
2274 SIVAL(*data
, 0, 0x0);
2279 if (!StrCaseCmp(value
, "NetPopup")) {
2281 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2283 SIVAL(*data
, 0, 0x00);
2288 if (!StrCaseCmp(value
, "MajorVersion")) {
2290 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2293 /* Windows NT 4.0 seems to not allow uploading of drivers
2294 to a server that reports 0x3 as the MajorVersion.
2295 need to investigate more how Win2k gets around this .
2298 if ( RA_WINNT
== get_remote_arch() )
2307 if (!StrCaseCmp(value
, "MinorVersion")) {
2309 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2317 * uint32 size = 0x114
2319 * uint32 minor = [0|1]
2320 * uint32 build = [2195|2600]
2321 * extra unicode string = e.g. "Service Pack 3"
2323 if (!StrCaseCmp(value
, "OSVersion")) {
2327 if ( !(*data
= TALLOC_ZERO_ARRAY(ctx
, uint8
, (*needed
> in_size
) ? *needed
:in_size
)) )
2330 SIVAL(*data
, 0, *needed
); /* size */
2331 SIVAL(*data
, 4, 5); /* Windows 2000 == 5.0 */
2333 SIVAL(*data
, 12, 2195); /* build */
2335 /* leave extra string empty */
2341 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2342 const char *string
="C:\\PRINTERS";
2344 *needed
= 2*(strlen(string
)+1);
2345 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2347 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2349 /* it's done by hand ready to go on the wire */
2350 for (i
=0; i
<strlen(string
); i
++) {
2351 (*data
)[2*i
]=string
[i
];
2352 (*data
)[2*i
+1]='\0';
2357 if (!StrCaseCmp(value
, "Architecture")) {
2358 const char *string
="Windows NT x86";
2360 *needed
= 2*(strlen(string
)+1);
2361 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2363 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2364 for (i
=0; i
<strlen(string
); i
++) {
2365 (*data
)[2*i
]=string
[i
];
2366 (*data
)[2*i
+1]='\0';
2371 if (!StrCaseCmp(value
, "DsPresent")) {
2373 if ( !(*data
= TALLOC_ARRAY(ctx
, uint8
, sizeof(uint32
) )) )
2376 /* only show the publish check box if we are a
2377 memeber of a AD domain */
2379 if ( lp_security() == SEC_ADS
)
2380 SIVAL(*data
, 0, 0x01);
2382 SIVAL(*data
, 0, 0x00);
2388 if (!StrCaseCmp(value
, "DNSMachineName")) {
2391 if (!get_mydnsfullname(hostname
))
2392 return WERR_BADFILE
;
2394 *needed
= 2*(strlen(hostname
)+1);
2395 if((*data
= (uint8
*)TALLOC(ctx
, (*needed
> in_size
) ? *needed
:in_size
)) == NULL
)
2397 memset(*data
, 0, (*needed
> in_size
) ? *needed
:in_size
);
2398 for (i
=0; i
<strlen(hostname
); i
++) {
2399 (*data
)[2*i
]=hostname
[i
];
2400 (*data
)[2*i
+1]='\0';
2406 return WERR_BADFILE
;
2409 /********************************************************************
2410 * spoolss_getprinterdata
2411 ********************************************************************/
2413 WERROR
_spoolss_getprinterdata(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATA
*q_u
, SPOOL_R_GETPRINTERDATA
*r_u
)
2415 POLICY_HND
*handle
= &q_u
->handle
;
2416 UNISTR2
*valuename
= &q_u
->valuename
;
2417 uint32 in_size
= q_u
->size
;
2418 uint32
*type
= &r_u
->type
;
2419 uint32
*out_size
= &r_u
->size
;
2420 uint8
**data
= &r_u
->data
;
2421 uint32
*needed
= &r_u
->needed
;
2424 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
2425 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
2429 * Reminder: when it's a string, the length is in BYTES
2430 * even if UNICODE is negociated.
2435 *out_size
= in_size
;
2437 /* in case of problem, return some default values */
2442 DEBUG(4,("_spoolss_getprinterdata\n"));
2445 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2446 status
= WERR_BADFID
;
2450 unistr2_to_ascii(value
, valuename
, sizeof(value
)-1);
2452 if ( Printer
->printer_type
== SPLHND_SERVER
)
2453 status
= getprinterdata_printer_server( p
->mem_ctx
, value
, type
, data
, needed
, *out_size
);
2456 if ( !get_printer_snum(p
,handle
, &snum
, NULL
) ) {
2457 status
= WERR_BADFID
;
2461 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
2462 if ( !W_ERROR_IS_OK(status
) )
2465 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2467 if ( strequal(value
, "ChangeId") ) {
2469 *needed
= sizeof(uint32
);
2470 if ( (*data
= (uint8
*)TALLOC(p
->mem_ctx
, sizeof(uint32
))) == NULL
) {
2471 status
= WERR_NOMEM
;
2474 SIVAL( *data
, 0, printer
->info_2
->changeid
);
2478 status
= get_printer_dataex( p
->mem_ctx
, printer
, SPOOL_PRINTERDATA_KEY
, value
, type
, data
, needed
, *out_size
);
2481 if (*needed
> *out_size
)
2482 status
= WERR_MORE_DATA
;
2485 if ( !W_ERROR_IS_OK(status
) )
2487 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status
),*out_size
));
2489 /* reply this param doesn't exist */
2492 if((*data
=(uint8
*)TALLOC_ZERO_ARRAY(p
->mem_ctx
, uint8
, *out_size
)) == NULL
) {
2494 free_a_printer( &printer
, 2 );
2503 /* cleanup & exit */
2506 free_a_printer( &printer
, 2 );
2511 /*********************************************************
2512 Connect to the client machine.
2513 **********************************************************/
2515 static BOOL
spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2516 struct in_addr
*client_ip
, const char *remote_machine
)
2519 struct cli_state
*the_cli
;
2520 struct in_addr rm_addr
;
2522 if ( is_zero_ip(*client_ip
) ) {
2523 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20) ) {
2524 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2528 if ( ismyip( rm_addr
)) {
2529 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine
));
2533 rm_addr
.s_addr
= client_ip
->s_addr
;
2534 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2535 inet_ntoa(*client_ip
) ));
2538 /* setup the connection */
2540 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2541 &rm_addr
, 0, "IPC$", "IPC",
2545 0, lp_client_signing(), NULL
);
2547 if ( !NT_STATUS_IS_OK( ret
) ) {
2548 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2553 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2554 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2555 cli_shutdown(the_cli
);
2560 * Ok - we have an anonymous connection to the IPC$ share.
2561 * Now start the NT Domain stuff :-).
2564 if ( !(*pp_pipe
= cli_rpc_pipe_open_noauth(the_cli
, PI_SPOOLSS
, &ret
)) ) {
2565 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2566 remote_machine
, nt_errstr(ret
)));
2567 cli_shutdown(the_cli
);
2571 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2573 (*pp_pipe
)->cli
= the_cli
;
2578 /***************************************************************************
2579 Connect to the client.
2580 ****************************************************************************/
2582 static BOOL
srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2583 uint32 localprinter
, uint32 type
,
2584 POLICY_HND
*handle
, struct in_addr
*client_ip
)
2589 * If it's the first connection, contact the client
2590 * and connect to the IPC$ share anonymously
2592 if (smb_connections
==0) {
2593 fstring unix_printer
;
2595 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2597 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ip
, unix_printer
))
2600 message_register(MSG_PRINTER_NOTIFY2
, receive_notify2_message_list
);
2601 /* Tell the connections db we're now interested in printer
2602 * notify messages. */
2603 register_message_flags( True
, FLAG_MSG_PRINT_NOTIFY
);
2607 * Tell the specific printing tdb we want messages for this printer
2608 * by registering our PID.
2611 if (!print_notify_register_pid(snum
))
2612 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2616 result
= rpccli_spoolss_reply_open_printer(notify_cli_pipe
, notify_cli_pipe
->cli
->mem_ctx
, printer
, localprinter
,
2619 if (!W_ERROR_IS_OK(result
))
2620 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2621 dos_errstr(result
)));
2623 return (W_ERROR_IS_OK(result
));
2626 /********************************************************************
2628 * ReplyFindFirstPrinterChangeNotifyEx
2630 * before replying OK: status=0 a rpc call is made to the workstation
2631 * asking ReplyOpenPrinter
2633 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2634 * called from api_spoolss_rffpcnex
2635 ********************************************************************/
2637 WERROR
_spoolss_rffpcnex(pipes_struct
*p
, SPOOL_Q_RFFPCNEX
*q_u
, SPOOL_R_RFFPCNEX
*r_u
)
2639 POLICY_HND
*handle
= &q_u
->handle
;
2640 uint32 flags
= q_u
->flags
;
2641 uint32 options
= q_u
->options
;
2642 UNISTR2
*localmachine
= &q_u
->localmachine
;
2643 uint32 printerlocal
= q_u
->printerlocal
;
2645 SPOOL_NOTIFY_OPTION
*option
= q_u
->option
;
2646 struct in_addr client_ip
;
2648 /* store the notify value in the printer struct */
2650 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
2653 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
2657 Printer
->notify
.flags
=flags
;
2658 Printer
->notify
.options
=options
;
2659 Printer
->notify
.printerlocal
=printerlocal
;
2661 if (Printer
->notify
.option
)
2662 free_spool_notify_option(&Printer
->notify
.option
);
2664 Printer
->notify
.option
=dup_spool_notify_option(option
);
2666 unistr2_to_ascii(Printer
->notify
.localmachine
, localmachine
,
2667 sizeof(Printer
->notify
.localmachine
)-1);
2669 /* Connect to the client machine and send a ReplyOpenPrinter */
2671 if ( Printer
->printer_type
== SPLHND_SERVER
)
2673 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2674 !get_printer_snum(p
, handle
, &snum
, NULL
) )
2677 client_ip
.s_addr
= inet_addr(p
->conn
->client_address
);
2679 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2680 Printer
->notify
.printerlocal
, 1,
2681 &Printer
->notify
.client_hnd
, &client_ip
))
2682 return WERR_SERVER_UNAVAILABLE
;
2684 Printer
->notify
.client_connected
=True
;
2689 /*******************************************************************
2690 * fill a notify_info_data with the servername
2691 ********************************************************************/
2693 void spoolss_notify_server_name(int snum
,
2694 SPOOL_NOTIFY_INFO_DATA
*data
,
2695 print_queue_struct
*queue
,
2696 NT_PRINTER_INFO_LEVEL
*printer
,
2697 TALLOC_CTX
*mem_ctx
)
2702 len
= rpcstr_push(temp
, printer
->info_2
->servername
, sizeof(temp
)-2, STR_TERMINATE
);
2704 data
->notify_data
.data
.length
= len
;
2705 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2707 if (!data
->notify_data
.data
.string
) {
2708 data
->notify_data
.data
.length
= 0;
2712 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2715 /*******************************************************************
2716 * fill a notify_info_data with the printername (not including the servername).
2717 ********************************************************************/
2719 void spoolss_notify_printer_name(int snum
,
2720 SPOOL_NOTIFY_INFO_DATA
*data
,
2721 print_queue_struct
*queue
,
2722 NT_PRINTER_INFO_LEVEL
*printer
,
2723 TALLOC_CTX
*mem_ctx
)
2728 /* the notify name should not contain the \\server\ part */
2729 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2732 p
= printer
->info_2
->printername
;
2737 len
= rpcstr_push(temp
, p
, sizeof(temp
)-2, STR_TERMINATE
);
2739 data
->notify_data
.data
.length
= len
;
2740 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2742 if (!data
->notify_data
.data
.string
) {
2743 data
->notify_data
.data
.length
= 0;
2747 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2750 /*******************************************************************
2751 * fill a notify_info_data with the servicename
2752 ********************************************************************/
2754 void spoolss_notify_share_name(int snum
,
2755 SPOOL_NOTIFY_INFO_DATA
*data
,
2756 print_queue_struct
*queue
,
2757 NT_PRINTER_INFO_LEVEL
*printer
,
2758 TALLOC_CTX
*mem_ctx
)
2763 len
= rpcstr_push(temp
, lp_servicename(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2765 data
->notify_data
.data
.length
= len
;
2766 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2768 if (!data
->notify_data
.data
.string
) {
2769 data
->notify_data
.data
.length
= 0;
2773 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2776 /*******************************************************************
2777 * fill a notify_info_data with the port name
2778 ********************************************************************/
2780 void spoolss_notify_port_name(int snum
,
2781 SPOOL_NOTIFY_INFO_DATA
*data
,
2782 print_queue_struct
*queue
,
2783 NT_PRINTER_INFO_LEVEL
*printer
,
2784 TALLOC_CTX
*mem_ctx
)
2789 /* even if it's strange, that's consistant in all the code */
2791 len
= rpcstr_push(temp
, printer
->info_2
->portname
, sizeof(temp
)-2, STR_TERMINATE
);
2793 data
->notify_data
.data
.length
= len
;
2794 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2796 if (!data
->notify_data
.data
.string
) {
2797 data
->notify_data
.data
.length
= 0;
2801 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2804 /*******************************************************************
2805 * fill a notify_info_data with the printername
2806 * but it doesn't exist, have to see what to do
2807 ********************************************************************/
2809 void spoolss_notify_driver_name(int snum
,
2810 SPOOL_NOTIFY_INFO_DATA
*data
,
2811 print_queue_struct
*queue
,
2812 NT_PRINTER_INFO_LEVEL
*printer
,
2813 TALLOC_CTX
*mem_ctx
)
2818 len
= rpcstr_push(temp
, printer
->info_2
->drivername
, sizeof(temp
)-2, STR_TERMINATE
);
2820 data
->notify_data
.data
.length
= len
;
2821 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2823 if (!data
->notify_data
.data
.string
) {
2824 data
->notify_data
.data
.length
= 0;
2828 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2831 /*******************************************************************
2832 * fill a notify_info_data with the comment
2833 ********************************************************************/
2835 void spoolss_notify_comment(int snum
,
2836 SPOOL_NOTIFY_INFO_DATA
*data
,
2837 print_queue_struct
*queue
,
2838 NT_PRINTER_INFO_LEVEL
*printer
,
2839 TALLOC_CTX
*mem_ctx
)
2844 if (*printer
->info_2
->comment
== '\0')
2845 len
= rpcstr_push(temp
, lp_comment(snum
), sizeof(temp
)-2, STR_TERMINATE
);
2847 len
= rpcstr_push(temp
, printer
->info_2
->comment
, sizeof(temp
)-2, STR_TERMINATE
);
2849 data
->notify_data
.data
.length
= len
;
2850 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2852 if (!data
->notify_data
.data
.string
) {
2853 data
->notify_data
.data
.length
= 0;
2857 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2860 /*******************************************************************
2861 * fill a notify_info_data with the comment
2862 * location = "Room 1, floor 2, building 3"
2863 ********************************************************************/
2865 void spoolss_notify_location(int snum
,
2866 SPOOL_NOTIFY_INFO_DATA
*data
,
2867 print_queue_struct
*queue
,
2868 NT_PRINTER_INFO_LEVEL
*printer
,
2869 TALLOC_CTX
*mem_ctx
)
2874 len
= rpcstr_push(temp
, printer
->info_2
->location
,sizeof(temp
)-2, STR_TERMINATE
);
2876 data
->notify_data
.data
.length
= len
;
2877 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2879 if (!data
->notify_data
.data
.string
) {
2880 data
->notify_data
.data
.length
= 0;
2884 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2887 /*******************************************************************
2888 * fill a notify_info_data with the device mode
2889 * jfm:xxxx don't to it for know but that's a real problem !!!
2890 ********************************************************************/
2892 static void spoolss_notify_devmode(int snum
,
2893 SPOOL_NOTIFY_INFO_DATA
*data
,
2894 print_queue_struct
*queue
,
2895 NT_PRINTER_INFO_LEVEL
*printer
,
2896 TALLOC_CTX
*mem_ctx
)
2898 /* for a dummy implementation we have to zero the fields */
2899 data
->notify_data
.data
.length
= 0;
2900 data
->notify_data
.data
.string
= NULL
;
2903 /*******************************************************************
2904 * fill a notify_info_data with the separator file name
2905 ********************************************************************/
2907 void spoolss_notify_sepfile(int snum
,
2908 SPOOL_NOTIFY_INFO_DATA
*data
,
2909 print_queue_struct
*queue
,
2910 NT_PRINTER_INFO_LEVEL
*printer
,
2911 TALLOC_CTX
*mem_ctx
)
2916 len
= rpcstr_push(temp
, printer
->info_2
->sepfile
, sizeof(temp
)-2, STR_TERMINATE
);
2918 data
->notify_data
.data
.length
= len
;
2919 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2921 if (!data
->notify_data
.data
.string
) {
2922 data
->notify_data
.data
.length
= 0;
2926 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2929 /*******************************************************************
2930 * fill a notify_info_data with the print processor
2931 * jfm:xxxx return always winprint to indicate we don't do anything to it
2932 ********************************************************************/
2934 void spoolss_notify_print_processor(int snum
,
2935 SPOOL_NOTIFY_INFO_DATA
*data
,
2936 print_queue_struct
*queue
,
2937 NT_PRINTER_INFO_LEVEL
*printer
,
2938 TALLOC_CTX
*mem_ctx
)
2943 len
= rpcstr_push(temp
, printer
->info_2
->printprocessor
, sizeof(temp
)-2, STR_TERMINATE
);
2945 data
->notify_data
.data
.length
= len
;
2946 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2948 if (!data
->notify_data
.data
.string
) {
2949 data
->notify_data
.data
.length
= 0;
2953 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2956 /*******************************************************************
2957 * fill a notify_info_data with the print processor options
2958 * jfm:xxxx send an empty string
2959 ********************************************************************/
2961 void spoolss_notify_parameters(int snum
,
2962 SPOOL_NOTIFY_INFO_DATA
*data
,
2963 print_queue_struct
*queue
,
2964 NT_PRINTER_INFO_LEVEL
*printer
,
2965 TALLOC_CTX
*mem_ctx
)
2970 len
= rpcstr_push(temp
, printer
->info_2
->parameters
, sizeof(temp
)-2, STR_TERMINATE
);
2972 data
->notify_data
.data
.length
= len
;
2973 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
2975 if (!data
->notify_data
.data
.string
) {
2976 data
->notify_data
.data
.length
= 0;
2980 memcpy(data
->notify_data
.data
.string
, temp
, len
);
2983 /*******************************************************************
2984 * fill a notify_info_data with the data type
2985 * jfm:xxxx always send RAW as data type
2986 ********************************************************************/
2988 void spoolss_notify_datatype(int snum
,
2989 SPOOL_NOTIFY_INFO_DATA
*data
,
2990 print_queue_struct
*queue
,
2991 NT_PRINTER_INFO_LEVEL
*printer
,
2992 TALLOC_CTX
*mem_ctx
)
2997 len
= rpcstr_push(temp
, printer
->info_2
->datatype
, sizeof(pstring
)-2, STR_TERMINATE
);
2999 data
->notify_data
.data
.length
= len
;
3000 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3002 if (!data
->notify_data
.data
.string
) {
3003 data
->notify_data
.data
.length
= 0;
3007 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3010 /*******************************************************************
3011 * fill a notify_info_data with the security descriptor
3012 * jfm:xxxx send an null pointer to say no security desc
3013 * have to implement security before !
3014 ********************************************************************/
3016 static void spoolss_notify_security_desc(int snum
,
3017 SPOOL_NOTIFY_INFO_DATA
*data
,
3018 print_queue_struct
*queue
,
3019 NT_PRINTER_INFO_LEVEL
*printer
,
3020 TALLOC_CTX
*mem_ctx
)
3022 data
->notify_data
.sd
.size
= printer
->info_2
->secdesc_buf
->sd_size
;
3023 data
->notify_data
.sd
.desc
= dup_sec_desc( mem_ctx
, printer
->info_2
->secdesc_buf
->sd
) ;
3026 /*******************************************************************
3027 * fill a notify_info_data with the attributes
3028 * jfm:xxxx a samba printer is always shared
3029 ********************************************************************/
3031 void spoolss_notify_attributes(int snum
,
3032 SPOOL_NOTIFY_INFO_DATA
*data
,
3033 print_queue_struct
*queue
,
3034 NT_PRINTER_INFO_LEVEL
*printer
,
3035 TALLOC_CTX
*mem_ctx
)
3037 data
->notify_data
.value
[0] = printer
->info_2
->attributes
;
3038 data
->notify_data
.value
[1] = 0;
3041 /*******************************************************************
3042 * fill a notify_info_data with the priority
3043 ********************************************************************/
3045 static void spoolss_notify_priority(int snum
,
3046 SPOOL_NOTIFY_INFO_DATA
*data
,
3047 print_queue_struct
*queue
,
3048 NT_PRINTER_INFO_LEVEL
*printer
,
3049 TALLOC_CTX
*mem_ctx
)
3051 data
->notify_data
.value
[0] = printer
->info_2
->priority
;
3052 data
->notify_data
.value
[1] = 0;
3055 /*******************************************************************
3056 * fill a notify_info_data with the default priority
3057 ********************************************************************/
3059 static void spoolss_notify_default_priority(int snum
,
3060 SPOOL_NOTIFY_INFO_DATA
*data
,
3061 print_queue_struct
*queue
,
3062 NT_PRINTER_INFO_LEVEL
*printer
,
3063 TALLOC_CTX
*mem_ctx
)
3065 data
->notify_data
.value
[0] = printer
->info_2
->default_priority
;
3066 data
->notify_data
.value
[1] = 0;
3069 /*******************************************************************
3070 * fill a notify_info_data with the start time
3071 ********************************************************************/
3073 static void spoolss_notify_start_time(int snum
,
3074 SPOOL_NOTIFY_INFO_DATA
*data
,
3075 print_queue_struct
*queue
,
3076 NT_PRINTER_INFO_LEVEL
*printer
,
3077 TALLOC_CTX
*mem_ctx
)
3079 data
->notify_data
.value
[0] = printer
->info_2
->starttime
;
3080 data
->notify_data
.value
[1] = 0;
3083 /*******************************************************************
3084 * fill a notify_info_data with the until time
3085 ********************************************************************/
3087 static void spoolss_notify_until_time(int snum
,
3088 SPOOL_NOTIFY_INFO_DATA
*data
,
3089 print_queue_struct
*queue
,
3090 NT_PRINTER_INFO_LEVEL
*printer
,
3091 TALLOC_CTX
*mem_ctx
)
3093 data
->notify_data
.value
[0] = printer
->info_2
->untiltime
;
3094 data
->notify_data
.value
[1] = 0;
3097 /*******************************************************************
3098 * fill a notify_info_data with the status
3099 ********************************************************************/
3101 static void spoolss_notify_status(int snum
,
3102 SPOOL_NOTIFY_INFO_DATA
*data
,
3103 print_queue_struct
*queue
,
3104 NT_PRINTER_INFO_LEVEL
*printer
,
3105 TALLOC_CTX
*mem_ctx
)
3107 print_status_struct status
;
3109 print_queue_length(snum
, &status
);
3110 data
->notify_data
.value
[0]=(uint32
) status
.status
;
3111 data
->notify_data
.value
[1] = 0;
3114 /*******************************************************************
3115 * fill a notify_info_data with the number of jobs queued
3116 ********************************************************************/
3118 void spoolss_notify_cjobs(int snum
,
3119 SPOOL_NOTIFY_INFO_DATA
*data
,
3120 print_queue_struct
*queue
,
3121 NT_PRINTER_INFO_LEVEL
*printer
,
3122 TALLOC_CTX
*mem_ctx
)
3124 data
->notify_data
.value
[0] = print_queue_length(snum
, NULL
);
3125 data
->notify_data
.value
[1] = 0;
3128 /*******************************************************************
3129 * fill a notify_info_data with the average ppm
3130 ********************************************************************/
3132 static void spoolss_notify_average_ppm(int snum
,
3133 SPOOL_NOTIFY_INFO_DATA
*data
,
3134 print_queue_struct
*queue
,
3135 NT_PRINTER_INFO_LEVEL
*printer
,
3136 TALLOC_CTX
*mem_ctx
)
3138 /* always respond 8 pages per minutes */
3139 /* a little hard ! */
3140 data
->notify_data
.value
[0] = printer
->info_2
->averageppm
;
3141 data
->notify_data
.value
[1] = 0;
3144 /*******************************************************************
3145 * fill a notify_info_data with username
3146 ********************************************************************/
3148 static void spoolss_notify_username(int snum
,
3149 SPOOL_NOTIFY_INFO_DATA
*data
,
3150 print_queue_struct
*queue
,
3151 NT_PRINTER_INFO_LEVEL
*printer
,
3152 TALLOC_CTX
*mem_ctx
)
3157 len
= rpcstr_push(temp
, queue
->fs_user
, sizeof(temp
)-2, STR_TERMINATE
);
3159 data
->notify_data
.data
.length
= len
;
3160 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3162 if (!data
->notify_data
.data
.string
) {
3163 data
->notify_data
.data
.length
= 0;
3167 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3170 /*******************************************************************
3171 * fill a notify_info_data with job status
3172 ********************************************************************/
3174 static void spoolss_notify_job_status(int snum
,
3175 SPOOL_NOTIFY_INFO_DATA
*data
,
3176 print_queue_struct
*queue
,
3177 NT_PRINTER_INFO_LEVEL
*printer
,
3178 TALLOC_CTX
*mem_ctx
)
3180 data
->notify_data
.value
[0]=nt_printj_status(queue
->status
);
3181 data
->notify_data
.value
[1] = 0;
3184 /*******************************************************************
3185 * fill a notify_info_data with job name
3186 ********************************************************************/
3188 static void spoolss_notify_job_name(int snum
,
3189 SPOOL_NOTIFY_INFO_DATA
*data
,
3190 print_queue_struct
*queue
,
3191 NT_PRINTER_INFO_LEVEL
*printer
,
3192 TALLOC_CTX
*mem_ctx
)
3197 len
= rpcstr_push(temp
, queue
->fs_file
, sizeof(temp
)-2, STR_TERMINATE
);
3199 data
->notify_data
.data
.length
= len
;
3200 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3202 if (!data
->notify_data
.data
.string
) {
3203 data
->notify_data
.data
.length
= 0;
3207 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3210 /*******************************************************************
3211 * fill a notify_info_data with job status
3212 ********************************************************************/
3214 static void spoolss_notify_job_status_string(int snum
,
3215 SPOOL_NOTIFY_INFO_DATA
*data
,
3216 print_queue_struct
*queue
,
3217 NT_PRINTER_INFO_LEVEL
*printer
,
3218 TALLOC_CTX
*mem_ctx
)
3221 * Now we're returning job status codes we just return a "" here. JRA.
3228 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3231 switch (queue
->status
) {
3236 p
= ""; /* NT provides the paused string */
3245 #endif /* NO LONGER NEEDED. */
3247 len
= rpcstr_push(temp
, p
, sizeof(temp
) - 2, STR_TERMINATE
);
3249 data
->notify_data
.data
.length
= len
;
3250 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3252 if (!data
->notify_data
.data
.string
) {
3253 data
->notify_data
.data
.length
= 0;
3257 memcpy(data
->notify_data
.data
.string
, temp
, len
);
3260 /*******************************************************************
3261 * fill a notify_info_data with job time
3262 ********************************************************************/
3264 static void spoolss_notify_job_time(int snum
,
3265 SPOOL_NOTIFY_INFO_DATA
*data
,
3266 print_queue_struct
*queue
,
3267 NT_PRINTER_INFO_LEVEL
*printer
,
3268 TALLOC_CTX
*mem_ctx
)
3270 data
->notify_data
.value
[0]=0x0;
3271 data
->notify_data
.value
[1]=0;
3274 /*******************************************************************
3275 * fill a notify_info_data with job size
3276 ********************************************************************/
3278 static void spoolss_notify_job_size(int snum
,
3279 SPOOL_NOTIFY_INFO_DATA
*data
,
3280 print_queue_struct
*queue
,
3281 NT_PRINTER_INFO_LEVEL
*printer
,
3282 TALLOC_CTX
*mem_ctx
)
3284 data
->notify_data
.value
[0]=queue
->size
;
3285 data
->notify_data
.value
[1]=0;
3288 /*******************************************************************
3289 * fill a notify_info_data with page info
3290 ********************************************************************/
3291 static void spoolss_notify_total_pages(int snum
,
3292 SPOOL_NOTIFY_INFO_DATA
*data
,
3293 print_queue_struct
*queue
,
3294 NT_PRINTER_INFO_LEVEL
*printer
,
3295 TALLOC_CTX
*mem_ctx
)
3297 data
->notify_data
.value
[0]=queue
->page_count
;
3298 data
->notify_data
.value
[1]=0;
3301 /*******************************************************************
3302 * fill a notify_info_data with pages printed info.
3303 ********************************************************************/
3304 static void spoolss_notify_pages_printed(int snum
,
3305 SPOOL_NOTIFY_INFO_DATA
*data
,
3306 print_queue_struct
*queue
,
3307 NT_PRINTER_INFO_LEVEL
*printer
,
3308 TALLOC_CTX
*mem_ctx
)
3310 data
->notify_data
.value
[0]=0; /* Add code when back-end tracks this */
3311 data
->notify_data
.value
[1]=0;
3314 /*******************************************************************
3315 Fill a notify_info_data with job position.
3316 ********************************************************************/
3318 static void spoolss_notify_job_position(int snum
,
3319 SPOOL_NOTIFY_INFO_DATA
*data
,
3320 print_queue_struct
*queue
,
3321 NT_PRINTER_INFO_LEVEL
*printer
,
3322 TALLOC_CTX
*mem_ctx
)
3324 data
->notify_data
.value
[0]=queue
->job
;
3325 data
->notify_data
.value
[1]=0;
3328 /*******************************************************************
3329 Fill a notify_info_data with submitted time.
3330 ********************************************************************/
3332 static void spoolss_notify_submitted_time(int snum
,
3333 SPOOL_NOTIFY_INFO_DATA
*data
,
3334 print_queue_struct
*queue
,
3335 NT_PRINTER_INFO_LEVEL
*printer
,
3336 TALLOC_CTX
*mem_ctx
)
3343 t
=gmtime(&queue
->time
);
3345 len
= sizeof(SYSTEMTIME
);
3347 data
->notify_data
.data
.length
= len
;
3348 data
->notify_data
.data
.string
= (uint16
*)TALLOC(mem_ctx
, len
);
3350 if (!data
->notify_data
.data
.string
) {
3351 data
->notify_data
.data
.length
= 0;
3355 make_systemtime(&st
, t
);
3358 * Systemtime must be linearized as a set of UINT16's.
3359 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3362 p
= (char *)data
->notify_data
.data
.string
;
3363 SSVAL(p
, 0, st
.year
);
3364 SSVAL(p
, 2, st
.month
);
3365 SSVAL(p
, 4, st
.dayofweek
);
3366 SSVAL(p
, 6, st
.day
);
3367 SSVAL(p
, 8, st
.hour
);
3368 SSVAL(p
, 10, st
.minute
);
3369 SSVAL(p
, 12, st
.second
);
3370 SSVAL(p
, 14, st
.milliseconds
);
3373 struct s_notify_info_data_table
3379 void (*fn
) (int snum
, SPOOL_NOTIFY_INFO_DATA
*data
,
3380 print_queue_struct
*queue
,
3381 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
3384 /* A table describing the various print notification constants and
3385 whether the notification data is a pointer to a variable sized
3386 buffer, a one value uint32 or a two value uint32. */
3388 static const struct s_notify_info_data_table notify_info_data_table
[] =
3390 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SERVER_NAME
, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3391 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINTER_NAME
, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3392 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SHARE_NAME
, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING
, spoolss_notify_share_name
},
3393 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PORT_NAME
, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3394 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DRIVER_NAME
, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3395 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_COMMENT
, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING
, spoolss_notify_comment
},
3396 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_LOCATION
, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING
, spoolss_notify_location
},
3397 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEVMODE
, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3398 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SEPFILE
, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING
, spoolss_notify_sepfile
},
3399 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRINT_PROCESSOR
, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3400 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PARAMETERS
, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3401 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DATATYPE
, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3402 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC
, spoolss_notify_security_desc
},
3403 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_ATTRIBUTES
, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE
, spoolss_notify_attributes
},
3404 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PRIORITY
, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3405 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_default_priority
},
3406 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_START_TIME
, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3407 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_UNTIL_TIME
, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3408 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS
, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_status
},
3409 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_STATUS_STRING
, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER
, NULL
},
3410 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_CJOBS
, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE
, spoolss_notify_cjobs
},
3411 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_AVERAGE_PPM
, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE
, spoolss_notify_average_ppm
},
3412 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_PAGES
, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER
, NULL
},
3413 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_PAGES_PRINTED
, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER
, NULL
},
3414 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_TOTAL_BYTES
, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER
, NULL
},
3415 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_BYTES_PRINTED
, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER
, NULL
},
3416 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINTER_NAME
, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING
, spoolss_notify_printer_name
},
3417 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_MACHINE_NAME
, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING
, spoolss_notify_server_name
},
3418 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PORT_NAME
, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING
, spoolss_notify_port_name
},
3419 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_USER_NAME
, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3420 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_NOTIFY_NAME
, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING
, spoolss_notify_username
},
3421 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DATATYPE
, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING
, spoolss_notify_datatype
},
3422 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRINT_PROCESSOR
, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING
, spoolss_notify_print_processor
},
3423 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PARAMETERS
, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING
, spoolss_notify_parameters
},
3424 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DRIVER_NAME
, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING
, spoolss_notify_driver_name
},
3425 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DEVMODE
, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER
, spoolss_notify_devmode
},
3426 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS
, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE
, spoolss_notify_job_status
},
3427 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_STATUS_STRING
, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING
, spoolss_notify_job_status_string
},
3428 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER
, NULL
},
3429 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_DOCUMENT
, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING
, spoolss_notify_job_name
},
3430 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PRIORITY
, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE
, spoolss_notify_priority
},
3431 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_POSITION
, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE
, spoolss_notify_job_position
},
3432 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_SUBMITTED
, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER
, spoolss_notify_submitted_time
},
3433 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_START_TIME
, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_start_time
},
3434 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_UNTIL_TIME
, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_until_time
},
3435 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TIME
, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE
, spoolss_notify_job_time
},
3436 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_PAGES
, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE
, spoolss_notify_total_pages
},
3437 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_PAGES_PRINTED
, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE
, spoolss_notify_pages_printed
},
3438 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_TOTAL_BYTES
, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE
, spoolss_notify_job_size
},
3439 { PRINT_TABLE_END
, 0x0, NULL
, 0x0, NULL
},
3442 /*******************************************************************
3443 Return the size of info_data structure.
3444 ********************************************************************/
3446 static uint32
size_of_notify_info_data(uint16 type
, uint16 field
)
3450 for (i
= 0; i
< (sizeof(notify_info_data_table
)/sizeof(struct s_notify_info_data_table
)); i
++) {
3451 if ( (notify_info_data_table
[i
].type
== type
)
3452 && (notify_info_data_table
[i
].field
== field
) ) {
3453 switch(notify_info_data_table
[i
].size
) {
3454 case NOTIFY_ONE_VALUE
:
3455 case NOTIFY_TWO_VALUE
:
3460 /* The only pointer notify data I have seen on
3461 the wire is the submitted time and this has
3462 the notify size set to 4. -tpot */
3464 case NOTIFY_POINTER
:
3467 case NOTIFY_SECDESC
:
3473 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3478 /*******************************************************************
3479 Return the type of notify_info_data.
3480 ********************************************************************/
3482 static uint32
type_of_notify_info_data(uint16 type
, uint16 field
)
3486 for (i
= 0; i
< (sizeof(notify_info_data_table
)/sizeof(struct s_notify_info_data_table
)); i
++) {
3487 if (notify_info_data_table
[i
].type
== type
&&
3488 notify_info_data_table
[i
].field
== field
)
3489 return notify_info_data_table
[i
].size
;
3495 /****************************************************************************
3496 ****************************************************************************/
3498 static BOOL
search_notify(uint16 type
, uint16 field
, int *value
)
3502 for (i
= 0; notify_info_data_table
[i
].type
!= PRINT_TABLE_END
; i
++) {
3503 if (notify_info_data_table
[i
].type
== type
&&
3504 notify_info_data_table
[i
].field
== field
&&
3505 notify_info_data_table
[i
].fn
!= NULL
) {
3514 /****************************************************************************
3515 ****************************************************************************/
3517 void construct_info_data(SPOOL_NOTIFY_INFO_DATA
*info_data
, uint16 type
, uint16 field
, int id
)
3519 info_data
->type
= type
;
3520 info_data
->field
= field
;
3521 info_data
->reserved
= 0;
3523 info_data
->size
= size_of_notify_info_data(type
, field
);
3524 info_data
->enc_type
= type_of_notify_info_data(type
, field
);
3529 /*******************************************************************
3531 * fill a notify_info struct with info asked
3533 ********************************************************************/
3535 static BOOL
construct_notify_printer_info(Printer_entry
*print_hnd
, SPOOL_NOTIFY_INFO
*info
, int
3536 snum
, SPOOL_NOTIFY_OPTION_TYPE
3537 *option_type
, uint32 id
,
3538 TALLOC_CTX
*mem_ctx
)
3544 SPOOL_NOTIFY_INFO_DATA
*current_data
;
3545 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3546 print_queue_struct
*queue
=NULL
;
3548 type
=option_type
->type
;
3550 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3551 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3552 option_type
->count
, lp_servicename(snum
)));
3554 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3557 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3558 field
= option_type
->fields
[field_num
];
3560 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3562 if (!search_notify(type
, field
, &j
) )
3565 if((info
->data
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3566 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3567 free_a_printer(&printer
, 2);
3571 current_data
= &info
->data
[info
->count
];
3573 construct_info_data(current_data
, type
, field
, id
);
3575 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3576 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3578 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3584 free_a_printer(&printer
, 2);
3588 /*******************************************************************
3590 * fill a notify_info struct with info asked
3592 ********************************************************************/
3594 static BOOL
construct_notify_jobs_info(print_queue_struct
*queue
,
3595 SPOOL_NOTIFY_INFO
*info
,
3596 NT_PRINTER_INFO_LEVEL
*printer
,
3597 int snum
, SPOOL_NOTIFY_OPTION_TYPE
3598 *option_type
, uint32 id
,
3599 TALLOC_CTX
*mem_ctx
)
3605 SPOOL_NOTIFY_INFO_DATA
*current_data
;
3607 DEBUG(4,("construct_notify_jobs_info\n"));
3609 type
= option_type
->type
;
3611 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3612 (option_type
->type
==PRINTER_NOTIFY_TYPE
?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3613 option_type
->count
));
3615 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3616 field
= option_type
->fields
[field_num
];
3618 if (!search_notify(type
, field
, &j
) )
3621 if((info
->data
=SMB_REALLOC_ARRAY(info
->data
, SPOOL_NOTIFY_INFO_DATA
, info
->count
+1)) == NULL
) {
3622 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3626 current_data
=&(info
->data
[info
->count
]);
3628 construct_info_data(current_data
, type
, field
, id
);
3629 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3638 * JFM: The enumeration is not that simple, it's even non obvious.
3640 * let's take an example: I want to monitor the PRINTER SERVER for
3641 * the printer's name and the number of jobs currently queued.
3642 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3643 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3645 * I have 3 printers on the back of my server.
3647 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3650 * 1 printer 1 name 1
3651 * 2 printer 1 cjob 1
3652 * 3 printer 2 name 2
3653 * 4 printer 2 cjob 2
3654 * 5 printer 3 name 3
3655 * 6 printer 3 name 3
3657 * that's the print server case, the printer case is even worse.
3660 /*******************************************************************
3662 * enumerate all printers on the printserver
3663 * fill a notify_info struct with info asked
3665 ********************************************************************/
3667 static WERROR
printserver_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
,
3668 SPOOL_NOTIFY_INFO
*info
,
3669 TALLOC_CTX
*mem_ctx
)
3672 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3673 int n_services
=lp_numservices();
3675 SPOOL_NOTIFY_OPTION
*option
;
3676 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3678 DEBUG(4,("printserver_notify_info\n"));
3683 option
=Printer
->notify
.option
;
3688 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3689 sending a ffpcn() request first */
3694 for (i
=0; i
<option
->count
; i
++) {
3695 option_type
=&(option
->ctr
.type
[i
]);
3697 if (option_type
->type
!=PRINTER_NOTIFY_TYPE
)
3700 for (snum
=0; snum
<n_services
; snum
++)
3702 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3703 construct_notify_printer_info ( Printer
, info
, snum
, option_type
, snum
, mem_ctx
);
3709 * Debugging information, don't delete.
3712 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3713 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3714 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3716 for (i
=0; i
<info
->count
; i
++) {
3717 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3718 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3719 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3726 /*******************************************************************
3728 * fill a notify_info struct with info asked
3730 ********************************************************************/
3732 static WERROR
printer_notify_info(pipes_struct
*p
, POLICY_HND
*hnd
, SPOOL_NOTIFY_INFO
*info
,
3733 TALLOC_CTX
*mem_ctx
)
3736 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, hnd
);
3739 SPOOL_NOTIFY_OPTION
*option
;
3740 SPOOL_NOTIFY_OPTION_TYPE
*option_type
;
3742 print_queue_struct
*queue
=NULL
;
3743 print_status_struct status
;
3745 DEBUG(4,("printer_notify_info\n"));
3750 option
=Printer
->notify
.option
;
3756 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3757 sending a ffpcn() request first */
3762 get_printer_snum(p
, hnd
, &snum
, NULL
);
3764 for (i
=0; i
<option
->count
; i
++) {
3765 option_type
=&option
->ctr
.type
[i
];
3767 switch ( option_type
->type
) {
3768 case PRINTER_NOTIFY_TYPE
:
3769 if(construct_notify_printer_info(Printer
, info
, snum
,
3775 case JOB_NOTIFY_TYPE
: {
3776 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3778 count
= print_queue_status(snum
, &queue
, &status
);
3780 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3783 for (j
=0; j
<count
; j
++) {
3784 construct_notify_jobs_info(&queue
[j
], info
,
3791 free_a_printer(&printer
, 2);
3801 * Debugging information, don't delete.
3804 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3805 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3806 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3808 for (i=0; i<info->count; i++) {
3809 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3810 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3811 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3817 /********************************************************************
3819 ********************************************************************/
3821 WERROR
_spoolss_rfnpcnex( pipes_struct
*p
, SPOOL_Q_RFNPCNEX
*q_u
, SPOOL_R_RFNPCNEX
*r_u
)
3823 POLICY_HND
*handle
= &q_u
->handle
;
3824 SPOOL_NOTIFY_INFO
*info
= &r_u
->info
;
3826 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
3827 WERROR result
= WERR_BADFID
;
3829 /* we always have a NOTIFY_INFO struct */
3833 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3834 OUR_HANDLE(handle
)));
3838 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3841 * We are now using the change value, and
3842 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3843 * I don't have a global notification system, I'm sending back all the
3844 * informations even when _NOTHING_ has changed.
3847 /* We need to keep track of the change value to send back in
3848 RRPCN replies otherwise our updates are ignored. */
3850 Printer
->notify
.fnpcn
= True
;
3852 if (Printer
->notify
.client_connected
) {
3853 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u
->change
));
3854 Printer
->notify
.change
= q_u
->change
;
3857 /* just ignore the SPOOL_NOTIFY_OPTION */
3859 switch (Printer
->printer_type
) {
3861 result
= printserver_notify_info(p
, handle
, info
, p
->mem_ctx
);
3864 case SPLHND_PRINTER
:
3865 result
= printer_notify_info(p
, handle
, info
, p
->mem_ctx
);
3869 Printer
->notify
.fnpcn
= False
;
3875 /********************************************************************
3876 * construct_printer_info_0
3877 * fill a printer_info_0 struct
3878 ********************************************************************/
3880 static BOOL
construct_printer_info_0(Printer_entry
*print_hnd
,
3881 PRINTER_INFO_0
*printer
,
3882 const struct share_params
*params
)
3886 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3887 counter_printer_0
*session_counter
;
3888 uint32 global_counter
;
3891 print_status_struct status
;
3893 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2,
3894 lp_const_servicename(params
->service
))))
3897 count
= print_queue_length(params
->service
, &status
);
3899 /* check if we already have a counter for this printer */
3900 for(session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3901 if (session_counter
->snum
== params
->service
)
3905 /* it's the first time, add it to the list */
3906 if (session_counter
==NULL
) {
3907 if((session_counter
=SMB_MALLOC_P(counter_printer_0
)) == NULL
) {
3908 free_a_printer(&ntprinter
, 2);
3911 ZERO_STRUCTP(session_counter
);
3912 session_counter
->snum
=params
->service
;
3913 session_counter
->counter
=0;
3914 DLIST_ADD(counter_list
, session_counter
);
3918 session_counter
->counter
++;
3921 * the global_counter should be stored in a TDB as it's common to all the clients
3922 * and should be zeroed on samba startup
3924 global_counter
=session_counter
->counter
;
3926 pstrcpy(chaine
,ntprinter
->info_2
->printername
);
3928 init_unistr(&printer
->printername
, chaine
);
3930 slprintf(chaine
,sizeof(chaine
)-1,"\\\\%s", get_server_name(print_hnd
));
3931 init_unistr(&printer
->servername
, chaine
);
3933 printer
->cjobs
= count
;
3934 printer
->total_jobs
= 0;
3935 printer
->total_bytes
= 0;
3937 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3938 t
=gmtime(&setuptime
);
3940 printer
->year
= t
->tm_year
+1900;
3941 printer
->month
= t
->tm_mon
+1;
3942 printer
->dayofweek
= t
->tm_wday
;
3943 printer
->day
= t
->tm_mday
;
3944 printer
->hour
= t
->tm_hour
;
3945 printer
->minute
= t
->tm_min
;
3946 printer
->second
= t
->tm_sec
;
3947 printer
->milliseconds
= 0;
3949 printer
->global_counter
= global_counter
;
3950 printer
->total_pages
= 0;
3952 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3953 printer
->major_version
= 0x0005; /* NT 5 */
3954 printer
->build_version
= 0x0893; /* build 2195 */
3956 printer
->unknown7
= 0x1;
3957 printer
->unknown8
= 0x0;
3958 printer
->unknown9
= 0x0;
3959 printer
->session_counter
= session_counter
->counter
;
3960 printer
->unknown11
= 0x0;
3961 printer
->printer_errors
= 0x0; /* number of print failure */
3962 printer
->unknown13
= 0x0;
3963 printer
->unknown14
= 0x1;
3964 printer
->unknown15
= 0x024a; /* 586 Pentium ? */
3965 printer
->unknown16
= 0x0;
3966 printer
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3967 printer
->unknown18
= 0x0;
3968 printer
->status
= nt_printq_status(status
.status
);
3969 printer
->unknown20
= 0x0;
3970 printer
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3971 printer
->unknown22
= 0x0;
3972 printer
->unknown23
= 0x6; /* 6 ???*/
3973 printer
->unknown24
= 0; /* unknown 24 to 26 are always 0 */
3974 printer
->unknown25
= 0;
3975 printer
->unknown26
= 0;
3976 printer
->unknown27
= 0;
3977 printer
->unknown28
= 0;
3978 printer
->unknown29
= 0;
3980 free_a_printer(&ntprinter
,2);
3984 /********************************************************************
3985 * construct_printer_info_1
3986 * fill a printer_info_1 struct
3987 ********************************************************************/
3988 static BOOL
construct_printer_info_1(Printer_entry
*print_hnd
, uint32 flags
,
3989 PRINTER_INFO_1
*printer
,
3990 const struct share_params
*params
)
3994 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3996 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2,
3997 lp_const_servicename(params
->service
))))
4000 printer
->flags
=flags
;
4002 if (*ntprinter
->info_2
->comment
== '\0') {
4003 init_unistr(&printer
->comment
, lp_comment(params
->service
));
4004 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4005 ntprinter
->info_2
->drivername
,
4006 lp_comment(params
->service
));
4009 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4010 slprintf(chaine
,sizeof(chaine
)-1,"%s,%s,%s", ntprinter
->info_2
->printername
,
4011 ntprinter
->info_2
->drivername
, ntprinter
->info_2
->comment
);
4014 slprintf(chaine2
,sizeof(chaine
)-1,"%s", ntprinter
->info_2
->printername
);
4016 init_unistr(&printer
->description
, chaine
);
4017 init_unistr(&printer
->name
, chaine2
);
4019 free_a_printer(&ntprinter
,2);
4024 /****************************************************************************
4025 Free a DEVMODE struct.
4026 ****************************************************************************/
4028 static void free_dev_mode(DEVICEMODE
*dev
)
4033 SAFE_FREE(dev
->dev_private
);
4038 /****************************************************************************
4039 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4040 should be valid upon entry
4041 ****************************************************************************/
4043 static BOOL
convert_nt_devicemode( DEVICEMODE
*devmode
, NT_DEVICEMODE
*ntdevmode
)
4045 if ( !devmode
|| !ntdevmode
)
4048 init_unistr(&devmode
->devicename
, ntdevmode
->devicename
);
4050 init_unistr(&devmode
->formname
, ntdevmode
->formname
);
4052 devmode
->specversion
= ntdevmode
->specversion
;
4053 devmode
->driverversion
= ntdevmode
->driverversion
;
4054 devmode
->size
= ntdevmode
->size
;
4055 devmode
->driverextra
= ntdevmode
->driverextra
;
4056 devmode
->fields
= ntdevmode
->fields
;
4058 devmode
->orientation
= ntdevmode
->orientation
;
4059 devmode
->papersize
= ntdevmode
->papersize
;
4060 devmode
->paperlength
= ntdevmode
->paperlength
;
4061 devmode
->paperwidth
= ntdevmode
->paperwidth
;
4062 devmode
->scale
= ntdevmode
->scale
;
4063 devmode
->copies
= ntdevmode
->copies
;
4064 devmode
->defaultsource
= ntdevmode
->defaultsource
;
4065 devmode
->printquality
= ntdevmode
->printquality
;
4066 devmode
->color
= ntdevmode
->color
;
4067 devmode
->duplex
= ntdevmode
->duplex
;
4068 devmode
->yresolution
= ntdevmode
->yresolution
;
4069 devmode
->ttoption
= ntdevmode
->ttoption
;
4070 devmode
->collate
= ntdevmode
->collate
;
4071 devmode
->icmmethod
= ntdevmode
->icmmethod
;
4072 devmode
->icmintent
= ntdevmode
->icmintent
;
4073 devmode
->mediatype
= ntdevmode
->mediatype
;
4074 devmode
->dithertype
= ntdevmode
->dithertype
;
4076 if (ntdevmode
->nt_dev_private
!= NULL
) {
4077 if ((devmode
->dev_private
=(uint8
*)memdup(ntdevmode
->nt_dev_private
, ntdevmode
->driverextra
)) == NULL
)
4084 /****************************************************************************
4085 Create a DEVMODE struct. Returns malloced memory.
4086 ****************************************************************************/
4088 DEVICEMODE
*construct_dev_mode(const char *servicename
)
4090 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4091 DEVICEMODE
*devmode
= NULL
;
4093 DEBUG(7,("construct_dev_mode\n"));
4095 DEBUGADD(8,("getting printer characteristics\n"));
4097 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
4100 if ( !printer
->info_2
->devmode
) {
4101 DEBUG(5, ("BONG! There was no device mode!\n"));
4105 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) == NULL
) {
4106 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4110 ZERO_STRUCTP(devmode
);
4112 DEBUGADD(8,("loading DEVICEMODE\n"));
4114 if ( !convert_nt_devicemode( devmode
, printer
->info_2
->devmode
) ) {
4115 free_dev_mode( devmode
);
4120 free_a_printer(&printer
,2);
4125 /********************************************************************
4126 * construct_printer_info_2
4127 * fill a printer_info_2 struct
4128 ********************************************************************/
4130 static BOOL
construct_printer_info_2(Printer_entry
*print_hnd
,
4131 PRINTER_INFO_2
*printer
,
4132 const struct share_params
*params
)
4135 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4137 print_status_struct status
;
4139 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2,
4140 lp_const_servicename(params
->service
))))
4143 count
= print_queue_length(params
->service
, &status
);
4145 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4146 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4147 init_unistr(&printer
->sharename
, lp_servicename(params
->service
)); /* sharename */
4148 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
); /* port */
4149 init_unistr(&printer
->drivername
, ntprinter
->info_2
->drivername
); /* drivername */
4151 if (*ntprinter
->info_2
->comment
== '\0')
4152 init_unistr(&printer
->comment
, lp_comment(params
->service
)); /* comment */
4154 init_unistr(&printer
->comment
, ntprinter
->info_2
->comment
); /* saved comment. */
4156 init_unistr(&printer
->location
, ntprinter
->info_2
->location
); /* location */
4157 init_unistr(&printer
->sepfile
, ntprinter
->info_2
->sepfile
); /* separator file */
4158 init_unistr(&printer
->printprocessor
, ntprinter
->info_2
->printprocessor
);/* print processor */
4159 init_unistr(&printer
->datatype
, ntprinter
->info_2
->datatype
); /* datatype */
4160 init_unistr(&printer
->parameters
, ntprinter
->info_2
->parameters
); /* parameters (of print processor) */
4162 printer
->attributes
= ntprinter
->info_2
->attributes
;
4164 printer
->priority
= ntprinter
->info_2
->priority
; /* priority */
4165 printer
->defaultpriority
= ntprinter
->info_2
->default_priority
; /* default priority */
4166 printer
->starttime
= ntprinter
->info_2
->starttime
; /* starttime */
4167 printer
->untiltime
= ntprinter
->info_2
->untiltime
; /* untiltime */
4168 printer
->status
= nt_printq_status(status
.status
); /* status */
4169 printer
->cjobs
= count
; /* jobs */
4170 printer
->averageppm
= ntprinter
->info_2
->averageppm
; /* average pages per minute */
4172 if ( !(printer
->devmode
= construct_dev_mode(
4173 lp_const_servicename(params
->service
))) )
4174 DEBUG(8, ("Returning NULL Devicemode!\n"));
4176 printer
->secdesc
= NULL
;
4178 if ( ntprinter
->info_2
->secdesc_buf
4179 && ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0 )
4181 /* don't use talloc_steal() here unless you do a deep steal of all
4182 the SEC_DESC members */
4184 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4185 ntprinter
->info_2
->secdesc_buf
->sd
);
4188 free_a_printer(&ntprinter
, 2);
4193 /********************************************************************
4194 * construct_printer_info_3
4195 * fill a printer_info_3 struct
4196 ********************************************************************/
4198 static BOOL
construct_printer_info_3(Printer_entry
*print_hnd
,
4199 PRINTER_INFO_3
**pp_printer
,
4200 const struct share_params
*params
)
4202 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4203 PRINTER_INFO_3
*printer
= NULL
;
4205 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2,
4206 lp_const_servicename(params
->service
))))
4210 if ((printer
= SMB_MALLOC_P(PRINTER_INFO_3
)) == NULL
) {
4211 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4212 free_a_printer(&ntprinter
, 2);
4216 ZERO_STRUCTP(printer
);
4218 /* These are the components of the SD we are returning. */
4220 printer
->flags
= 0x4;
4222 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
4223 /* don't use talloc_steal() here unless you do a deep steal of all
4224 the SEC_DESC members */
4226 printer
->secdesc
= dup_sec_desc( get_talloc_ctx(),
4227 ntprinter
->info_2
->secdesc_buf
->sd
);
4230 free_a_printer(&ntprinter
, 2);
4232 *pp_printer
= printer
;
4236 /********************************************************************
4237 * construct_printer_info_4
4238 * fill a printer_info_4 struct
4239 ********************************************************************/
4241 static BOOL
construct_printer_info_4(Printer_entry
*print_hnd
,
4242 PRINTER_INFO_4
*printer
,
4243 const struct share_params
*params
)
4245 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4247 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2,
4248 lp_const_servicename(params
->service
))))
4251 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
); /* printername*/
4252 init_unistr(&printer
->servername
, ntprinter
->info_2
->servername
); /* servername*/
4253 printer
->attributes
= ntprinter
->info_2
->attributes
;
4255 free_a_printer(&ntprinter
, 2);
4259 /********************************************************************
4260 * construct_printer_info_5
4261 * fill a printer_info_5 struct
4262 ********************************************************************/
4264 static BOOL
construct_printer_info_5(Printer_entry
*print_hnd
,
4265 PRINTER_INFO_5
*printer
,
4266 const struct share_params
*params
)
4268 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4270 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2,
4271 lp_const_servicename(params
->service
))))
4274 init_unistr(&printer
->printername
, ntprinter
->info_2
->printername
);
4275 init_unistr(&printer
->portname
, ntprinter
->info_2
->portname
);
4276 printer
->attributes
= ntprinter
->info_2
->attributes
;
4278 /* these two are not used by NT+ according to MSDN */
4280 printer
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4281 printer
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4283 free_a_printer(&ntprinter
, 2);
4288 /********************************************************************
4289 * construct_printer_info_6
4290 * fill a printer_info_6 struct
4291 ********************************************************************/
4293 static BOOL
construct_printer_info_6(Printer_entry
*print_hnd
,
4294 PRINTER_INFO_6
*printer
,
4295 const struct share_params
*params
)
4297 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4299 print_status_struct status
;
4301 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &ntprinter
, 2,
4302 lp_const_servicename(params
->service
))))
4305 count
= print_queue_length(params
->service
, &status
);
4307 printer
->status
= nt_printq_status(status
.status
);
4309 free_a_printer(&ntprinter
, 2);
4314 /********************************************************************
4315 * construct_printer_info_7
4316 * fill a printer_info_7 struct
4317 ********************************************************************/
4319 static BOOL
construct_printer_info_7(Printer_entry
*print_hnd
,
4320 PRINTER_INFO_7
*printer
,
4321 const struct share_params
*params
)
4323 char *guid_str
= NULL
;
4326 if (is_printer_published(print_hnd
, params
->service
, &guid
)) {
4327 asprintf(&guid_str
, "{%s}", smb_uuid_string_static(guid
));
4328 strupper_m(guid_str
);
4329 init_unistr(&printer
->guid
, guid_str
);
4330 printer
->action
= SPOOL_DS_PUBLISH
;
4332 init_unistr(&printer
->guid
, "");
4333 printer
->action
= SPOOL_DS_UNPUBLISH
;
4339 /********************************************************************
4340 Spoolss_enumprinters.
4341 ********************************************************************/
4343 static WERROR
enum_all_printers_info_1(uint32 flags
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4347 int n_services
=lp_numservices();
4348 PRINTER_INFO_1
*printers
=NULL
;
4349 PRINTER_INFO_1 current_prt
;
4350 WERROR result
= WERR_OK
;
4352 DEBUG(4,("enum_all_printers_info_1\n"));
4354 for (snum
=0; snum
<n_services
; snum
++) {
4355 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4356 struct share_params params
;
4357 params
.service
= snum
;
4359 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4361 if (construct_printer_info_1(NULL
, flags
, ¤t_prt
, ¶ms
)) {
4362 if((printers
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_1
, *returned
+1)) == NULL
) {
4363 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4367 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned
));
4369 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_1
));
4375 /* check the required size. */
4376 for (i
=0; i
<*returned
; i
++)
4377 (*needed
) += spoolss_size_printer_info_1(&printers
[i
]);
4379 if (*needed
> offered
) {
4380 result
= WERR_INSUFFICIENT_BUFFER
;
4384 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4385 result
= WERR_NOMEM
;
4389 /* fill the buffer with the structures */
4390 for (i
=0; i
<*returned
; i
++)
4391 smb_io_printer_info_1("", buffer
, &printers
[i
], 0);
4396 SAFE_FREE(printers
);
4398 if ( !W_ERROR_IS_OK(result
) )
4404 /********************************************************************
4405 enum_all_printers_info_1_local.
4406 *********************************************************************/
4408 static WERROR
enum_all_printers_info_1_local(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4410 DEBUG(4,("enum_all_printers_info_1_local\n"));
4412 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4415 /********************************************************************
4416 enum_all_printers_info_1_name.
4417 *********************************************************************/
4419 static WERROR
enum_all_printers_info_1_name(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4423 DEBUG(4,("enum_all_printers_info_1_name\n"));
4425 if ((name
[0] == '\\') && (name
[1] == '\\'))
4428 if (is_myname_or_ipaddr(s
)) {
4429 return enum_all_printers_info_1(PRINTER_ENUM_ICON8
, buffer
, offered
, needed
, returned
);
4432 return WERR_INVALID_NAME
;
4435 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4436 /********************************************************************
4437 enum_all_printers_info_1_remote.
4438 *********************************************************************/
4440 static WERROR
enum_all_printers_info_1_remote(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4442 PRINTER_INFO_1
*printer
;
4443 fstring printername
;
4446 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4447 WERROR result
= WERR_OK
;
4449 /* JFM: currently it's more a place holder than anything else.
4450 * In the spooler world there is a notion of server registration.
4451 * the print servers are registered on the PDC (in the same domain)
4453 * We should have a TDB here. The registration is done thru an
4454 * undocumented RPC call.
4457 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4462 slprintf(printername
, sizeof(printername
)-1,"Windows NT Remote Printers!!\\\\%s", name
);
4463 slprintf(desc
, sizeof(desc
)-1,"%s", name
);
4464 slprintf(comment
, sizeof(comment
)-1, "Logged on Domain");
4466 init_unistr(&printer
->description
, desc
);
4467 init_unistr(&printer
->name
, printername
);
4468 init_unistr(&printer
->comment
, comment
);
4469 printer
->flags
=PRINTER_ENUM_ICON3
|PRINTER_ENUM_CONTAINER
;
4471 /* check the required size. */
4472 *needed
+= spoolss_size_printer_info_1(printer
);
4474 if (*needed
> offered
) {
4475 result
= WERR_INSUFFICIENT_BUFFER
;
4479 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4480 result
= WERR_NOMEM
;
4484 /* fill the buffer with the structures */
4485 smb_io_printer_info_1("", buffer
, printer
, 0);
4491 if ( !W_ERROR_IS_OK(result
) )
4499 /********************************************************************
4500 enum_all_printers_info_1_network.
4501 *********************************************************************/
4503 static WERROR
enum_all_printers_info_1_network(fstring name
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4507 DEBUG(4,("enum_all_printers_info_1_network\n"));
4509 /* If we respond to a enum_printers level 1 on our name with flags
4510 set to PRINTER_ENUM_REMOTE with a list of printers then these
4511 printers incorrectly appear in the APW browse list.
4512 Specifically the printers for the server appear at the workgroup
4513 level where all the other servers in the domain are
4514 listed. Windows responds to this call with a
4515 WERR_CAN_NOT_COMPLETE so we should do the same. */
4517 if (name
[0] == '\\' && name
[1] == '\\')
4520 if (is_myname_or_ipaddr(s
))
4521 return WERR_CAN_NOT_COMPLETE
;
4523 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8
, buffer
, offered
, needed
, returned
);
4526 /********************************************************************
4527 * api_spoolss_enumprinters
4529 * called from api_spoolss_enumprinters (see this to understand)
4530 ********************************************************************/
4532 static WERROR
enum_all_printers_info_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
4536 int n_services
=lp_numservices();
4537 PRINTER_INFO_2
*printers
=NULL
;
4538 PRINTER_INFO_2 current_prt
;
4539 WERROR result
= WERR_OK
;
4543 for (snum
=0; snum
<n_services
; snum
++) {
4544 if (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) ) {
4545 struct share_params params
;
4546 params
.service
= snum
;
4547 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum
), snum
));
4549 if (construct_printer_info_2(NULL
, ¤t_prt
, ¶ms
)) {
4550 if ( !(printers
=SMB_REALLOC_ARRAY(printers
, PRINTER_INFO_2
, *returned
+1)) ) {
4551 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4556 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned
+ 1));
4558 memcpy(&printers
[*returned
], ¤t_prt
, sizeof(PRINTER_INFO_2
));
4565 /* check the required size. */
4566 for (i
=0; i
<*returned
; i
++)
4567 (*needed
) += spoolss_size_printer_info_2(&printers
[i
]);
4569 if (*needed
> offered
) {
4570 result
= WERR_INSUFFICIENT_BUFFER
;
4574 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4575 result
= WERR_NOMEM
;
4579 /* fill the buffer with the structures */
4580 for (i
=0; i
<*returned
; i
++)
4581 smb_io_printer_info_2("", buffer
, &(printers
[i
]), 0);
4586 for (i
=0; i
<*returned
; i
++)
4587 free_devmode(printers
[i
].devmode
);
4589 SAFE_FREE(printers
);
4591 if ( !W_ERROR_IS_OK(result
) )
4597 /********************************************************************
4598 * handle enumeration of printers at level 1
4599 ********************************************************************/
4601 static WERROR
enumprinters_level1( uint32 flags
, fstring name
,
4602 RPC_BUFFER
*buffer
, uint32 offered
,
4603 uint32
*needed
, uint32
*returned
)
4605 /* Not all the flags are equals */
4607 if (flags
& PRINTER_ENUM_LOCAL
)
4608 return enum_all_printers_info_1_local(buffer
, offered
, needed
, returned
);
4610 if (flags
& PRINTER_ENUM_NAME
)
4611 return enum_all_printers_info_1_name(name
, buffer
, offered
, needed
, returned
);
4613 #if 0 /* JERRY - disabled for now */
4614 if (flags
& PRINTER_ENUM_REMOTE
)
4615 return enum_all_printers_info_1_remote(name
, buffer
, offered
, needed
, returned
);
4618 if (flags
& PRINTER_ENUM_NETWORK
)
4619 return enum_all_printers_info_1_network(name
, buffer
, offered
, needed
, returned
);
4621 return WERR_OK
; /* NT4sp5 does that */
4624 /********************************************************************
4625 * handle enumeration of printers at level 2
4626 ********************************************************************/
4628 static WERROR
enumprinters_level2( uint32 flags
, fstring servername
,
4629 RPC_BUFFER
*buffer
, uint32 offered
,
4630 uint32
*needed
, uint32
*returned
)
4632 char *s
= servername
;
4634 if (flags
& PRINTER_ENUM_LOCAL
) {
4635 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4638 if (flags
& PRINTER_ENUM_NAME
) {
4639 if ((servername
[0] == '\\') && (servername
[1] == '\\'))
4641 if (is_myname_or_ipaddr(s
))
4642 return enum_all_printers_info_2(buffer
, offered
, needed
, returned
);
4644 return WERR_INVALID_NAME
;
4647 if (flags
& PRINTER_ENUM_REMOTE
)
4648 return WERR_UNKNOWN_LEVEL
;
4653 /********************************************************************
4654 * handle enumeration of printers at level 5
4655 ********************************************************************/
4657 static WERROR
enumprinters_level5( uint32 flags
, fstring servername
,
4658 RPC_BUFFER
*buffer
, uint32 offered
,
4659 uint32
*needed
, uint32
*returned
)
4661 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4665 /********************************************************************
4666 * api_spoolss_enumprinters
4668 * called from api_spoolss_enumprinters (see this to understand)
4669 ********************************************************************/
4671 WERROR
_spoolss_enumprinters( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERS
*q_u
, SPOOL_R_ENUMPRINTERS
*r_u
)
4673 uint32 flags
= q_u
->flags
;
4674 UNISTR2
*servername
= &q_u
->servername
;
4675 uint32 level
= q_u
->level
;
4676 RPC_BUFFER
*buffer
= NULL
;
4677 uint32 offered
= q_u
->offered
;
4678 uint32
*needed
= &r_u
->needed
;
4679 uint32
*returned
= &r_u
->returned
;
4683 /* that's an [in out] buffer */
4685 if (!q_u
->buffer
&& (offered
!=0)) {
4686 return WERR_INVALID_PARAM
;
4689 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
4690 buffer
= r_u
->buffer
;
4692 DEBUG(4,("_spoolss_enumprinters\n"));
4699 * flags==PRINTER_ENUM_NAME
4700 * if name=="" then enumerates all printers
4701 * if name!="" then enumerate the printer
4702 * flags==PRINTER_ENUM_REMOTE
4703 * name is NULL, enumerate printers
4704 * Level 2: name!="" enumerates printers, name can't be NULL
4705 * Level 3: doesn't exist
4706 * Level 4: does a local registry lookup
4707 * Level 5: same as Level 2
4710 unistr2_to_ascii(name
, servername
, sizeof(name
)-1);
4715 return enumprinters_level1(flags
, name
, buffer
, offered
, needed
, returned
);
4717 return enumprinters_level2(flags
, name
, buffer
, offered
, needed
, returned
);
4719 return enumprinters_level5(flags
, name
, buffer
, offered
, needed
, returned
);
4724 return WERR_UNKNOWN_LEVEL
;
4727 /****************************************************************************
4728 ****************************************************************************/
4730 static WERROR
getprinter_level_0(Printer_entry
*print_hnd
,
4731 const struct share_params
*params
,
4732 RPC_BUFFER
*buffer
, uint32 offered
,
4735 PRINTER_INFO_0
*printer
=NULL
;
4736 WERROR result
= WERR_OK
;
4738 if((printer
=SMB_MALLOC_P(PRINTER_INFO_0
)) == NULL
)
4741 construct_printer_info_0(print_hnd
, printer
, params
);
4743 /* check the required size. */
4744 *needed
+= spoolss_size_printer_info_0(printer
);
4746 if (*needed
> offered
) {
4747 result
= WERR_INSUFFICIENT_BUFFER
;
4751 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4752 result
= WERR_NOMEM
;
4756 /* fill the buffer with the structures */
4757 smb_io_printer_info_0("", buffer
, printer
, 0);
4767 /****************************************************************************
4768 ****************************************************************************/
4770 static WERROR
getprinter_level_1(Printer_entry
*print_hnd
,
4771 const struct share_params
*params
,
4772 RPC_BUFFER
*buffer
, uint32 offered
,
4775 PRINTER_INFO_1
*printer
=NULL
;
4776 WERROR result
= WERR_OK
;
4778 if((printer
=SMB_MALLOC_P(PRINTER_INFO_1
)) == NULL
)
4781 construct_printer_info_1(print_hnd
, PRINTER_ENUM_ICON8
, printer
,
4784 /* check the required size. */
4785 *needed
+= spoolss_size_printer_info_1(printer
);
4787 if (*needed
> offered
) {
4788 result
= WERR_INSUFFICIENT_BUFFER
;
4792 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4793 result
= WERR_NOMEM
;
4797 /* fill the buffer with the structures */
4798 smb_io_printer_info_1("", buffer
, printer
, 0);
4807 /****************************************************************************
4808 ****************************************************************************/
4810 static WERROR
getprinter_level_2(Printer_entry
*print_hnd
,
4811 const struct share_params
*params
,
4812 RPC_BUFFER
*buffer
, uint32 offered
,
4815 PRINTER_INFO_2
*printer
=NULL
;
4816 WERROR result
= WERR_OK
;
4818 if((printer
=SMB_MALLOC_P(PRINTER_INFO_2
))==NULL
)
4821 construct_printer_info_2(print_hnd
, printer
, params
);
4823 /* check the required size. */
4824 *needed
+= spoolss_size_printer_info_2(printer
);
4826 if (*needed
> offered
) {
4827 result
= WERR_INSUFFICIENT_BUFFER
;
4831 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4832 result
= WERR_NOMEM
;
4836 /* fill the buffer with the structures */
4837 if (!smb_io_printer_info_2("", buffer
, printer
, 0))
4838 result
= WERR_NOMEM
;
4842 free_printer_info_2(printer
);
4847 /****************************************************************************
4848 ****************************************************************************/
4850 static WERROR
getprinter_level_3(Printer_entry
*print_hnd
,
4851 const struct share_params
*params
,
4852 RPC_BUFFER
*buffer
, uint32 offered
,
4855 PRINTER_INFO_3
*printer
=NULL
;
4856 WERROR result
= WERR_OK
;
4858 if (!construct_printer_info_3(print_hnd
, &printer
, params
))
4861 /* check the required size. */
4862 *needed
+= spoolss_size_printer_info_3(printer
);
4864 if (*needed
> offered
) {
4865 result
= WERR_INSUFFICIENT_BUFFER
;
4869 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4870 result
= WERR_NOMEM
;
4874 /* fill the buffer with the structures */
4875 smb_io_printer_info_3("", buffer
, printer
, 0);
4879 free_printer_info_3(printer
);
4884 /****************************************************************************
4885 ****************************************************************************/
4887 static WERROR
getprinter_level_4(Printer_entry
*print_hnd
,
4888 const struct share_params
*params
,
4889 RPC_BUFFER
*buffer
, uint32 offered
,
4892 PRINTER_INFO_4
*printer
=NULL
;
4893 WERROR result
= WERR_OK
;
4895 if((printer
=SMB_MALLOC_P(PRINTER_INFO_4
))==NULL
)
4898 if (!construct_printer_info_4(print_hnd
, printer
, params
)) {
4903 /* check the required size. */
4904 *needed
+= spoolss_size_printer_info_4(printer
);
4906 if (*needed
> offered
) {
4907 result
= WERR_INSUFFICIENT_BUFFER
;
4911 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4912 result
= WERR_NOMEM
;
4916 /* fill the buffer with the structures */
4917 smb_io_printer_info_4("", buffer
, printer
, 0);
4921 free_printer_info_4(printer
);
4926 /****************************************************************************
4927 ****************************************************************************/
4929 static WERROR
getprinter_level_5(Printer_entry
*print_hnd
,
4930 const struct share_params
*params
,
4931 RPC_BUFFER
*buffer
, uint32 offered
,
4934 PRINTER_INFO_5
*printer
=NULL
;
4935 WERROR result
= WERR_OK
;
4937 if((printer
=SMB_MALLOC_P(PRINTER_INFO_5
))==NULL
)
4940 if (!construct_printer_info_5(print_hnd
, printer
, params
)) {
4941 free_printer_info_5(printer
);
4945 /* check the required size. */
4946 *needed
+= spoolss_size_printer_info_5(printer
);
4948 if (*needed
> offered
) {
4949 result
= WERR_INSUFFICIENT_BUFFER
;
4953 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4954 result
= WERR_NOMEM
;
4958 /* fill the buffer with the structures */
4959 smb_io_printer_info_5("", buffer
, printer
, 0);
4963 free_printer_info_5(printer
);
4968 static WERROR
getprinter_level_6(Printer_entry
*print_hnd
,
4969 const struct share_params
*params
,
4970 RPC_BUFFER
*buffer
, uint32 offered
,
4973 PRINTER_INFO_6
*printer
;
4974 WERROR result
= WERR_OK
;
4976 if ((printer
= SMB_MALLOC_P(PRINTER_INFO_6
)) == NULL
) {
4980 if (!construct_printer_info_6(print_hnd
, printer
, params
)) {
4981 free_printer_info_6(printer
);
4985 /* check the required size. */
4986 *needed
+= spoolss_size_printer_info_6(printer
);
4988 if (*needed
> offered
) {
4989 result
= WERR_INSUFFICIENT_BUFFER
;
4993 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
4994 result
= WERR_NOMEM
;
4998 /* fill the buffer with the structures */
4999 smb_io_printer_info_6("", buffer
, printer
, 0);
5003 free_printer_info_6(printer
);
5008 static WERROR
getprinter_level_7(Printer_entry
*print_hnd
,
5009 const struct share_params
*params
,
5010 RPC_BUFFER
*buffer
, uint32 offered
,
5013 PRINTER_INFO_7
*printer
=NULL
;
5014 WERROR result
= WERR_OK
;
5016 if((printer
=SMB_MALLOC_P(PRINTER_INFO_7
))==NULL
)
5019 if (!construct_printer_info_7(print_hnd
, printer
, params
))
5022 /* check the required size. */
5023 *needed
+= spoolss_size_printer_info_7(printer
);
5025 if (*needed
> offered
) {
5026 result
= WERR_INSUFFICIENT_BUFFER
;
5030 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5031 result
= WERR_NOMEM
;
5036 /* fill the buffer with the structures */
5037 smb_io_printer_info_7("", buffer
, printer
, 0);
5041 free_printer_info_7(printer
);
5046 /****************************************************************************
5047 ****************************************************************************/
5049 WERROR
_spoolss_getprinter(pipes_struct
*p
, SPOOL_Q_GETPRINTER
*q_u
, SPOOL_R_GETPRINTER
*r_u
)
5051 POLICY_HND
*handle
= &q_u
->handle
;
5052 uint32 level
= q_u
->level
;
5053 RPC_BUFFER
*buffer
= NULL
;
5054 uint32 offered
= q_u
->offered
;
5055 uint32
*needed
= &r_u
->needed
;
5056 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
5057 struct share_params
*params
;
5061 /* that's an [in out] buffer */
5063 if (!q_u
->buffer
&& (offered
!=0)) {
5064 return WERR_INVALID_PARAM
;
5067 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5068 buffer
= r_u
->buffer
;
5072 if (!get_printer_snum(p
, handle
, &snum
, ¶ms
))
5077 return getprinter_level_0(Printer
, params
, buffer
, offered
,
5080 return getprinter_level_1(Printer
, params
, buffer
, offered
,
5083 return getprinter_level_2(Printer
, params
, buffer
, offered
,
5086 return getprinter_level_3(Printer
, params
, buffer
, offered
,
5089 return getprinter_level_4(Printer
, params
, buffer
, offered
,
5092 return getprinter_level_5(Printer
, params
, buffer
, offered
,
5095 return getprinter_level_6(Printer
, params
, buffer
, offered
,
5098 return getprinter_level_7(Printer
, params
, buffer
, offered
,
5101 return WERR_UNKNOWN_LEVEL
;
5104 /********************************************************************
5105 * fill a DRIVER_INFO_1 struct
5106 ********************************************************************/
5108 static void fill_printer_driver_info_1(DRIVER_INFO_1
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
, fstring architecture
)
5110 init_unistr( &info
->name
, driver
.info_3
->name
);
5113 /********************************************************************
5114 * construct_printer_driver_info_1
5115 ********************************************************************/
5117 static WERROR
construct_printer_driver_info_1(DRIVER_INFO_1
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5119 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5120 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5122 ZERO_STRUCT(driver
);
5124 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5125 return WERR_INVALID_PRINTER_NAME
;
5127 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5128 free_a_printer(&printer
, 2);
5129 return WERR_UNKNOWN_PRINTER_DRIVER
;
5132 fill_printer_driver_info_1(info
, driver
, servername
, architecture
);
5134 free_a_printer(&printer
,2);
5139 /********************************************************************
5140 * construct_printer_driver_info_2
5141 * fill a printer_info_2 struct
5142 ********************************************************************/
5144 static void fill_printer_driver_info_2(DRIVER_INFO_2
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5148 info
->version
=driver
.info_3
->cversion
;
5150 init_unistr( &info
->name
, driver
.info_3
->name
);
5151 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5154 if (strlen(driver
.info_3
->driverpath
)) {
5155 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5156 init_unistr( &info
->driverpath
, temp
);
5158 init_unistr( &info
->driverpath
, "" );
5160 if (strlen(driver
.info_3
->datafile
)) {
5161 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5162 init_unistr( &info
->datafile
, temp
);
5164 init_unistr( &info
->datafile
, "" );
5166 if (strlen(driver
.info_3
->configfile
)) {
5167 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5168 init_unistr( &info
->configfile
, temp
);
5170 init_unistr( &info
->configfile
, "" );
5173 /********************************************************************
5174 * construct_printer_driver_info_2
5175 * fill a printer_info_2 struct
5176 ********************************************************************/
5178 static WERROR
construct_printer_driver_info_2(DRIVER_INFO_2
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5180 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5181 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5183 ZERO_STRUCT(printer
);
5184 ZERO_STRUCT(driver
);
5186 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
))))
5187 return WERR_INVALID_PRINTER_NAME
;
5189 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
))) {
5190 free_a_printer(&printer
, 2);
5191 return WERR_UNKNOWN_PRINTER_DRIVER
;
5194 fill_printer_driver_info_2(info
, driver
, servername
);
5196 free_a_printer(&printer
,2);
5201 /********************************************************************
5202 * copy a strings array and convert to UNICODE
5204 * convert an array of ascii string to a UNICODE string
5205 ********************************************************************/
5207 static uint32
init_unistr_array(uint16
**uni_array
, fstring
*char_array
, const char *servername
)
5214 DEBUG(6,("init_unistr_array\n"));
5225 v
= ""; /* hack to handle null lists */
5228 /* hack to allow this to be used in places other than when generating
5229 the list of dependent files */
5232 slprintf( line
, sizeof(line
)-1, "\\\\%s%s", servername
, v
);
5236 DEBUGADD(6,("%d:%s:%lu\n", i
, line
, (unsigned long)strlen(line
)));
5238 /* add one extra unit16 for the second terminating NULL */
5240 if ( (*uni_array
=SMB_REALLOC_ARRAY(*uni_array
, uint16
, j
+1+strlen(line
)+2)) == NULL
) {
5241 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5248 j
+= (rpcstr_push((*uni_array
+j
), line
, sizeof(uint16
)*strlen(line
)+2, STR_TERMINATE
) / sizeof(uint16
));
5253 /* special case for ""; we need to add both NULL's here */
5255 (*uni_array
)[j
++]=0x0000;
5256 (*uni_array
)[j
]=0x0000;
5259 DEBUGADD(6,("last one:done\n"));
5261 /* return size of array in uint16's */
5266 /********************************************************************
5267 * construct_printer_info_3
5268 * fill a printer_info_3 struct
5269 ********************************************************************/
5271 static void fill_printer_driver_info_3(DRIVER_INFO_3
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5277 info
->version
=driver
.info_3
->cversion
;
5279 init_unistr( &info
->name
, driver
.info_3
->name
);
5280 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5282 if (strlen(driver
.info_3
->driverpath
)) {
5283 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5284 init_unistr( &info
->driverpath
, temp
);
5286 init_unistr( &info
->driverpath
, "" );
5288 if (strlen(driver
.info_3
->datafile
)) {
5289 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5290 init_unistr( &info
->datafile
, temp
);
5292 init_unistr( &info
->datafile
, "" );
5294 if (strlen(driver
.info_3
->configfile
)) {
5295 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5296 init_unistr( &info
->configfile
, temp
);
5298 init_unistr( &info
->configfile
, "" );
5300 if (strlen(driver
.info_3
->helpfile
)) {
5301 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5302 init_unistr( &info
->helpfile
, temp
);
5304 init_unistr( &info
->helpfile
, "" );
5306 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5307 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5309 info
->dependentfiles
=NULL
;
5310 init_unistr_array(&info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5313 /********************************************************************
5314 * construct_printer_info_3
5315 * fill a printer_info_3 struct
5316 ********************************************************************/
5318 static WERROR
construct_printer_driver_info_3(DRIVER_INFO_3
*info
, int snum
, fstring servername
, fstring architecture
, uint32 version
)
5320 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5321 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5323 ZERO_STRUCT(driver
);
5325 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5326 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5327 if (!W_ERROR_IS_OK(status
))
5328 return WERR_INVALID_PRINTER_NAME
;
5330 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5331 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5336 * I put this code in during testing. Helpful when commenting out the
5337 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5338 * as win2k always queries the driver using an infor level of 6.
5339 * I've left it in (but ifdef'd out) because I'll probably
5340 * use it in experimentation again in the future. --jerry 22/01/2002
5343 if (!W_ERROR_IS_OK(status
)) {
5345 * Is this a W2k client ?
5348 /* Yes - try again with a WinNT driver. */
5350 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5351 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status
)));
5355 if (!W_ERROR_IS_OK(status
)) {
5356 free_a_printer(&printer
,2);
5357 return WERR_UNKNOWN_PRINTER_DRIVER
;
5365 fill_printer_driver_info_3(info
, driver
, servername
);
5367 free_a_printer(&printer
,2);
5372 /********************************************************************
5373 * construct_printer_info_6
5374 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5375 ********************************************************************/
5377 static void fill_printer_driver_info_6(DRIVER_INFO_6
*info
, NT_PRINTER_DRIVER_INFO_LEVEL driver
, fstring servername
)
5383 memset(&nullstr
, '\0', sizeof(fstring
));
5385 info
->version
=driver
.info_3
->cversion
;
5387 init_unistr( &info
->name
, driver
.info_3
->name
);
5388 init_unistr( &info
->architecture
, driver
.info_3
->environment
);
5390 if (strlen(driver
.info_3
->driverpath
)) {
5391 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->driverpath
);
5392 init_unistr( &info
->driverpath
, temp
);
5394 init_unistr( &info
->driverpath
, "" );
5396 if (strlen(driver
.info_3
->datafile
)) {
5397 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->datafile
);
5398 init_unistr( &info
->datafile
, temp
);
5400 init_unistr( &info
->datafile
, "" );
5402 if (strlen(driver
.info_3
->configfile
)) {
5403 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->configfile
);
5404 init_unistr( &info
->configfile
, temp
);
5406 init_unistr( &info
->configfile
, "" );
5408 if (strlen(driver
.info_3
->helpfile
)) {
5409 slprintf(temp
, sizeof(temp
)-1, "\\\\%s%s", servername
, driver
.info_3
->helpfile
);
5410 init_unistr( &info
->helpfile
, temp
);
5412 init_unistr( &info
->helpfile
, "" );
5414 init_unistr( &info
->monitorname
, driver
.info_3
->monitorname
);
5415 init_unistr( &info
->defaultdatatype
, driver
.info_3
->defaultdatatype
);
5417 info
->dependentfiles
= NULL
;
5418 init_unistr_array( &info
->dependentfiles
, driver
.info_3
->dependentfiles
, servername
);
5420 info
->previousdrivernames
=NULL
;
5421 init_unistr_array(&info
->previousdrivernames
, &nullstr
, servername
);
5423 info
->driver_date
=0;
5426 info
->driver_version_low
=0;
5427 info
->driver_version_high
=0;
5429 init_unistr( &info
->mfgname
, "");
5430 init_unistr( &info
->oem_url
, "");
5431 init_unistr( &info
->hardware_id
, "");
5432 init_unistr( &info
->provider
, "");
5435 /********************************************************************
5436 * construct_printer_info_6
5437 * fill a printer_info_6 struct
5438 ********************************************************************/
5440 static WERROR
construct_printer_driver_info_6(DRIVER_INFO_6
*info
, int snum
,
5441 fstring servername
, fstring architecture
, uint32 version
)
5443 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5444 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
5447 ZERO_STRUCT(driver
);
5449 status
=get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
) );
5451 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5453 if (!W_ERROR_IS_OK(status
))
5454 return WERR_INVALID_PRINTER_NAME
;
5456 status
= get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5458 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5460 if (!W_ERROR_IS_OK(status
))
5463 * Is this a W2k client ?
5467 free_a_printer(&printer
,2);
5468 return WERR_UNKNOWN_PRINTER_DRIVER
;
5471 /* Yes - try again with a WinNT driver. */
5473 status
=get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
, architecture
, version
);
5474 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status
)));
5475 if (!W_ERROR_IS_OK(status
)) {
5476 free_a_printer(&printer
,2);
5477 return WERR_UNKNOWN_PRINTER_DRIVER
;
5481 fill_printer_driver_info_6(info
, driver
, servername
);
5483 free_a_printer(&printer
,2);
5484 free_a_printer_driver(driver
, 3);
5489 /****************************************************************************
5490 ****************************************************************************/
5492 static void free_printer_driver_info_3(DRIVER_INFO_3
*info
)
5494 SAFE_FREE(info
->dependentfiles
);
5497 /****************************************************************************
5498 ****************************************************************************/
5500 static void free_printer_driver_info_6(DRIVER_INFO_6
*info
)
5502 SAFE_FREE(info
->dependentfiles
);
5505 /****************************************************************************
5506 ****************************************************************************/
5508 static WERROR
getprinterdriver2_level1(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5510 DRIVER_INFO_1
*info
=NULL
;
5513 if((info
=SMB_MALLOC_P(DRIVER_INFO_1
)) == NULL
)
5516 result
= construct_printer_driver_info_1(info
, snum
, servername
, architecture
, version
);
5517 if (!W_ERROR_IS_OK(result
))
5520 /* check the required size. */
5521 *needed
+= spoolss_size_printer_driver_info_1(info
);
5523 if (*needed
> offered
) {
5524 result
= WERR_INSUFFICIENT_BUFFER
;
5528 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5529 result
= WERR_NOMEM
;
5533 /* fill the buffer with the structures */
5534 smb_io_printer_driver_info_1("", buffer
, info
, 0);
5543 /****************************************************************************
5544 ****************************************************************************/
5546 static WERROR
getprinterdriver2_level2(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5548 DRIVER_INFO_2
*info
=NULL
;
5551 if((info
=SMB_MALLOC_P(DRIVER_INFO_2
)) == NULL
)
5554 result
= construct_printer_driver_info_2(info
, snum
, servername
, architecture
, version
);
5555 if (!W_ERROR_IS_OK(result
))
5558 /* check the required size. */
5559 *needed
+= spoolss_size_printer_driver_info_2(info
);
5561 if (*needed
> offered
) {
5562 result
= WERR_INSUFFICIENT_BUFFER
;
5566 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5567 result
= WERR_NOMEM
;
5571 /* fill the buffer with the structures */
5572 smb_io_printer_driver_info_2("", buffer
, info
, 0);
5581 /****************************************************************************
5582 ****************************************************************************/
5584 static WERROR
getprinterdriver2_level3(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5591 result
= construct_printer_driver_info_3(&info
, snum
, servername
, architecture
, version
);
5592 if (!W_ERROR_IS_OK(result
))
5595 /* check the required size. */
5596 *needed
+= spoolss_size_printer_driver_info_3(&info
);
5598 if (*needed
> offered
) {
5599 result
= WERR_INSUFFICIENT_BUFFER
;
5603 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5604 result
= WERR_NOMEM
;
5608 /* fill the buffer with the structures */
5609 smb_io_printer_driver_info_3("", buffer
, &info
, 0);
5612 free_printer_driver_info_3(&info
);
5617 /****************************************************************************
5618 ****************************************************************************/
5620 static WERROR
getprinterdriver2_level6(fstring servername
, fstring architecture
, uint32 version
, int snum
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
5627 result
= construct_printer_driver_info_6(&info
, snum
, servername
, architecture
, version
);
5628 if (!W_ERROR_IS_OK(result
))
5631 /* check the required size. */
5632 *needed
+= spoolss_size_printer_driver_info_6(&info
);
5634 if (*needed
> offered
) {
5635 result
= WERR_INSUFFICIENT_BUFFER
;
5639 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
5640 result
= WERR_NOMEM
;
5644 /* fill the buffer with the structures */
5645 smb_io_printer_driver_info_6("", buffer
, &info
, 0);
5648 free_printer_driver_info_6(&info
);
5653 /****************************************************************************
5654 ****************************************************************************/
5656 WERROR
_spoolss_getprinterdriver2(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVER2
*q_u
, SPOOL_R_GETPRINTERDRIVER2
*r_u
)
5658 POLICY_HND
*handle
= &q_u
->handle
;
5659 UNISTR2
*uni_arch
= &q_u
->architecture
;
5660 uint32 level
= q_u
->level
;
5661 uint32 clientmajorversion
= q_u
->clientmajorversion
;
5662 RPC_BUFFER
*buffer
= NULL
;
5663 uint32 offered
= q_u
->offered
;
5664 uint32
*needed
= &r_u
->needed
;
5665 uint32
*servermajorversion
= &r_u
->servermajorversion
;
5666 uint32
*serverminorversion
= &r_u
->serverminorversion
;
5667 Printer_entry
*printer
;
5670 fstring architecture
;
5673 /* that's an [in out] buffer */
5675 if (!q_u
->buffer
&& (offered
!=0)) {
5676 return WERR_INVALID_PARAM
;
5679 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
5680 buffer
= r_u
->buffer
;
5682 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5684 if ( !(printer
= find_printer_index_by_hnd( p
, handle
)) ) {
5685 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5686 return WERR_INVALID_PRINTER_NAME
;
5690 *servermajorversion
= 0;
5691 *serverminorversion
= 0;
5693 fstrcpy(servername
, get_server_name( printer
));
5694 unistr2_to_ascii(architecture
, uni_arch
, sizeof(architecture
)-1);
5696 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5701 return getprinterdriver2_level1(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5703 return getprinterdriver2_level2(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5705 return getprinterdriver2_level3(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5707 return getprinterdriver2_level6(servername
, architecture
, clientmajorversion
, snum
, buffer
, offered
, needed
);
5710 /* apparently this call is the equivalent of
5711 EnumPrinterDataEx() for the DsDriver key */
5716 return WERR_UNKNOWN_LEVEL
;
5719 /****************************************************************************
5720 ****************************************************************************/
5722 WERROR
_spoolss_startpageprinter(pipes_struct
*p
, SPOOL_Q_STARTPAGEPRINTER
*q_u
, SPOOL_R_STARTPAGEPRINTER
*r_u
)
5724 POLICY_HND
*handle
= &q_u
->handle
;
5726 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5729 DEBUG(3,("Error in startpageprinter printer handle\n"));
5733 Printer
->page_started
=True
;
5737 /****************************************************************************
5738 ****************************************************************************/
5740 WERROR
_spoolss_endpageprinter(pipes_struct
*p
, SPOOL_Q_ENDPAGEPRINTER
*q_u
, SPOOL_R_ENDPAGEPRINTER
*r_u
)
5742 POLICY_HND
*handle
= &q_u
->handle
;
5745 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5748 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle
)));
5752 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5755 Printer
->page_started
=False
;
5756 print_job_endpage(snum
, Printer
->jobid
);
5761 /********************************************************************
5762 * api_spoolss_getprinter
5763 * called from the spoolss dispatcher
5765 ********************************************************************/
5767 WERROR
_spoolss_startdocprinter(pipes_struct
*p
, SPOOL_Q_STARTDOCPRINTER
*q_u
, SPOOL_R_STARTDOCPRINTER
*r_u
)
5769 POLICY_HND
*handle
= &q_u
->handle
;
5770 DOC_INFO
*docinfo
= &q_u
->doc_info_container
.docinfo
;
5771 uint32
*jobid
= &r_u
->jobid
;
5773 DOC_INFO_1
*info_1
= &docinfo
->doc_info_1
;
5777 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5780 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5785 * a nice thing with NT is it doesn't listen to what you tell it.
5786 * when asked to send _only_ RAW datas, it tries to send datas
5789 * So I add checks like in NT Server ...
5792 if (info_1
->p_datatype
!= 0) {
5793 unistr2_to_ascii(datatype
, &info_1
->datatype
, sizeof(datatype
));
5794 if (strcmp(datatype
, "RAW") != 0) {
5796 return WERR_INVALID_DATATYPE
;
5800 /* get the share number of the printer */
5801 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
5805 unistr2_to_ascii(jobname
, &info_1
->docname
, sizeof(jobname
));
5807 Printer
->jobid
= print_job_start(&p
->pipe_user
, snum
, jobname
, Printer
->nt_devmode
);
5809 /* An error occured in print_job_start() so return an appropriate
5812 if (Printer
->jobid
== -1) {
5813 return map_werror_from_unix(errno
);
5816 Printer
->document_started
=True
;
5817 (*jobid
) = Printer
->jobid
;
5822 /********************************************************************
5823 * api_spoolss_getprinter
5824 * called from the spoolss dispatcher
5826 ********************************************************************/
5828 WERROR
_spoolss_enddocprinter(pipes_struct
*p
, SPOOL_Q_ENDDOCPRINTER
*q_u
, SPOOL_R_ENDDOCPRINTER
*r_u
)
5830 POLICY_HND
*handle
= &q_u
->handle
;
5832 return _spoolss_enddocprinter_internal(p
, handle
);
5835 /****************************************************************************
5836 ****************************************************************************/
5838 WERROR
_spoolss_writeprinter(pipes_struct
*p
, SPOOL_Q_WRITEPRINTER
*q_u
, SPOOL_R_WRITEPRINTER
*r_u
)
5840 POLICY_HND
*handle
= &q_u
->handle
;
5841 uint32 buffer_size
= q_u
->buffer_size
;
5842 uint8
*buffer
= q_u
->buffer
;
5843 uint32
*buffer_written
= &q_u
->buffer_size2
;
5845 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5848 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5849 r_u
->buffer_written
= q_u
->buffer_size2
;
5853 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5856 (*buffer_written
) = (uint32
)print_job_write(snum
, Printer
->jobid
, (const char *)buffer
,
5857 (SMB_OFF_T
)-1, (size_t)buffer_size
);
5858 if (*buffer_written
== (uint32
)-1) {
5859 r_u
->buffer_written
= 0;
5860 if (errno
== ENOSPC
)
5861 return WERR_NO_SPOOL_SPACE
;
5863 return WERR_ACCESS_DENIED
;
5866 r_u
->buffer_written
= q_u
->buffer_size2
;
5871 /********************************************************************
5872 * api_spoolss_getprinter
5873 * called from the spoolss dispatcher
5875 ********************************************************************/
5877 static WERROR
control_printer(POLICY_HND
*handle
, uint32 command
,
5881 WERROR errcode
= WERR_BADFUNC
;
5882 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5885 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
5889 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5893 case PRINTER_CONTROL_PAUSE
:
5894 if (print_queue_pause(&p
->pipe_user
, snum
, &errcode
)) {
5898 case PRINTER_CONTROL_RESUME
:
5899 case PRINTER_CONTROL_UNPAUSE
:
5900 if (print_queue_resume(&p
->pipe_user
, snum
, &errcode
)) {
5904 case PRINTER_CONTROL_PURGE
:
5905 if (print_queue_purge(&p
->pipe_user
, snum
, &errcode
)) {
5910 return WERR_UNKNOWN_LEVEL
;
5916 /********************************************************************
5917 * api_spoolss_abortprinter
5918 * From MSDN: "Deletes printer's spool file if printer is configured
5920 ********************************************************************/
5922 WERROR
_spoolss_abortprinter(pipes_struct
*p
, SPOOL_Q_ABORTPRINTER
*q_u
, SPOOL_R_ABORTPRINTER
*r_u
)
5924 POLICY_HND
*handle
= &q_u
->handle
;
5925 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5927 WERROR errcode
= WERR_OK
;
5930 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle
)));
5934 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5937 print_job_delete( &p
->pipe_user
, snum
, Printer
->jobid
, &errcode
);
5942 /********************************************************************
5943 * called by spoolss_api_setprinter
5944 * when updating a printer description
5945 ********************************************************************/
5947 static WERROR
update_printer_sec(POLICY_HND
*handle
, uint32 level
,
5948 const SPOOL_PRINTER_INFO_LEVEL
*info
,
5949 pipes_struct
*p
, SEC_DESC_BUF
*secdesc_ctr
)
5951 SEC_DESC_BUF
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5955 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5957 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5958 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5959 OUR_HANDLE(handle
)));
5961 result
= WERR_BADFID
;
5965 /* Check the user has permissions to change the security
5966 descriptor. By experimentation with two NT machines, the user
5967 requires Full Access to the printer to change security
5970 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5971 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5972 result
= WERR_ACCESS_DENIED
;
5976 /* NT seems to like setting the security descriptor even though
5977 nothing may have actually changed. */
5979 nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
);
5981 if (DEBUGLEVEL
>= 10) {
5985 the_acl
= old_secdesc_ctr
->sd
->dacl
;
5986 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5987 PRINTERNAME(snum
), the_acl
->num_aces
));
5989 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5992 sid_to_string(sid_str
, &the_acl
->aces
[i
].trustee
);
5994 DEBUG(10, ("%s 0x%08x\n", sid_str
,
5995 the_acl
->aces
[i
].access_mask
));
5998 the_acl
= secdesc_ctr
->sd
->dacl
;
6001 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6002 PRINTERNAME(snum
), the_acl
->num_aces
));
6004 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6007 sid_to_string(sid_str
, &the_acl
->aces
[i
].trustee
);
6009 DEBUG(10, ("%s 0x%08x\n", sid_str
,
6010 the_acl
->aces
[i
].access_mask
));
6013 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6017 new_secdesc_ctr
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
6018 if (!new_secdesc_ctr
) {
6019 result
= WERR_NOMEM
;
6023 if (sec_desc_equal(new_secdesc_ctr
->sd
, old_secdesc_ctr
->sd
)) {
6028 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
6035 /********************************************************************
6036 Canonicalize printer info from a client
6038 ATTN: It does not matter what we set the servername to hear
6039 since we do the necessary work in get_a_printer() to set it to
6040 the correct value based on what the client sent in the
6041 _spoolss_open_printer_ex().
6042 ********************************************************************/
6044 static BOOL
check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
6046 fstring printername
;
6049 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6050 "portname=%s drivername=%s comment=%s location=%s\n",
6051 info
->servername
, info
->printername
, info
->sharename
,
6052 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
6054 /* we force some elements to "correct" values */
6055 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
6056 fstrcpy(info
->sharename
, lp_servicename(snum
));
6058 /* check to see if we allow printername != sharename */
6060 if ( lp_force_printername(snum
) ) {
6061 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
6062 global_myname(), info
->sharename
);
6065 /* make sure printername is in \\server\printername format */
6067 fstrcpy( printername
, info
->printername
);
6069 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
6070 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
6074 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
6075 global_myname(), p
);
6078 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
6079 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
6086 /****************************************************************************
6087 ****************************************************************************/
6089 WERROR
add_port_hook(NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
6091 char *cmd
= lp_addport_cmd();
6095 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
6096 BOOL is_print_op
= False
;
6099 return WERR_ACCESS_DENIED
;
6102 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
6105 is_print_op
= user_has_privileges( token
, &se_printop
);
6107 DEBUG(10,("Running [%s]\n", command
));
6109 /********* BEGIN SePrintOperatorPrivilege **********/
6114 ret
= smbrun(command
, &fd
);
6119 /********* END SePrintOperatorPrivilege **********/
6121 DEBUGADD(10,("returned [%d]\n", ret
));
6126 return WERR_ACCESS_DENIED
;
6132 /****************************************************************************
6133 ****************************************************************************/
6135 BOOL
add_printer_hook(NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
6137 char *cmd
= lp_addprinter_cmd();
6143 fstring remote_machine
= "%m";
6144 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
6145 BOOL is_print_op
= False
;
6147 standard_sub_basic(current_user_info
.smb_name
,
6148 current_user_info
.domain
,
6149 remote_machine
,sizeof(remote_machine
));
6151 slprintf(command
, sizeof(command
)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6152 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
6153 printer
->info_2
->portname
, printer
->info_2
->drivername
,
6154 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
6157 is_print_op
= user_has_privileges( token
, &se_printop
);
6159 DEBUG(10,("Running [%s]\n", command
));
6161 /********* BEGIN SePrintOperatorPrivilege **********/
6166 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6167 /* Tell everyone we updated smb.conf. */
6168 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
6174 /********* END SePrintOperatorPrivilege **********/
6176 DEBUGADD(10,("returned [%d]\n", ret
));
6184 /* reload our services immediately */
6185 reload_services( False
);
6188 /* Get lines and convert them back to dos-codepage */
6189 qlines
= fd_lines_load(fd
, &numlines
, 0);
6190 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6193 /* Set the portname to what the script says the portname should be. */
6194 /* but don't require anything to be return from the script exit a good error code */
6197 /* Set the portname to what the script says the portname should be. */
6198 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
6199 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6202 file_lines_free(qlines
);
6207 /********************************************************************
6208 * Called by spoolss_api_setprinter
6209 * when updating a printer description.
6210 ********************************************************************/
6212 static WERROR
update_printer(pipes_struct
*p
, POLICY_HND
*handle
, uint32 level
,
6213 const SPOOL_PRINTER_INFO_LEVEL
*info
,
6214 DEVICEMODE
*devmode
)
6217 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
6218 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6223 DEBUG(8,("update_printer\n"));
6228 result
= WERR_BADFID
;
6232 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6233 result
= WERR_BADFID
;
6237 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
6238 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
6239 result
= WERR_BADFID
;
6243 DEBUGADD(8,("Converting info_2 struct\n"));
6246 * convert_printer_info converts the incoming
6247 * info from the client and overwrites the info
6248 * just read from the tdb in the pointer 'printer'.
6251 if (!convert_printer_info(info
, printer
, level
)) {
6252 result
= WERR_NOMEM
;
6257 /* we have a valid devmode
6258 convert it and link it*/
6260 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6261 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
6262 &printer
->info_2
->devmode
)) {
6263 result
= WERR_NOMEM
;
6268 /* Do sanity check on the requested changes for Samba */
6270 if (!check_printer_ok(printer
->info_2
, snum
)) {
6271 result
= WERR_INVALID_PARAM
;
6275 /* FIXME!!! If the driver has changed we really should verify that
6276 it is installed before doing much else --jerry */
6278 /* Check calling user has permission to update printer description */
6280 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6281 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6282 result
= WERR_ACCESS_DENIED
;
6286 /* Call addprinter hook */
6287 /* Check changes to see if this is really needed */
6289 if ( *lp_addprinter_cmd()
6290 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
6291 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
6292 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
6293 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
6295 /* add_printer_hook() will call reload_services() */
6297 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
6298 result
= WERR_ACCESS_DENIED
;
6304 * When a *new* driver is bound to a printer, the drivername is used to
6305 * lookup previously saved driver initialization info, which is then
6306 * bound to the printer, simulating what happens in the Windows arch.
6308 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
6310 if (!set_driver_init(printer
, 2))
6312 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6313 printer
->info_2
->drivername
));
6316 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6317 printer
->info_2
->drivername
));
6319 notify_printer_driver(snum
, printer
->info_2
->drivername
);
6323 * flag which changes actually occured. This is a small subset of
6324 * all the possible changes. We also have to update things in the
6328 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
6329 init_unistr2( &buffer
, printer
->info_2
->comment
, UNI_STR_TERMINATE
);
6330 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
6331 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6333 notify_printer_comment(snum
, printer
->info_2
->comment
);
6336 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
6337 init_unistr2( &buffer
, printer
->info_2
->sharename
, UNI_STR_TERMINATE
);
6338 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
6339 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6341 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
6344 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
6347 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
6350 pname
= printer
->info_2
->printername
;
6353 init_unistr2( &buffer
, pname
, UNI_STR_TERMINATE
);
6354 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
6355 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6357 notify_printer_printername( snum
, pname
);
6360 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
6361 init_unistr2( &buffer
, printer
->info_2
->portname
, UNI_STR_TERMINATE
);
6362 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
6363 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6365 notify_printer_port(snum
, printer
->info_2
->portname
);
6368 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
6369 init_unistr2( &buffer
, printer
->info_2
->location
, UNI_STR_TERMINATE
);
6370 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
6371 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6373 notify_printer_location(snum
, printer
->info_2
->location
);
6376 /* here we need to update some more DsSpooler keys */
6377 /* uNCName, serverName, shortServerName */
6379 init_unistr2( &buffer
, global_myname(), UNI_STR_TERMINATE
);
6380 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
6381 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6382 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
6383 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6385 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
6386 global_myname(), printer
->info_2
->sharename
);
6387 init_unistr2( &buffer
, asc_buffer
, UNI_STR_TERMINATE
);
6388 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
6389 REG_SZ
, (uint8
*)buffer
.buffer
, buffer
.uni_str_len
*2 );
6391 /* Update printer info */
6392 result
= mod_a_printer(printer
, 2);
6395 free_a_printer(&printer
, 2);
6396 free_a_printer(&old_printer
, 2);
6402 /****************************************************************************
6403 ****************************************************************************/
6404 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
, POLICY_HND
*handle
,
6405 const SPOOL_PRINTER_INFO_LEVEL
*info
)
6408 SPOOL_PRINTER_INFO_LEVEL_7
*info7
= info
->info_7
;
6410 Printer_entry
*Printer
;
6412 if ( lp_security() != SEC_ADS
) {
6413 return WERR_UNKNOWN_LEVEL
;
6416 Printer
= find_printer_index_by_hnd(p
, handle
);
6418 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6423 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6426 nt_printer_publish(Printer
, snum
, info7
->action
);
6430 return WERR_UNKNOWN_LEVEL
;
6433 /****************************************************************************
6434 ****************************************************************************/
6436 WERROR
_spoolss_setprinter(pipes_struct
*p
, SPOOL_Q_SETPRINTER
*q_u
, SPOOL_R_SETPRINTER
*r_u
)
6438 POLICY_HND
*handle
= &q_u
->handle
;
6439 uint32 level
= q_u
->level
;
6440 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
6441 DEVMODE_CTR devmode_ctr
= q_u
->devmode_ctr
;
6442 SEC_DESC_BUF
*secdesc_ctr
= q_u
->secdesc_ctr
;
6443 uint32 command
= q_u
->command
;
6446 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6449 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6453 /* check the level */
6456 return control_printer(handle
, command
, p
);
6458 result
= update_printer(p
, handle
, level
, info
, devmode_ctr
.devmode
);
6459 if (!W_ERROR_IS_OK(result
))
6462 result
= update_printer_sec(handle
, level
, info
, p
, secdesc_ctr
);
6465 return update_printer_sec(handle
, level
, info
, p
,
6468 return publish_or_unpublish_printer(p
, handle
, info
);
6470 return WERR_UNKNOWN_LEVEL
;
6474 /****************************************************************************
6475 ****************************************************************************/
6477 WERROR
_spoolss_fcpn(pipes_struct
*p
, SPOOL_Q_FCPN
*q_u
, SPOOL_R_FCPN
*r_u
)
6479 POLICY_HND
*handle
= &q_u
->handle
;
6480 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
6483 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle
)));
6487 if (Printer
->notify
.client_connected
==True
) {
6490 if ( Printer
->printer_type
== SPLHND_SERVER
)
6492 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
6493 !get_printer_snum(p
, handle
, &snum
, NULL
) )
6496 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
6499 Printer
->notify
.flags
=0;
6500 Printer
->notify
.options
=0;
6501 Printer
->notify
.localmachine
[0]='\0';
6502 Printer
->notify
.printerlocal
=0;
6503 if (Printer
->notify
.option
)
6504 free_spool_notify_option(&Printer
->notify
.option
);
6505 Printer
->notify
.client_connected
=False
;
6510 /****************************************************************************
6511 ****************************************************************************/
6513 WERROR
_spoolss_addjob(pipes_struct
*p
, SPOOL_Q_ADDJOB
*q_u
, SPOOL_R_ADDJOB
*r_u
)
6515 /* that's an [in out] buffer */
6517 if (!q_u
->buffer
&& (q_u
->offered
!=0)) {
6518 return WERR_INVALID_PARAM
;
6521 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6524 return WERR_INVALID_PARAM
; /* this is what a NT server
6525 returns for AddJob. AddJob
6526 must fail on non-local
6530 /****************************************************************************
6531 ****************************************************************************/
6533 static void fill_job_info_1(JOB_INFO_1
*job_info
, const print_queue_struct
*queue
,
6534 int position
, int snum
,
6535 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
6539 t
=gmtime(&queue
->time
);
6541 job_info
->jobid
=queue
->job
;
6542 init_unistr(&job_info
->printername
, lp_servicename(snum
));
6543 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6544 init_unistr(&job_info
->username
, queue
->fs_user
);
6545 init_unistr(&job_info
->document
, queue
->fs_file
);
6546 init_unistr(&job_info
->datatype
, "RAW");
6547 init_unistr(&job_info
->text_status
, "");
6548 job_info
->status
=nt_printj_status(queue
->status
);
6549 job_info
->priority
=queue
->priority
;
6550 job_info
->position
=position
;
6551 job_info
->totalpages
=queue
->page_count
;
6552 job_info
->pagesprinted
=0;
6554 make_systemtime(&job_info
->submitted
, t
);
6557 /****************************************************************************
6558 ****************************************************************************/
6560 static BOOL
fill_job_info_2(JOB_INFO_2
*job_info
, const print_queue_struct
*queue
,
6561 int position
, int snum
,
6562 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6563 DEVICEMODE
*devmode
)
6567 t
=gmtime(&queue
->time
);
6569 job_info
->jobid
=queue
->job
;
6571 init_unistr(&job_info
->printername
, ntprinter
->info_2
->printername
);
6573 init_unistr(&job_info
->machinename
, ntprinter
->info_2
->servername
);
6574 init_unistr(&job_info
->username
, queue
->fs_user
);
6575 init_unistr(&job_info
->document
, queue
->fs_file
);
6576 init_unistr(&job_info
->notifyname
, queue
->fs_user
);
6577 init_unistr(&job_info
->datatype
, "RAW");
6578 init_unistr(&job_info
->printprocessor
, "winprint");
6579 init_unistr(&job_info
->parameters
, "");
6580 init_unistr(&job_info
->drivername
, ntprinter
->info_2
->drivername
);
6581 init_unistr(&job_info
->text_status
, "");
6583 /* and here the security descriptor */
6585 job_info
->status
=nt_printj_status(queue
->status
);
6586 job_info
->priority
=queue
->priority
;
6587 job_info
->position
=position
;
6588 job_info
->starttime
=0;
6589 job_info
->untiltime
=0;
6590 job_info
->totalpages
=queue
->page_count
;
6591 job_info
->size
=queue
->size
;
6592 make_systemtime(&(job_info
->submitted
), t
);
6593 job_info
->timeelapsed
=0;
6594 job_info
->pagesprinted
=0;
6596 job_info
->devmode
= devmode
;
6601 /****************************************************************************
6602 Enumjobs at level 1.
6603 ****************************************************************************/
6605 static WERROR
enumjobs_level1(const print_queue_struct
*queue
, int snum
,
6606 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6607 RPC_BUFFER
*buffer
, uint32 offered
,
6608 uint32
*needed
, uint32
*returned
)
6612 WERROR result
= WERR_OK
;
6614 info
=SMB_MALLOC_ARRAY(JOB_INFO_1
,*returned
);
6620 for (i
=0; i
<*returned
; i
++)
6621 fill_job_info_1( &info
[i
], &queue
[i
], i
, snum
, ntprinter
);
6623 /* check the required size. */
6624 for (i
=0; i
<*returned
; i
++)
6625 (*needed
) += spoolss_size_job_info_1(&info
[i
]);
6627 if (*needed
> offered
) {
6628 result
= WERR_INSUFFICIENT_BUFFER
;
6632 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6633 result
= WERR_NOMEM
;
6637 /* fill the buffer with the structures */
6638 for (i
=0; i
<*returned
; i
++)
6639 smb_io_job_info_1("", buffer
, &info
[i
], 0);
6645 if ( !W_ERROR_IS_OK(result
) )
6651 /****************************************************************************
6652 Enumjobs at level 2.
6653 ****************************************************************************/
6655 static WERROR
enumjobs_level2(const print_queue_struct
*queue
, int snum
,
6656 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6657 RPC_BUFFER
*buffer
, uint32 offered
,
6658 uint32
*needed
, uint32
*returned
)
6660 JOB_INFO_2
*info
= NULL
;
6662 WERROR result
= WERR_OK
;
6663 DEVICEMODE
*devmode
= NULL
;
6665 if ( !(info
= SMB_MALLOC_ARRAY(JOB_INFO_2
,*returned
)) ) {
6670 /* this should not be a failure condition if the devmode is NULL */
6672 devmode
= construct_dev_mode(lp_const_servicename(snum
));
6674 for (i
=0; i
<*returned
; i
++)
6675 fill_job_info_2(&(info
[i
]), &queue
[i
], i
, snum
, ntprinter
, devmode
);
6677 /* check the required size. */
6678 for (i
=0; i
<*returned
; i
++)
6679 (*needed
) += spoolss_size_job_info_2(&info
[i
]);
6681 if (*needed
> offered
) {
6682 result
= WERR_INSUFFICIENT_BUFFER
;
6686 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6687 result
= WERR_NOMEM
;
6691 /* fill the buffer with the structures */
6692 for (i
=0; i
<*returned
; i
++)
6693 smb_io_job_info_2("", buffer
, &info
[i
], 0);
6696 free_devmode(devmode
);
6699 if ( !W_ERROR_IS_OK(result
) )
6706 /****************************************************************************
6708 ****************************************************************************/
6710 WERROR
_spoolss_enumjobs( pipes_struct
*p
, SPOOL_Q_ENUMJOBS
*q_u
, SPOOL_R_ENUMJOBS
*r_u
)
6712 POLICY_HND
*handle
= &q_u
->handle
;
6713 uint32 level
= q_u
->level
;
6714 RPC_BUFFER
*buffer
= NULL
;
6715 uint32 offered
= q_u
->offered
;
6716 uint32
*needed
= &r_u
->needed
;
6717 uint32
*returned
= &r_u
->returned
;
6719 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6721 print_status_struct prt_status
;
6722 print_queue_struct
*queue
=NULL
;
6724 /* that's an [in out] buffer */
6726 if (!q_u
->buffer
&& (offered
!=0)) {
6727 return WERR_INVALID_PARAM
;
6730 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
6731 buffer
= r_u
->buffer
;
6733 DEBUG(4,("_spoolss_enumjobs\n"));
6738 /* lookup the printer snum and tdb entry */
6740 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6743 wret
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6744 if ( !W_ERROR_IS_OK(wret
) )
6747 *returned
= print_queue_status(snum
, &queue
, &prt_status
);
6748 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned
, prt_status
.status
, prt_status
.message
));
6750 if (*returned
== 0) {
6752 free_a_printer(&ntprinter
, 2);
6758 wret
= enumjobs_level1(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6761 wret
= enumjobs_level2(queue
, snum
, ntprinter
, buffer
, offered
, needed
, returned
);
6765 wret
= WERR_UNKNOWN_LEVEL
;
6770 free_a_printer( &ntprinter
, 2 );
6774 /****************************************************************************
6775 ****************************************************************************/
6777 WERROR
_spoolss_schedulejob( pipes_struct
*p
, SPOOL_Q_SCHEDULEJOB
*q_u
, SPOOL_R_SCHEDULEJOB
*r_u
)
6782 /****************************************************************************
6783 ****************************************************************************/
6785 WERROR
_spoolss_setjob(pipes_struct
*p
, SPOOL_Q_SETJOB
*q_u
, SPOOL_R_SETJOB
*r_u
)
6787 POLICY_HND
*handle
= &q_u
->handle
;
6788 uint32 jobid
= q_u
->jobid
;
6789 uint32 command
= q_u
->command
;
6792 WERROR errcode
= WERR_BADFUNC
;
6794 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6798 if (!print_job_exists(lp_const_servicename(snum
), jobid
)) {
6799 return WERR_INVALID_PRINTER_NAME
;
6803 case JOB_CONTROL_CANCEL
:
6804 case JOB_CONTROL_DELETE
:
6805 if (print_job_delete(&p
->pipe_user
, snum
, jobid
, &errcode
)) {
6809 case JOB_CONTROL_PAUSE
:
6810 if (print_job_pause(&p
->pipe_user
, snum
, jobid
, &errcode
)) {
6814 case JOB_CONTROL_RESTART
:
6815 case JOB_CONTROL_RESUME
:
6816 if (print_job_resume(&p
->pipe_user
, snum
, jobid
, &errcode
)) {
6821 return WERR_UNKNOWN_LEVEL
;
6827 /****************************************************************************
6828 Enumerates all printer drivers at level 1.
6829 ****************************************************************************/
6831 static WERROR
enumprinterdrivers_level1(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6836 fstring
*list
= NULL
;
6837 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6838 DRIVER_INFO_1
*driver_info_1
=NULL
;
6839 WERROR result
= WERR_OK
;
6843 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6845 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6846 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6848 if(ndrivers
== -1) {
6849 SAFE_FREE(driver_info_1
);
6854 if((driver_info_1
=SMB_REALLOC_ARRAY(driver_info_1
, DRIVER_INFO_1
, *returned
+ndrivers
)) == NULL
) {
6855 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6861 for (i
=0; i
<ndrivers
; i
++) {
6863 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6864 ZERO_STRUCT(driver
);
6865 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6866 architecture
, version
);
6867 if (!W_ERROR_IS_OK(status
)) {
6869 SAFE_FREE(driver_info_1
);
6872 fill_printer_driver_info_1(&driver_info_1
[*returned
+i
], driver
, servername
, architecture
);
6873 free_a_printer_driver(driver
, 3);
6876 *returned
+=ndrivers
;
6880 /* check the required size. */
6881 for (i
=0; i
<*returned
; i
++) {
6882 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6883 *needed
+= spoolss_size_printer_driver_info_1(&driver_info_1
[i
]);
6886 if (*needed
> offered
) {
6887 result
= WERR_INSUFFICIENT_BUFFER
;
6891 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6892 result
= WERR_NOMEM
;
6896 /* fill the buffer with the driver structures */
6897 for (i
=0; i
<*returned
; i
++) {
6898 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6899 smb_io_printer_driver_info_1("", buffer
, &driver_info_1
[i
], 0);
6903 SAFE_FREE(driver_info_1
);
6905 if ( !W_ERROR_IS_OK(result
) )
6911 /****************************************************************************
6912 Enumerates all printer drivers at level 2.
6913 ****************************************************************************/
6915 static WERROR
enumprinterdrivers_level2(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
6920 fstring
*list
= NULL
;
6921 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
6922 DRIVER_INFO_2
*driver_info_2
=NULL
;
6923 WERROR result
= WERR_OK
;
6927 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6929 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
6930 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
6932 if(ndrivers
== -1) {
6933 SAFE_FREE(driver_info_2
);
6938 if((driver_info_2
=SMB_REALLOC_ARRAY(driver_info_2
, DRIVER_INFO_2
, *returned
+ndrivers
)) == NULL
) {
6939 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
6945 for (i
=0; i
<ndrivers
; i
++) {
6948 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6949 ZERO_STRUCT(driver
);
6950 status
= get_a_printer_driver(&driver
, 3, list
[i
],
6951 architecture
, version
);
6952 if (!W_ERROR_IS_OK(status
)) {
6954 SAFE_FREE(driver_info_2
);
6957 fill_printer_driver_info_2(&driver_info_2
[*returned
+i
], driver
, servername
);
6958 free_a_printer_driver(driver
, 3);
6961 *returned
+=ndrivers
;
6965 /* check the required size. */
6966 for (i
=0; i
<*returned
; i
++) {
6967 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
6968 *needed
+= spoolss_size_printer_driver_info_2(&(driver_info_2
[i
]));
6971 if (*needed
> offered
) {
6972 result
= WERR_INSUFFICIENT_BUFFER
;
6976 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
6977 result
= WERR_NOMEM
;
6981 /* fill the buffer with the form structures */
6982 for (i
=0; i
<*returned
; i
++) {
6983 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
6984 smb_io_printer_driver_info_2("", buffer
, &(driver_info_2
[i
]), 0);
6988 SAFE_FREE(driver_info_2
);
6990 if ( !W_ERROR_IS_OK(result
) )
6996 /****************************************************************************
6997 Enumerates all printer drivers at level 3.
6998 ****************************************************************************/
7000 static WERROR
enumprinterdrivers_level3(fstring servername
, fstring architecture
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7005 fstring
*list
= NULL
;
7006 DRIVER_INFO_3
*driver_info_3
=NULL
;
7007 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7008 WERROR result
= WERR_OK
;
7012 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
7014 ndrivers
=get_ntdrivers(&list
, architecture
, version
);
7015 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers
, architecture
, version
));
7017 if(ndrivers
== -1) {
7018 SAFE_FREE(driver_info_3
);
7023 if((driver_info_3
=SMB_REALLOC_ARRAY(driver_info_3
, DRIVER_INFO_3
, *returned
+ndrivers
)) == NULL
) {
7024 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7030 for (i
=0; i
<ndrivers
; i
++) {
7033 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
7034 ZERO_STRUCT(driver
);
7035 status
= get_a_printer_driver(&driver
, 3, list
[i
],
7036 architecture
, version
);
7037 if (!W_ERROR_IS_OK(status
)) {
7039 SAFE_FREE(driver_info_3
);
7042 fill_printer_driver_info_3(&driver_info_3
[*returned
+i
], driver
, servername
);
7043 free_a_printer_driver(driver
, 3);
7046 *returned
+=ndrivers
;
7050 /* check the required size. */
7051 for (i
=0; i
<*returned
; i
++) {
7052 DEBUGADD(6,("adding driver [%d]'s size\n",i
));
7053 *needed
+= spoolss_size_printer_driver_info_3(&driver_info_3
[i
]);
7056 if (*needed
> offered
) {
7057 result
= WERR_INSUFFICIENT_BUFFER
;
7061 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7062 result
= WERR_NOMEM
;
7066 /* fill the buffer with the driver structures */
7067 for (i
=0; i
<*returned
; i
++) {
7068 DEBUGADD(6,("adding driver [%d] to buffer\n",i
));
7069 smb_io_printer_driver_info_3("", buffer
, &driver_info_3
[i
], 0);
7073 for (i
=0; i
<*returned
; i
++) {
7074 SAFE_FREE(driver_info_3
[i
].dependentfiles
);
7077 SAFE_FREE(driver_info_3
);
7079 if ( !W_ERROR_IS_OK(result
) )
7085 /****************************************************************************
7086 Enumerates all printer drivers.
7087 ****************************************************************************/
7089 WERROR
_spoolss_enumprinterdrivers( pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDRIVERS
*q_u
, SPOOL_R_ENUMPRINTERDRIVERS
*r_u
)
7091 uint32 level
= q_u
->level
;
7092 RPC_BUFFER
*buffer
= NULL
;
7093 uint32 offered
= q_u
->offered
;
7094 uint32
*needed
= &r_u
->needed
;
7095 uint32
*returned
= &r_u
->returned
;
7098 fstring architecture
;
7100 /* that's an [in out] buffer */
7102 if (!q_u
->buffer
&& (offered
!=0)) {
7103 return WERR_INVALID_PARAM
;
7106 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7107 buffer
= r_u
->buffer
;
7109 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7114 unistr2_to_ascii(architecture
, &q_u
->environment
, sizeof(architecture
)-1);
7115 unistr2_to_ascii(servername
, &q_u
->name
, sizeof(servername
)-1);
7117 if ( !is_myname_or_ipaddr( servername
) )
7118 return WERR_UNKNOWN_PRINTER_DRIVER
;
7122 return enumprinterdrivers_level1(servername
, architecture
, buffer
, offered
, needed
, returned
);
7124 return enumprinterdrivers_level2(servername
, architecture
, buffer
, offered
, needed
, returned
);
7126 return enumprinterdrivers_level3(servername
, architecture
, buffer
, offered
, needed
, returned
);
7128 return WERR_UNKNOWN_LEVEL
;
7132 /****************************************************************************
7133 ****************************************************************************/
7135 static void fill_form_1(FORM_1
*form
, nt_forms_struct
*list
)
7137 form
->flag
=list
->flag
;
7138 init_unistr(&form
->name
, list
->name
);
7139 form
->width
=list
->width
;
7140 form
->length
=list
->length
;
7141 form
->left
=list
->left
;
7142 form
->top
=list
->top
;
7143 form
->right
=list
->right
;
7144 form
->bottom
=list
->bottom
;
7147 /****************************************************************************
7148 ****************************************************************************/
7150 WERROR
_spoolss_enumforms(pipes_struct
*p
, SPOOL_Q_ENUMFORMS
*q_u
, SPOOL_R_ENUMFORMS
*r_u
)
7152 uint32 level
= q_u
->level
;
7153 RPC_BUFFER
*buffer
= NULL
;
7154 uint32 offered
= q_u
->offered
;
7155 uint32
*needed
= &r_u
->needed
;
7156 uint32
*numofforms
= &r_u
->numofforms
;
7157 uint32 numbuiltinforms
;
7159 nt_forms_struct
*list
=NULL
;
7160 nt_forms_struct
*builtinlist
=NULL
;
7165 /* that's an [in out] buffer */
7167 if (!q_u
->buffer
&& (offered
!=0) ) {
7168 return WERR_INVALID_PARAM
;
7171 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7172 buffer
= r_u
->buffer
;
7174 DEBUG(4,("_spoolss_enumforms\n"));
7175 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7176 DEBUGADD(5,("Info level [%d]\n", level
));
7178 numbuiltinforms
= get_builtin_ntforms(&builtinlist
);
7179 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms
));
7180 *numofforms
= get_ntforms(&list
);
7181 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms
));
7182 *numofforms
+= numbuiltinforms
;
7184 if (*numofforms
== 0) {
7185 SAFE_FREE(builtinlist
);
7187 return WERR_NO_MORE_ITEMS
;
7192 if ((forms_1
=SMB_MALLOC_ARRAY(FORM_1
, *numofforms
)) == NULL
) {
7193 SAFE_FREE(builtinlist
);
7199 /* construct the list of form structures */
7200 for (i
=0; i
<numbuiltinforms
; i
++) {
7201 DEBUGADD(6,("Filling form number [%d]\n",i
));
7202 fill_form_1(&forms_1
[i
], &builtinlist
[i
]);
7205 SAFE_FREE(builtinlist
);
7207 for (; i
<*numofforms
; i
++) {
7208 DEBUGADD(6,("Filling form number [%d]\n",i
));
7209 fill_form_1(&forms_1
[i
], &list
[i
-numbuiltinforms
]);
7214 /* check the required size. */
7215 for (i
=0; i
<numbuiltinforms
; i
++) {
7216 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7217 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7219 for (; i
<*numofforms
; i
++) {
7220 DEBUGADD(6,("adding form [%d]'s size\n",i
));
7221 buffer_size
+= spoolss_size_form_1(&forms_1
[i
]);
7224 *needed
=buffer_size
;
7226 if (*needed
> offered
) {
7229 return WERR_INSUFFICIENT_BUFFER
;
7232 if (!rpcbuf_alloc_size(buffer
, buffer_size
)){
7238 /* fill the buffer with the form structures */
7239 for (i
=0; i
<numbuiltinforms
; i
++) {
7240 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7241 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7243 for (; i
<*numofforms
; i
++) {
7244 DEBUGADD(6,("adding form [%d] to buffer\n",i
));
7245 smb_io_form_1("", buffer
, &forms_1
[i
], 0);
7254 SAFE_FREE(builtinlist
);
7255 return WERR_UNKNOWN_LEVEL
;
7259 /****************************************************************************
7260 ****************************************************************************/
7262 WERROR
_spoolss_getform(pipes_struct
*p
, SPOOL_Q_GETFORM
*q_u
, SPOOL_R_GETFORM
*r_u
)
7264 uint32 level
= q_u
->level
;
7265 UNISTR2
*uni_formname
= &q_u
->formname
;
7266 RPC_BUFFER
*buffer
= NULL
;
7267 uint32 offered
= q_u
->offered
;
7268 uint32
*needed
= &r_u
->needed
;
7270 nt_forms_struct
*list
=NULL
;
7271 nt_forms_struct builtin_form
;
7276 int numofforms
=0, i
=0;
7278 /* that's an [in out] buffer */
7280 if (!q_u
->buffer
&& (offered
!=0)) {
7281 return WERR_INVALID_PARAM
;
7284 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7285 buffer
= r_u
->buffer
;
7287 unistr2_to_ascii(form_name
, uni_formname
, sizeof(form_name
)-1);
7289 DEBUG(4,("_spoolss_getform\n"));
7290 DEBUGADD(5,("Offered buffer size [%d]\n", offered
));
7291 DEBUGADD(5,("Info level [%d]\n", level
));
7293 foundBuiltin
= get_a_builtin_ntform(uni_formname
,&builtin_form
);
7294 if (!foundBuiltin
) {
7295 numofforms
= get_ntforms(&list
);
7296 DEBUGADD(5,("Number of forms [%d]\n", numofforms
));
7298 if (numofforms
== 0)
7305 fill_form_1(&form_1
, &builtin_form
);
7308 /* Check if the requested name is in the list of form structures */
7309 for (i
=0; i
<numofforms
; i
++) {
7311 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list
[i
].name
, form_name
));
7313 if (strequal(form_name
, list
[i
].name
)) {
7314 DEBUGADD(6,("Found form %s number [%d]\n", form_name
, i
));
7315 fill_form_1(&form_1
, &list
[i
]);
7321 if (i
== numofforms
) {
7325 /* check the required size. */
7327 *needed
=spoolss_size_form_1(&form_1
);
7329 if (*needed
> offered
)
7330 return WERR_INSUFFICIENT_BUFFER
;
7332 if (!rpcbuf_alloc_size(buffer
, buffer_size
))
7335 /* fill the buffer with the form structures */
7336 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name
, i
));
7337 smb_io_form_1("", buffer
, &form_1
, 0);
7343 return WERR_UNKNOWN_LEVEL
;
7347 /****************************************************************************
7348 ****************************************************************************/
7350 static void fill_port_1(PORT_INFO_1
*port
, const char *name
)
7352 init_unistr(&port
->port_name
, name
);
7355 /****************************************************************************
7356 TODO: This probably needs distinguish between TCP/IP and Local ports
7358 ****************************************************************************/
7360 static void fill_port_2(PORT_INFO_2
*port
, const char *name
)
7362 init_unistr(&port
->port_name
, name
);
7363 init_unistr(&port
->monitor_name
, "Local Monitor");
7364 init_unistr(&port
->description
, SPL_LOCAL_PORT
);
7365 port
->port_type
=PORT_TYPE_WRITE
;
7370 /****************************************************************************
7371 wrapper around the enumer ports command
7372 ****************************************************************************/
7374 WERROR
enumports_hook( int *count
, char ***lines
)
7376 char *cmd
= lp_enumports_cmd();
7386 /* if no hook then just fill in the default port */
7389 qlines
= SMB_MALLOC_ARRAY( char*, 2 );
7390 qlines
[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME
);
7395 /* we have a valid enumport command */
7397 slprintf(command
, sizeof(command
)-1, "%s \"%d\"", cmd
, 1);
7399 DEBUG(10,("Running [%s]\n", command
));
7400 ret
= smbrun(command
, &fd
);
7401 DEBUG(10,("Returned [%d]\n", ret
));
7406 return WERR_ACCESS_DENIED
;
7410 qlines
= fd_lines_load(fd
, &numlines
, 0);
7411 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7421 /****************************************************************************
7423 ****************************************************************************/
7425 static WERROR
enumports_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7427 PORT_INFO_1
*ports
=NULL
;
7429 WERROR result
= WERR_OK
;
7430 char **qlines
= NULL
;
7433 result
= enumports_hook( &numlines
, &qlines
);
7434 if (!W_ERROR_IS_OK(result
)) {
7435 file_lines_free(qlines
);
7440 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_1
, numlines
)) == NULL
) {
7441 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7442 dos_errstr(WERR_NOMEM
)));
7443 file_lines_free(qlines
);
7447 for (i
=0; i
<numlines
; i
++) {
7448 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7449 fill_port_1(&ports
[i
], qlines
[i
]);
7452 file_lines_free(qlines
);
7454 *returned
= numlines
;
7456 /* check the required size. */
7457 for (i
=0; i
<*returned
; i
++) {
7458 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7459 *needed
+= spoolss_size_port_info_1(&ports
[i
]);
7462 if (*needed
> offered
) {
7463 result
= WERR_INSUFFICIENT_BUFFER
;
7467 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7468 result
= WERR_NOMEM
;
7472 /* fill the buffer with the ports structures */
7473 for (i
=0; i
<*returned
; i
++) {
7474 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7475 smb_io_port_1("", buffer
, &ports
[i
], 0);
7481 if ( !W_ERROR_IS_OK(result
) )
7487 /****************************************************************************
7489 ****************************************************************************/
7491 static WERROR
enumports_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
7493 PORT_INFO_2
*ports
=NULL
;
7495 WERROR result
= WERR_OK
;
7496 char **qlines
= NULL
;
7499 result
= enumports_hook( &numlines
, &qlines
);
7500 if ( !W_ERROR_IS_OK(result
)) {
7501 file_lines_free(qlines
);
7506 if((ports
=SMB_MALLOC_ARRAY( PORT_INFO_2
, numlines
)) == NULL
) {
7507 file_lines_free(qlines
);
7511 for (i
=0; i
<numlines
; i
++) {
7512 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7513 fill_port_2(&(ports
[i
]), qlines
[i
]);
7517 file_lines_free(qlines
);
7519 *returned
= numlines
;
7521 /* check the required size. */
7522 for (i
=0; i
<*returned
; i
++) {
7523 DEBUGADD(6,("adding port [%d]'s size\n", i
));
7524 *needed
+= spoolss_size_port_info_2(&ports
[i
]);
7527 if (*needed
> offered
) {
7528 result
= WERR_INSUFFICIENT_BUFFER
;
7532 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7533 result
= WERR_NOMEM
;
7537 /* fill the buffer with the ports structures */
7538 for (i
=0; i
<*returned
; i
++) {
7539 DEBUGADD(6,("adding port [%d] to buffer\n", i
));
7540 smb_io_port_2("", buffer
, &ports
[i
], 0);
7546 if ( !W_ERROR_IS_OK(result
) )
7552 /****************************************************************************
7554 ****************************************************************************/
7556 WERROR
_spoolss_enumports( pipes_struct
*p
, SPOOL_Q_ENUMPORTS
*q_u
, SPOOL_R_ENUMPORTS
*r_u
)
7558 uint32 level
= q_u
->level
;
7559 RPC_BUFFER
*buffer
= NULL
;
7560 uint32 offered
= q_u
->offered
;
7561 uint32
*needed
= &r_u
->needed
;
7562 uint32
*returned
= &r_u
->returned
;
7564 /* that's an [in out] buffer */
7566 if (!q_u
->buffer
&& (offered
!=0)) {
7567 return WERR_INVALID_PARAM
;
7570 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7571 buffer
= r_u
->buffer
;
7573 DEBUG(4,("_spoolss_enumports\n"));
7580 return enumports_level_1(buffer
, offered
, needed
, returned
);
7582 return enumports_level_2(buffer
, offered
, needed
, returned
);
7584 return WERR_UNKNOWN_LEVEL
;
7588 /****************************************************************************
7589 ****************************************************************************/
7591 static WERROR
spoolss_addprinterex_level_2( pipes_struct
*p
, const UNISTR2
*uni_srv_name
,
7592 const SPOOL_PRINTER_INFO_LEVEL
*info
,
7593 DEVICEMODE
*devmode
, SEC_DESC_BUF
*sec_desc_buf
,
7594 uint32 user_switch
, const SPOOL_USER_CTR
*user
,
7597 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7600 WERROR err
= WERR_OK
;
7602 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7603 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7607 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7608 if (!convert_printer_info(info
, printer
, 2)) {
7609 free_a_printer(&printer
, 2);
7613 /* check to see if the printer already exists */
7615 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7616 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7617 printer
->info_2
->sharename
));
7618 free_a_printer(&printer
, 2);
7619 return WERR_PRINTER_ALREADY_EXISTS
;
7622 /* FIXME!!! smbd should check to see if the driver is installed before
7623 trying to add a printer like this --jerry */
7625 if (*lp_addprinter_cmd() ) {
7626 if ( !add_printer_hook(p
->pipe_user
.nt_user_token
, printer
) ) {
7627 free_a_printer(&printer
,2);
7628 return WERR_ACCESS_DENIED
;
7631 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7632 "smb.conf parameter \"addprinter command\" is defined. This"
7633 "parameter must exist for this call to succeed\n",
7634 printer
->info_2
->sharename
));
7637 /* use our primary netbios name since get_a_printer() will convert
7638 it to what the client expects on a case by case basis */
7640 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7641 printer
->info_2
->sharename
);
7644 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7645 free_a_printer(&printer
,2);
7646 return WERR_ACCESS_DENIED
;
7649 /* you must be a printer admin to add a new printer */
7650 if (!print_access_check(NULL
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7651 free_a_printer(&printer
,2);
7652 return WERR_ACCESS_DENIED
;
7656 * Do sanity check on the requested changes for Samba.
7659 if (!check_printer_ok(printer
->info_2
, snum
)) {
7660 free_a_printer(&printer
,2);
7661 return WERR_INVALID_PARAM
;
7665 * When a printer is created, the drivername bound to the printer is used
7666 * to lookup previously saved driver initialization info, which is then
7667 * bound to the new printer, simulating what happens in the Windows arch.
7672 set_driver_init(printer
, 2);
7676 /* A valid devmode was included, convert and link it
7678 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7680 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7681 &printer
->info_2
->devmode
))
7685 /* write the ASCII on disk */
7686 err
= mod_a_printer(printer
, 2);
7687 if (!W_ERROR_IS_OK(err
)) {
7688 free_a_printer(&printer
,2);
7692 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7693 /* Handle open failed - remove addition. */
7694 del_a_printer(printer
->info_2
->sharename
);
7695 free_a_printer(&printer
,2);
7696 return WERR_ACCESS_DENIED
;
7699 update_c_setprinter(False
);
7700 free_a_printer(&printer
,2);
7705 /****************************************************************************
7706 ****************************************************************************/
7708 WERROR
_spoolss_addprinterex( pipes_struct
*p
, SPOOL_Q_ADDPRINTEREX
*q_u
, SPOOL_R_ADDPRINTEREX
*r_u
)
7710 UNISTR2
*uni_srv_name
= q_u
->server_name
;
7711 uint32 level
= q_u
->level
;
7712 SPOOL_PRINTER_INFO_LEVEL
*info
= &q_u
->info
;
7713 DEVICEMODE
*devmode
= q_u
->devmode_ctr
.devmode
;
7714 SEC_DESC_BUF
*sdb
= q_u
->secdesc_ctr
;
7715 uint32 user_switch
= q_u
->user_switch
;
7716 SPOOL_USER_CTR
*user
= &q_u
->user_ctr
;
7717 POLICY_HND
*handle
= &r_u
->handle
;
7721 /* we don't handle yet */
7722 /* but I know what to do ... */
7723 return WERR_UNKNOWN_LEVEL
;
7725 return spoolss_addprinterex_level_2(p
, uni_srv_name
, info
,
7727 user_switch
, user
, handle
);
7729 return WERR_UNKNOWN_LEVEL
;
7733 /****************************************************************************
7734 ****************************************************************************/
7736 WERROR
_spoolss_addprinterdriver(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVER
*q_u
, SPOOL_R_ADDPRINTERDRIVER
*r_u
)
7738 uint32 level
= q_u
->level
;
7739 SPOOL_PRINTER_DRIVER_INFO_LEVEL
*info
= &q_u
->info
;
7740 WERROR err
= WERR_OK
;
7741 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
7742 fstring driver_name
;
7745 ZERO_STRUCT(driver
);
7747 if (!convert_printer_driver_info(info
, &driver
, level
)) {
7752 DEBUG(5,("Cleaning driver's information\n"));
7753 err
= clean_up_driver_struct(driver
, level
, &p
->pipe_user
);
7754 if (!W_ERROR_IS_OK(err
))
7757 DEBUG(5,("Moving driver to final destination\n"));
7758 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(driver
, level
, &p
->pipe_user
, &err
)) ) {
7762 if (add_a_printer_driver(driver
, level
)!=0) {
7763 err
= WERR_ACCESS_DENIED
;
7768 * I think this is where he DrvUpgradePrinter() hook would be
7769 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7770 * server. Right now, we just need to send ourselves a message
7771 * to update each printer bound to this driver. --jerry
7774 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7775 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7780 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7781 * decide if the driver init data should be deleted. The rules are:
7782 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7783 * 2) delete init data only if there is no 2k/Xp driver
7784 * 3) always delete init data
7785 * The generalized rule is always use init data from the highest order driver.
7786 * It is necessary to follow the driver install by an initialization step to
7787 * finish off this process.
7790 version
= driver
.info_3
->cversion
;
7791 else if (level
== 6)
7792 version
= driver
.info_6
->version
;
7797 * 9x printer driver - never delete init data
7800 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7805 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7806 * there is no 2k/Xp driver init data for this driver name.
7810 NT_PRINTER_DRIVER_INFO_LEVEL driver1
;
7812 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1
, 3, driver_name
, "Windows NT x86", 3))) {
7814 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7816 if (!del_driver_init(driver_name
))
7817 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name
));
7820 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7822 free_a_printer_driver(driver1
,3);
7823 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7830 * 2k or Xp printer driver - always delete init data
7833 if (!del_driver_init(driver_name
))
7834 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name
));
7838 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level
));
7844 free_a_printer_driver(driver
, level
);
7848 /********************************************************************
7849 * spoolss_addprinterdriverex
7850 ********************************************************************/
7852 WERROR
_spoolss_addprinterdriverex(pipes_struct
*p
, SPOOL_Q_ADDPRINTERDRIVEREX
*q_u
, SPOOL_R_ADDPRINTERDRIVEREX
*r_u
)
7854 SPOOL_Q_ADDPRINTERDRIVER q_u_local
;
7855 SPOOL_R_ADDPRINTERDRIVER r_u_local
;
7858 * we only support the semantics of AddPrinterDriver()
7859 * i.e. only copy files that are newer than existing ones
7862 if ( q_u
->copy_flags
!= APD_COPY_NEW_FILES
)
7863 return WERR_ACCESS_DENIED
;
7865 ZERO_STRUCT(q_u_local
);
7866 ZERO_STRUCT(r_u_local
);
7868 /* just pass the information off to _spoolss_addprinterdriver() */
7869 q_u_local
.server_name_ptr
= q_u
->server_name_ptr
;
7870 copy_unistr2(&q_u_local
.server_name
, &q_u
->server_name
);
7871 q_u_local
.level
= q_u
->level
;
7872 memcpy( &q_u_local
.info
, &q_u
->info
, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL
) );
7874 return _spoolss_addprinterdriver( p
, &q_u_local
, &r_u_local
);
7877 /****************************************************************************
7878 ****************************************************************************/
7880 static void fill_driverdir_1(DRIVER_DIRECTORY_1
*info
, char *name
)
7882 init_unistr(&info
->name
, name
);
7885 /****************************************************************************
7886 ****************************************************************************/
7888 static WERROR
getprinterdriverdir_level_1(UNISTR2
*name
, UNISTR2
*uni_environment
, RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
)
7894 const char *short_archi
;
7895 DRIVER_DIRECTORY_1
*info
=NULL
;
7896 WERROR result
= WERR_OK
;
7898 unistr2_to_ascii(servername
, name
, sizeof(servername
)-1);
7899 unistr2_to_ascii(long_archi
, uni_environment
, sizeof(long_archi
)-1);
7901 /* check for beginning double '\'s and that the server
7904 pservername
= servername
;
7905 if ( *pservername
== '\\' && strlen(servername
)>2 ) {
7909 if ( !is_myname_or_ipaddr( pservername
) )
7910 return WERR_INVALID_PARAM
;
7912 if (!(short_archi
= get_short_archi(long_archi
)))
7913 return WERR_INVALID_ENVIRONMENT
;
7915 if((info
=SMB_MALLOC_P(DRIVER_DIRECTORY_1
)) == NULL
)
7918 slprintf(path
, sizeof(path
)-1, "\\\\%s\\print$\\%s", pservername
, short_archi
);
7920 DEBUG(4,("printer driver directory: [%s]\n", path
));
7922 fill_driverdir_1(info
, path
);
7924 *needed
+= spoolss_size_driverdir_info_1(info
);
7926 if (*needed
> offered
) {
7927 result
= WERR_INSUFFICIENT_BUFFER
;
7931 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
7932 result
= WERR_NOMEM
;
7936 smb_io_driverdir_1("", buffer
, info
, 0);
7944 /****************************************************************************
7945 ****************************************************************************/
7947 WERROR
_spoolss_getprinterdriverdirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTERDRIVERDIR
*q_u
, SPOOL_R_GETPRINTERDRIVERDIR
*r_u
)
7949 UNISTR2
*name
= &q_u
->name
;
7950 UNISTR2
*uni_environment
= &q_u
->environment
;
7951 uint32 level
= q_u
->level
;
7952 RPC_BUFFER
*buffer
= NULL
;
7953 uint32 offered
= q_u
->offered
;
7954 uint32
*needed
= &r_u
->needed
;
7956 /* that's an [in out] buffer */
7958 if (!q_u
->buffer
&& (offered
!=0)) {
7959 return WERR_INVALID_PARAM
;
7962 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
7963 buffer
= r_u
->buffer
;
7965 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
7971 return getprinterdriverdir_level_1(name
, uni_environment
, buffer
, offered
, needed
);
7973 return WERR_UNKNOWN_LEVEL
;
7977 /****************************************************************************
7978 ****************************************************************************/
7980 WERROR
_spoolss_enumprinterdata(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATA
*q_u
, SPOOL_R_ENUMPRINTERDATA
*r_u
)
7982 POLICY_HND
*handle
= &q_u
->handle
;
7983 uint32 idx
= q_u
->index
;
7984 uint32 in_value_len
= q_u
->valuesize
;
7985 uint32 in_data_len
= q_u
->datasize
;
7986 uint32
*out_max_value_len
= &r_u
->valuesize
;
7987 uint16
**out_value
= &r_u
->value
;
7988 uint32
*out_value_len
= &r_u
->realvaluesize
;
7989 uint32
*out_type
= &r_u
->type
;
7990 uint32
*out_max_data_len
= &r_u
->datasize
;
7991 uint8
**data_out
= &r_u
->data
;
7992 uint32
*out_data_len
= &r_u
->realdatasize
;
7994 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7996 uint32 biggest_valuesize
;
7997 uint32 biggest_datasize
;
7999 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8002 REGISTRY_VALUE
*val
= NULL
;
8003 NT_PRINTER_DATA
*p_data
;
8004 int i
, key_index
, num_values
;
8009 *out_max_data_len
= 0;
8013 DEBUG(5,("spoolss_enumprinterdata\n"));
8016 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8020 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
8023 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8024 if (!W_ERROR_IS_OK(result
))
8027 p_data
= printer
->info_2
->data
;
8028 key_index
= lookup_printerkey( p_data
, SPOOL_PRINTERDATA_KEY
);
8033 * The NT machine wants to know the biggest size of value and data
8035 * cf: MSDN EnumPrinterData remark section
8038 if ( !in_value_len
&& !in_data_len
&& (key_index
!= -1) )
8040 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8042 biggest_valuesize
= 0;
8043 biggest_datasize
= 0;
8045 num_values
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
8047 for ( i
=0; i
<num_values
; i
++ )
8049 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
8051 name_length
= strlen(val
->valuename
);
8052 if ( strlen(val
->valuename
) > biggest_valuesize
)
8053 biggest_valuesize
= name_length
;
8055 if ( val
->size
> biggest_datasize
)
8056 biggest_datasize
= val
->size
;
8058 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
8062 /* the value is an UNICODE string but real_value_size is the length
8063 in bytes including the trailing 0 */
8065 *out_value_len
= 2 * (1+biggest_valuesize
);
8066 *out_data_len
= biggest_datasize
;
8068 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len
, *out_data_len
));
8074 * the value len is wrong in NT sp3
8075 * that's the number of bytes not the number of unicode chars
8078 if ( key_index
!= -1 )
8079 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, idx
);
8084 /* out_value should default to "" or else NT4 has
8085 problems unmarshalling the response */
8087 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
8089 if((*out_value
=(uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
8091 result
= WERR_NOMEM
;
8095 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, "", in_value_len
, 0);
8097 /* the data is counted in bytes */
8099 *out_max_data_len
= in_data_len
;
8100 *out_data_len
= in_data_len
;
8102 /* only allocate when given a non-zero data_len */
8104 if ( in_data_len
&& ((*data_out
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
) )
8106 result
= WERR_NOMEM
;
8110 result
= WERR_NO_MORE_ITEMS
;
8116 * - counted in bytes in the request
8117 * - counted in UNICODE chars in the max reply
8118 * - counted in bytes in the real size
8120 * take a pause *before* coding not *during* coding
8124 *out_max_value_len
=(in_value_len
/sizeof(uint16
));
8125 if ( (*out_value
= (uint16
*)TALLOC_ZERO(p
->mem_ctx
, in_value_len
*sizeof(uint8
))) == NULL
)
8127 result
= WERR_NOMEM
;
8131 *out_value_len
= (uint32
)rpcstr_push((char *)*out_value
, regval_name(val
), (size_t)in_value_len
, 0);
8135 *out_type
= regval_type( val
);
8137 /* data - counted in bytes */
8139 *out_max_data_len
= in_data_len
;
8140 if ( in_data_len
&& (*data_out
= (uint8
*)TALLOC_ZERO(p
->mem_ctx
, in_data_len
*sizeof(uint8
))) == NULL
)
8142 result
= WERR_NOMEM
;
8145 data_len
= regval_size(val
);
8147 memcpy( *data_out
, regval_data_p(val
), data_len
);
8148 *out_data_len
= data_len
;
8152 free_a_printer(&printer
, 2);
8156 /****************************************************************************
8157 ****************************************************************************/
8159 WERROR
_spoolss_setprinterdata( pipes_struct
*p
, SPOOL_Q_SETPRINTERDATA
*q_u
, SPOOL_R_SETPRINTERDATA
*r_u
)
8161 POLICY_HND
*handle
= &q_u
->handle
;
8162 UNISTR2
*value
= &q_u
->value
;
8163 uint32 type
= q_u
->type
;
8164 uint8
*data
= q_u
->data
;
8165 uint32 real_len
= q_u
->real_len
;
8167 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8169 WERROR status
= WERR_OK
;
8170 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8173 DEBUG(5,("spoolss_setprinterdata\n"));
8176 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8180 if ( Printer
->printer_type
== SPLHND_SERVER
) {
8181 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8182 return WERR_INVALID_PARAM
;
8185 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
8189 * Access check : NT returns "access denied" if you make a
8190 * SetPrinterData call without the necessary privildge.
8191 * we were originally returning OK if nothing changed
8192 * which made Win2k issue **a lot** of SetPrinterData
8193 * when connecting to a printer --jerry
8196 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
8198 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8199 status
= WERR_ACCESS_DENIED
;
8203 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8204 if (!W_ERROR_IS_OK(status
))
8207 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8210 * When client side code sets a magic printer data key, detect it and save
8211 * the current printer data and the magic key's data (its the DEVMODE) for
8212 * future printer/driver initializations.
8214 if ( (type
== REG_BINARY
) && strequal( valuename
, PHANTOM_DEVMODE_KEY
))
8216 /* Set devmode and printer initialization info */
8217 status
= save_driver_init( printer
, 2, data
, real_len
);
8219 srv_spoolss_reset_printerdata( printer
->info_2
->drivername
);
8223 status
= set_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
,
8224 type
, data
, real_len
);
8225 if ( W_ERROR_IS_OK(status
) )
8226 status
= mod_a_printer(printer
, 2);
8230 free_a_printer(&printer
, 2);
8235 /****************************************************************************
8236 ****************************************************************************/
8238 WERROR
_spoolss_resetprinter(pipes_struct
*p
, SPOOL_Q_RESETPRINTER
*q_u
, SPOOL_R_RESETPRINTER
*r_u
)
8240 POLICY_HND
*handle
= &q_u
->handle
;
8241 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8244 DEBUG(5,("_spoolss_resetprinter\n"));
8247 * All we do is to check to see if the handle and queue is valid.
8248 * This call really doesn't mean anything to us because we only
8249 * support RAW printing. --jerry
8253 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8257 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
8261 /* blindly return success */
8266 /****************************************************************************
8267 ****************************************************************************/
8269 WERROR
_spoolss_deleteprinterdata(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATA
*q_u
, SPOOL_R_DELETEPRINTERDATA
*r_u
)
8271 POLICY_HND
*handle
= &q_u
->handle
;
8272 UNISTR2
*value
= &q_u
->valuename
;
8274 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8276 WERROR status
= WERR_OK
;
8277 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
8280 DEBUG(5,("spoolss_deleteprinterdata\n"));
8283 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8287 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
8290 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8291 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8292 return WERR_ACCESS_DENIED
;
8295 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8296 if (!W_ERROR_IS_OK(status
))
8299 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
8301 status
= delete_printer_dataex( printer
, SPOOL_PRINTERDATA_KEY
, valuename
);
8303 if ( W_ERROR_IS_OK(status
) )
8304 mod_a_printer( printer
, 2 );
8306 free_a_printer(&printer
, 2);
8311 /****************************************************************************
8312 ****************************************************************************/
8314 WERROR
_spoolss_addform( pipes_struct
*p
, SPOOL_Q_ADDFORM
*q_u
, SPOOL_R_ADDFORM
*r_u
)
8316 POLICY_HND
*handle
= &q_u
->handle
;
8317 FORM
*form
= &q_u
->form
;
8318 nt_forms_struct tmpForm
;
8320 WERROR status
= WERR_OK
;
8321 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8324 nt_forms_struct
*list
=NULL
;
8325 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8327 DEBUG(5,("spoolss_addform\n"));
8330 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8335 /* forms can be added on printer of on the print server handle */
8337 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8339 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
8342 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8343 if (!W_ERROR_IS_OK(status
))
8347 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8348 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8349 status
= WERR_ACCESS_DENIED
;
8353 /* can't add if builtin */
8355 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8356 status
= WERR_ALREADY_EXISTS
;
8360 count
= get_ntforms(&list
);
8362 if(!add_a_form(&list
, form
, &count
)) {
8363 status
= WERR_NOMEM
;
8367 write_ntforms(&list
, count
);
8370 * ChangeID must always be set if this is a printer
8373 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8374 status
= mod_a_printer(printer
, 2);
8378 free_a_printer(&printer
, 2);
8384 /****************************************************************************
8385 ****************************************************************************/
8387 WERROR
_spoolss_deleteform( pipes_struct
*p
, SPOOL_Q_DELETEFORM
*q_u
, SPOOL_R_DELETEFORM
*r_u
)
8389 POLICY_HND
*handle
= &q_u
->handle
;
8390 UNISTR2
*form_name
= &q_u
->name
;
8391 nt_forms_struct tmpForm
;
8393 nt_forms_struct
*list
=NULL
;
8394 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8396 WERROR status
= WERR_OK
;
8397 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8399 DEBUG(5,("spoolss_deleteform\n"));
8402 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8406 /* forms can be deleted on printer of on the print server handle */
8408 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8410 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
8413 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8414 if (!W_ERROR_IS_OK(status
))
8418 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8419 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8420 status
= WERR_ACCESS_DENIED
;
8424 /* can't delete if builtin */
8426 if (get_a_builtin_ntform(form_name
,&tmpForm
)) {
8427 status
= WERR_INVALID_PARAM
;
8431 count
= get_ntforms(&list
);
8433 if ( !delete_a_form(&list
, form_name
, &count
, &status
))
8437 * ChangeID must always be set if this is a printer
8440 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8441 status
= mod_a_printer(printer
, 2);
8445 free_a_printer(&printer
, 2);
8451 /****************************************************************************
8452 ****************************************************************************/
8454 WERROR
_spoolss_setform(pipes_struct
*p
, SPOOL_Q_SETFORM
*q_u
, SPOOL_R_SETFORM
*r_u
)
8456 POLICY_HND
*handle
= &q_u
->handle
;
8457 FORM
*form
= &q_u
->form
;
8458 nt_forms_struct tmpForm
;
8460 WERROR status
= WERR_OK
;
8461 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8464 nt_forms_struct
*list
=NULL
;
8465 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
8467 DEBUG(5,("spoolss_setform\n"));
8470 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
8474 /* forms can be modified on printer of on the print server handle */
8476 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8478 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
8481 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8482 if (!W_ERROR_IS_OK(status
))
8486 if ( !(Printer
->access_granted
& (PRINTER_ACCESS_ADMINISTER
|SERVER_ACCESS_ADMINISTER
)) ) {
8487 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8488 status
= WERR_ACCESS_DENIED
;
8492 /* can't set if builtin */
8493 if (get_a_builtin_ntform(&form
->name
,&tmpForm
)) {
8494 status
= WERR_INVALID_PARAM
;
8498 count
= get_ntforms(&list
);
8499 update_a_form(&list
, form
, count
);
8500 write_ntforms(&list
, count
);
8503 * ChangeID must always be set if this is a printer
8506 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8507 status
= mod_a_printer(printer
, 2);
8512 free_a_printer(&printer
, 2);
8518 /****************************************************************************
8519 enumprintprocessors level 1.
8520 ****************************************************************************/
8522 static WERROR
enumprintprocessors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8524 PRINTPROCESSOR_1
*info_1
=NULL
;
8525 WERROR result
= WERR_OK
;
8527 if((info_1
= SMB_MALLOC_P(PRINTPROCESSOR_1
)) == NULL
)
8532 init_unistr(&info_1
->name
, "winprint");
8534 *needed
+= spoolss_size_printprocessor_info_1(info_1
);
8536 if (*needed
> offered
) {
8537 result
= WERR_INSUFFICIENT_BUFFER
;
8541 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8542 result
= WERR_NOMEM
;
8546 smb_io_printprocessor_info_1("", buffer
, info_1
, 0);
8551 if ( !W_ERROR_IS_OK(result
) )
8557 /****************************************************************************
8558 ****************************************************************************/
8560 WERROR
_spoolss_enumprintprocessors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCESSORS
*q_u
, SPOOL_R_ENUMPRINTPROCESSORS
*r_u
)
8562 uint32 level
= q_u
->level
;
8563 RPC_BUFFER
*buffer
= NULL
;
8564 uint32 offered
= q_u
->offered
;
8565 uint32
*needed
= &r_u
->needed
;
8566 uint32
*returned
= &r_u
->returned
;
8568 /* that's an [in out] buffer */
8570 if (!q_u
->buffer
&& (offered
!=0)) {
8571 return WERR_INVALID_PARAM
;
8574 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8575 buffer
= r_u
->buffer
;
8577 DEBUG(5,("spoolss_enumprintprocessors\n"));
8580 * Enumerate the print processors ...
8582 * Just reply with "winprint", to keep NT happy
8583 * and I can use my nice printer checker.
8591 return enumprintprocessors_level_1(buffer
, offered
, needed
, returned
);
8593 return WERR_UNKNOWN_LEVEL
;
8597 /****************************************************************************
8598 enumprintprocdatatypes level 1.
8599 ****************************************************************************/
8601 static WERROR
enumprintprocdatatypes_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8603 PRINTPROCDATATYPE_1
*info_1
=NULL
;
8604 WERROR result
= WERR_NOMEM
;
8606 if((info_1
= SMB_MALLOC_P(PRINTPROCDATATYPE_1
)) == NULL
)
8611 init_unistr(&info_1
->name
, "RAW");
8613 *needed
+= spoolss_size_printprocdatatype_info_1(info_1
);
8615 if (*needed
> offered
) {
8616 result
= WERR_INSUFFICIENT_BUFFER
;
8620 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8621 result
= WERR_NOMEM
;
8625 smb_io_printprocdatatype_info_1("", buffer
, info_1
, 0);
8630 if ( !W_ERROR_IS_OK(result
) )
8636 /****************************************************************************
8637 ****************************************************************************/
8639 WERROR
_spoolss_enumprintprocdatatypes(pipes_struct
*p
, SPOOL_Q_ENUMPRINTPROCDATATYPES
*q_u
, SPOOL_R_ENUMPRINTPROCDATATYPES
*r_u
)
8641 uint32 level
= q_u
->level
;
8642 RPC_BUFFER
*buffer
= NULL
;
8643 uint32 offered
= q_u
->offered
;
8644 uint32
*needed
= &r_u
->needed
;
8645 uint32
*returned
= &r_u
->returned
;
8647 /* that's an [in out] buffer */
8649 if (!q_u
->buffer
&& (offered
!=0)) {
8650 return WERR_INVALID_PARAM
;
8653 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8654 buffer
= r_u
->buffer
;
8656 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8663 return enumprintprocdatatypes_level_1(buffer
, offered
, needed
, returned
);
8665 return WERR_UNKNOWN_LEVEL
;
8669 /****************************************************************************
8670 enumprintmonitors level 1.
8671 ****************************************************************************/
8673 static WERROR
enumprintmonitors_level_1(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8675 PRINTMONITOR_1
*info_1
;
8676 WERROR result
= WERR_OK
;
8679 if((info_1
= SMB_MALLOC_ARRAY(PRINTMONITOR_1
, 2)) == NULL
)
8684 init_unistr(&(info_1
[0].name
), SPL_LOCAL_PORT
);
8685 init_unistr(&(info_1
[1].name
), SPL_TCPIP_PORT
);
8687 for ( i
=0; i
<*returned
; i
++ ) {
8688 *needed
+= spoolss_size_printmonitor_info_1(&info_1
[i
]);
8691 if (*needed
> offered
) {
8692 result
= WERR_INSUFFICIENT_BUFFER
;
8696 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8697 result
= WERR_NOMEM
;
8701 for ( i
=0; i
<*returned
; i
++ ) {
8702 smb_io_printmonitor_info_1("", buffer
, &info_1
[i
], 0);
8708 if ( !W_ERROR_IS_OK(result
) )
8714 /****************************************************************************
8715 enumprintmonitors level 2.
8716 ****************************************************************************/
8718 static WERROR
enumprintmonitors_level_2(RPC_BUFFER
*buffer
, uint32 offered
, uint32
*needed
, uint32
*returned
)
8720 PRINTMONITOR_2
*info_2
;
8721 WERROR result
= WERR_OK
;
8724 if((info_2
= SMB_MALLOC_ARRAY(PRINTMONITOR_2
, 2)) == NULL
)
8729 init_unistr( &(info_2
[0].name
), SPL_LOCAL_PORT
);
8730 init_unistr( &(info_2
[0].environment
), "Windows NT X86" );
8731 init_unistr( &(info_2
[0].dll_name
), "localmon.dll" );
8733 init_unistr( &(info_2
[1].name
), SPL_TCPIP_PORT
);
8734 init_unistr( &(info_2
[1].environment
), "Windows NT X86" );
8735 init_unistr( &(info_2
[1].dll_name
), "tcpmon.dll" );
8737 for ( i
=0; i
<*returned
; i
++ ) {
8738 *needed
+= spoolss_size_printmonitor_info_2(&info_2
[i
]);
8741 if (*needed
> offered
) {
8742 result
= WERR_INSUFFICIENT_BUFFER
;
8746 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8747 result
= WERR_NOMEM
;
8751 for ( i
=0; i
<*returned
; i
++ ) {
8752 smb_io_printmonitor_info_2("", buffer
, &info_2
[i
], 0);
8758 if ( !W_ERROR_IS_OK(result
) )
8764 /****************************************************************************
8765 ****************************************************************************/
8767 WERROR
_spoolss_enumprintmonitors(pipes_struct
*p
, SPOOL_Q_ENUMPRINTMONITORS
*q_u
, SPOOL_R_ENUMPRINTMONITORS
*r_u
)
8769 uint32 level
= q_u
->level
;
8770 RPC_BUFFER
*buffer
= NULL
;
8771 uint32 offered
= q_u
->offered
;
8772 uint32
*needed
= &r_u
->needed
;
8773 uint32
*returned
= &r_u
->returned
;
8775 /* that's an [in out] buffer */
8777 if (!q_u
->buffer
&& (offered
!=0)) {
8778 return WERR_INVALID_PARAM
;
8781 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8782 buffer
= r_u
->buffer
;
8784 DEBUG(5,("spoolss_enumprintmonitors\n"));
8787 * Enumerate the print monitors ...
8789 * Just reply with "Local Port", to keep NT happy
8790 * and I can use my nice printer checker.
8798 return enumprintmonitors_level_1(buffer
, offered
, needed
, returned
);
8800 return enumprintmonitors_level_2(buffer
, offered
, needed
, returned
);
8802 return WERR_UNKNOWN_LEVEL
;
8806 /****************************************************************************
8807 ****************************************************************************/
8809 static WERROR
getjob_level_1(print_queue_struct
**queue
, int count
, int snum
,
8810 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8811 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8816 JOB_INFO_1
*info_1
=NULL
;
8817 WERROR result
= WERR_OK
;
8819 info_1
=SMB_MALLOC_P(JOB_INFO_1
);
8821 if (info_1
== NULL
) {
8825 for (i
=0; i
<count
&& found
==False
; i
++) {
8826 if ((*queue
)[i
].job
==(int)jobid
)
8832 /* NT treats not found as bad param... yet another bad choice */
8833 return WERR_INVALID_PARAM
;
8836 fill_job_info_1( info_1
, &((*queue
)[i
-1]), i
, snum
, ntprinter
);
8838 *needed
+= spoolss_size_job_info_1(info_1
);
8840 if (*needed
> offered
) {
8841 result
= WERR_INSUFFICIENT_BUFFER
;
8845 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8846 result
= WERR_NOMEM
;
8850 smb_io_job_info_1("", buffer
, info_1
, 0);
8858 /****************************************************************************
8859 ****************************************************************************/
8861 static WERROR
getjob_level_2(print_queue_struct
**queue
, int count
, int snum
,
8862 NT_PRINTER_INFO_LEVEL
*ntprinter
,
8863 uint32 jobid
, RPC_BUFFER
*buffer
, uint32 offered
,
8870 DEVICEMODE
*devmode
= NULL
;
8871 NT_DEVICEMODE
*nt_devmode
= NULL
;
8873 if ( !(info_2
=SMB_MALLOC_P(JOB_INFO_2
)) )
8876 ZERO_STRUCTP(info_2
);
8878 for ( i
=0; i
<count
&& found
==False
; i
++ )
8880 if ((*queue
)[i
].job
== (int)jobid
)
8885 /* NT treats not found as bad param... yet another bad
8887 result
= WERR_INVALID_PARAM
;
8892 * if the print job does not have a DEVMODE associated with it,
8893 * just use the one for the printer. A NULL devicemode is not
8894 * a failure condition
8897 if ( !(nt_devmode
=print_job_devmode( lp_const_servicename(snum
), jobid
)) )
8898 devmode
= construct_dev_mode(lp_const_servicename(snum
));
8900 if ((devmode
= SMB_MALLOC_P(DEVICEMODE
)) != NULL
) {
8901 ZERO_STRUCTP( devmode
);
8902 convert_nt_devicemode( devmode
, nt_devmode
);
8906 fill_job_info_2(info_2
, &((*queue
)[i
-1]), i
, snum
, ntprinter
, devmode
);
8908 *needed
+= spoolss_size_job_info_2(info_2
);
8910 if (*needed
> offered
) {
8911 result
= WERR_INSUFFICIENT_BUFFER
;
8915 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
8916 result
= WERR_NOMEM
;
8920 smb_io_job_info_2("", buffer
, info_2
, 0);
8925 /* Cleanup allocated memory */
8927 free_job_info_2(info_2
); /* Also frees devmode */
8933 /****************************************************************************
8934 ****************************************************************************/
8936 WERROR
_spoolss_getjob( pipes_struct
*p
, SPOOL_Q_GETJOB
*q_u
, SPOOL_R_GETJOB
*r_u
)
8938 POLICY_HND
*handle
= &q_u
->handle
;
8939 uint32 jobid
= q_u
->jobid
;
8940 uint32 level
= q_u
->level
;
8941 RPC_BUFFER
*buffer
= NULL
;
8942 uint32 offered
= q_u
->offered
;
8943 uint32
*needed
= &r_u
->needed
;
8944 WERROR wstatus
= WERR_OK
;
8945 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8948 print_queue_struct
*queue
= NULL
;
8949 print_status_struct prt_status
;
8951 /* that's an [in out] buffer */
8953 if (!q_u
->buffer
&& (offered
!=0)) {
8954 return WERR_INVALID_PARAM
;
8957 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
8958 buffer
= r_u
->buffer
;
8960 DEBUG(5,("spoolss_getjob\n"));
8964 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
8967 wstatus
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8968 if ( !W_ERROR_IS_OK(wstatus
) )
8971 count
= print_queue_status(snum
, &queue
, &prt_status
);
8973 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8974 count
, prt_status
.status
, prt_status
.message
));
8978 wstatus
= getjob_level_1(&queue
, count
, snum
, ntprinter
, jobid
,
8979 buffer
, offered
, needed
);
8982 wstatus
= getjob_level_2(&queue
, count
, snum
, ntprinter
, jobid
,
8983 buffer
, offered
, needed
);
8986 wstatus
= WERR_UNKNOWN_LEVEL
;
8991 free_a_printer( &ntprinter
, 2 );
8996 /********************************************************************
8997 spoolss_getprinterdataex
8999 From MSDN documentation of GetPrinterDataEx: pass request
9000 to GetPrinterData if key is "PrinterDriverData".
9001 ********************************************************************/
9003 WERROR
_spoolss_getprinterdataex(pipes_struct
*p
, SPOOL_Q_GETPRINTERDATAEX
*q_u
, SPOOL_R_GETPRINTERDATAEX
*r_u
)
9005 POLICY_HND
*handle
= &q_u
->handle
;
9006 uint32 in_size
= q_u
->size
;
9007 uint32
*type
= &r_u
->type
;
9008 uint32
*out_size
= &r_u
->size
;
9009 uint8
**data
= &r_u
->data
;
9010 uint32
*needed
= &r_u
->needed
;
9011 fstring keyname
, valuename
;
9013 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9015 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9017 WERROR status
= WERR_OK
;
9019 DEBUG(4,("_spoolss_getprinterdataex\n"));
9021 unistr2_to_ascii(keyname
, &q_u
->keyname
, sizeof(keyname
) - 1);
9022 unistr2_to_ascii(valuename
, &q_u
->valuename
, sizeof(valuename
) - 1);
9024 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9025 keyname
, valuename
));
9027 /* in case of problem, return some default values */
9031 *out_size
= in_size
;
9034 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9035 status
= WERR_BADFID
;
9039 /* Is the handle to a printer or to the server? */
9041 if (Printer
->printer_type
== SPLHND_SERVER
) {
9042 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9043 status
= WERR_INVALID_PARAM
;
9047 if ( !get_printer_snum(p
,handle
, &snum
, NULL
) )
9050 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9051 if ( !W_ERROR_IS_OK(status
) )
9054 /* check to see if the keyname is valid */
9055 if ( !strlen(keyname
) ) {
9056 status
= WERR_INVALID_PARAM
;
9060 if ( lookup_printerkey( printer
->info_2
->data
, keyname
) == -1 ) {
9061 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname
));
9062 free_a_printer( &printer
, 2 );
9063 status
= WERR_BADFILE
;
9067 /* When given a new keyname, we should just create it */
9069 status
= get_printer_dataex( p
->mem_ctx
, printer
, keyname
, valuename
, type
, data
, needed
, in_size
);
9071 if (*needed
> *out_size
)
9072 status
= WERR_MORE_DATA
;
9075 if ( !W_ERROR_IS_OK(status
) )
9077 DEBUG(5, ("error: allocating %d\n", *out_size
));
9079 /* reply this param doesn't exist */
9083 if( (*data
=(uint8
*)TALLOC_ZERO(p
->mem_ctx
, *out_size
*sizeof(uint8
))) == NULL
) {
9084 status
= WERR_NOMEM
;
9094 free_a_printer( &printer
, 2 );
9099 /********************************************************************
9100 * spoolss_setprinterdataex
9101 ********************************************************************/
9103 WERROR
_spoolss_setprinterdataex(pipes_struct
*p
, SPOOL_Q_SETPRINTERDATAEX
*q_u
, SPOOL_R_SETPRINTERDATAEX
*r_u
)
9105 POLICY_HND
*handle
= &q_u
->handle
;
9106 uint32 type
= q_u
->type
;
9107 uint8
*data
= q_u
->data
;
9108 uint32 real_len
= q_u
->real_len
;
9110 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9112 WERROR status
= WERR_OK
;
9113 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9118 DEBUG(4,("_spoolss_setprinterdataex\n"));
9120 /* From MSDN documentation of SetPrinterDataEx: pass request to
9121 SetPrinterData if key is "PrinterDriverData" */
9124 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9128 if ( Printer
->printer_type
== SPLHND_SERVER
) {
9129 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9130 return WERR_INVALID_PARAM
;
9133 if ( !get_printer_snum(p
,handle
, &snum
, NULL
) )
9137 * Access check : NT returns "access denied" if you make a
9138 * SetPrinterData call without the necessary privildge.
9139 * we were originally returning OK if nothing changed
9140 * which made Win2k issue **a lot** of SetPrinterData
9141 * when connecting to a printer --jerry
9144 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
)
9146 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9147 return WERR_ACCESS_DENIED
;
9150 status
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
9151 if (!W_ERROR_IS_OK(status
))
9154 unistr2_to_ascii( valuename
, &q_u
->value
, sizeof(valuename
) - 1);
9155 unistr2_to_ascii( keyname
, &q_u
->key
, sizeof(keyname
) - 1);
9157 /* check for OID in valuename */
9159 if ( (oid_string
= strchr( valuename
, ',' )) != NULL
)
9165 /* save the registry data */
9167 status
= set_printer_dataex( printer
, keyname
, valuename
, type
, data
, real_len
);
9169 if ( W_ERROR_IS_OK(status
) )
9171 /* save the OID if one was specified */
9173 fstrcat( keyname
, "\\" );
9174 fstrcat( keyname
, SPOOL_OID_KEY
);
9177 * I'm not checking the status here on purpose. Don't know
9178 * if this is right, but I'm returning the status from the
9179 * previous set_printer_dataex() call. I have no idea if
9180 * this is right. --jerry
9183 set_printer_dataex( printer
, keyname
, valuename
,
9184 REG_SZ
, (uint8
*)oid_string
,
9185 strlen(oid_string
)+1 );
9188 status
= mod_a_printer(printer
, 2);
9191 free_a_printer(&printer
, 2);
9197 /********************************************************************
9198 * spoolss_deleteprinterdataex
9199 ********************************************************************/
9201 WERROR
_spoolss_deleteprinterdataex(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERDATAEX
*q_u
, SPOOL_R_DELETEPRINTERDATAEX
*r_u
)
9203 POLICY_HND
*handle
= &q_u
->handle
;
9204 UNISTR2
*value
= &q_u
->valuename
;
9205 UNISTR2
*key
= &q_u
->keyname
;
9207 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9209 WERROR status
= WERR_OK
;
9210 Printer_entry
*Printer
=find_printer_index_by_hnd(p
, handle
);
9211 pstring valuename
, keyname
;
9213 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9216 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9220 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
9223 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9224 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9225 return WERR_ACCESS_DENIED
;
9228 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9229 if (!W_ERROR_IS_OK(status
))
9232 unistr2_to_ascii( valuename
, value
, sizeof(valuename
)-1 );
9233 unistr2_to_ascii( keyname
, key
, sizeof(keyname
)-1 );
9235 status
= delete_printer_dataex( printer
, keyname
, valuename
);
9237 if ( W_ERROR_IS_OK(status
) )
9238 mod_a_printer( printer
, 2 );
9240 free_a_printer(&printer
, 2);
9245 /********************************************************************
9246 * spoolss_enumprinterkey
9247 ********************************************************************/
9250 WERROR
_spoolss_enumprinterkey(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERKEY
*q_u
, SPOOL_R_ENUMPRINTERKEY
*r_u
)
9253 fstring
*keynames
= NULL
;
9254 uint16
*enumkeys
= NULL
;
9257 POLICY_HND
*handle
= &q_u
->handle
;
9258 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9259 NT_PRINTER_DATA
*data
;
9260 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9262 WERROR status
= WERR_BADFILE
;
9265 DEBUG(4,("_spoolss_enumprinterkey\n"));
9268 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9272 if ( !get_printer_snum(p
,handle
, &snum
, NULL
) )
9275 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9276 if (!W_ERROR_IS_OK(status
))
9279 /* get the list of subkey names */
9281 unistr2_to_ascii( key
, &q_u
->key
, sizeof(key
)-1 );
9282 data
= printer
->info_2
->data
;
9284 num_keys
= get_printer_subkeys( data
, key
, &keynames
);
9286 if ( num_keys
== -1 ) {
9287 status
= WERR_BADFILE
;
9291 printerkey_len
= init_unistr_array( &enumkeys
, keynames
, NULL
);
9293 r_u
->needed
= printerkey_len
*2;
9295 if ( q_u
->size
< r_u
->needed
) {
9296 status
= WERR_MORE_DATA
;
9300 if (!make_spoolss_buffer5(p
->mem_ctx
, &r_u
->keys
, printerkey_len
, enumkeys
)) {
9301 status
= WERR_NOMEM
;
9307 if ( q_u
->size
< r_u
->needed
)
9308 status
= WERR_MORE_DATA
;
9311 free_a_printer( &printer
, 2 );
9312 SAFE_FREE( keynames
);
9317 /********************************************************************
9318 * spoolss_deleteprinterkey
9319 ********************************************************************/
9321 WERROR
_spoolss_deleteprinterkey(pipes_struct
*p
, SPOOL_Q_DELETEPRINTERKEY
*q_u
, SPOOL_R_DELETEPRINTERKEY
*r_u
)
9323 POLICY_HND
*handle
= &q_u
->handle
;
9324 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9326 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9330 DEBUG(5,("spoolss_deleteprinterkey\n"));
9333 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle
)));
9337 /* if keyname == NULL, return error */
9339 if ( !q_u
->keyname
.buffer
)
9340 return WERR_INVALID_PARAM
;
9342 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
9345 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9346 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9347 return WERR_ACCESS_DENIED
;
9350 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9351 if (!W_ERROR_IS_OK(status
))
9354 /* delete the key and all subneys */
9356 unistr2_to_ascii(key
, &q_u
->keyname
, sizeof(key
) - 1);
9358 status
= delete_all_printer_data( printer
->info_2
, key
);
9360 if ( W_ERROR_IS_OK(status
) )
9361 status
= mod_a_printer(printer
, 2);
9363 free_a_printer( &printer
, 2 );
9369 /********************************************************************
9370 * spoolss_enumprinterdataex
9371 ********************************************************************/
9373 WERROR
_spoolss_enumprinterdataex(pipes_struct
*p
, SPOOL_Q_ENUMPRINTERDATAEX
*q_u
, SPOOL_R_ENUMPRINTERDATAEX
*r_u
)
9375 POLICY_HND
*handle
= &q_u
->handle
;
9376 uint32 in_size
= q_u
->size
;
9379 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9380 PRINTER_ENUM_VALUES
*enum_values
= NULL
;
9381 NT_PRINTER_DATA
*p_data
;
9383 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
9388 REGISTRY_VALUE
*val
;
9393 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9396 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle
)));
9401 * first check for a keyname of NULL or "". Win2k seems to send
9402 * this a lot and we should send back WERR_INVALID_PARAM
9403 * no need to spend time looking up the printer in this case.
9407 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9408 if ( !strlen(key
) ) {
9409 result
= WERR_INVALID_PARAM
;
9413 /* get the printer off of disk */
9415 if (!get_printer_snum(p
,handle
, &snum
, NULL
))
9418 ZERO_STRUCT(printer
);
9419 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9420 if (!W_ERROR_IS_OK(result
))
9423 /* now look for a match on the key name */
9425 p_data
= printer
->info_2
->data
;
9427 unistr2_to_ascii(key
, &q_u
->key
, sizeof(key
) - 1);
9428 if ( (key_index
= lookup_printerkey( p_data
, key
)) == -1 )
9430 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key
));
9431 result
= WERR_INVALID_PARAM
;
9438 /* allocate the memory for the array of pointers -- if necessary */
9440 num_entries
= regval_ctr_numvals( p_data
->keys
[key_index
].values
);
9443 if ( (enum_values
=TALLOC_ARRAY(p
->mem_ctx
, PRINTER_ENUM_VALUES
, num_entries
)) == NULL
)
9445 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9446 (unsigned long)num_entries
*sizeof(PRINTER_ENUM_VALUES
)));
9447 result
= WERR_NOMEM
;
9451 memset( enum_values
, 0x0, num_entries
*sizeof(PRINTER_ENUM_VALUES
) );
9455 * loop through all params and build the array to pass
9456 * back to the client
9459 for ( i
=0; i
<num_entries
; i
++ )
9461 /* lookup the registry value */
9463 val
= regval_ctr_specific_value( p_data
->keys
[key_index
].values
, i
);
9464 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
) ));
9468 value_name
= regval_name( val
);
9469 init_unistr( &enum_values
[i
].valuename
, value_name
);
9470 enum_values
[i
].value_len
= (strlen(value_name
)+1) * 2;
9471 enum_values
[i
].type
= regval_type( val
);
9473 data_len
= regval_size( val
);
9475 if ( !(enum_values
[i
].data
= (uint8
*)TALLOC_MEMDUP(p
->mem_ctx
, regval_data_p(val
), data_len
)) )
9477 DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
9479 result
= WERR_NOMEM
;
9483 enum_values
[i
].data_len
= data_len
;
9485 /* keep track of the size of the array in bytes */
9487 needed
+= spoolss_size_printer_enum_values(&enum_values
[i
]);
9490 /* housekeeping information in the reply */
9492 r_u
->needed
= needed
;
9493 r_u
->returned
= num_entries
;
9495 if (needed
> in_size
) {
9496 result
= WERR_MORE_DATA
;
9500 /* copy data into the reply */
9502 r_u
->ctr
.size
= r_u
->needed
;
9503 r_u
->ctr
.size_of_array
= r_u
->returned
;
9504 r_u
->ctr
.values
= enum_values
;
9510 free_a_printer(&printer
, 2);
9515 /****************************************************************************
9516 ****************************************************************************/
9518 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1
*info
, char *name
)
9520 init_unistr(&info
->name
, name
);
9523 static WERROR
getprintprocessordirectory_level_1(UNISTR2
*name
,
9524 UNISTR2
*environment
,
9531 PRINTPROCESSOR_DIRECTORY_1
*info
=NULL
;
9532 WERROR result
= WERR_OK
;
9534 unistr2_to_ascii(long_archi
, environment
, sizeof(long_archi
)-1);
9536 if (!get_short_archi(long_archi
))
9537 return WERR_INVALID_ENVIRONMENT
;
9539 if((info
=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1
)) == NULL
)
9542 pstrcpy(path
, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9544 fill_printprocessordirectory_1(info
, path
);
9546 *needed
+= spoolss_size_printprocessordirectory_info_1(info
);
9548 if (*needed
> offered
) {
9549 result
= WERR_INSUFFICIENT_BUFFER
;
9553 if (!rpcbuf_alloc_size(buffer
, *needed
)) {
9554 result
= WERR_INSUFFICIENT_BUFFER
;
9558 smb_io_printprocessordirectory_1("", buffer
, info
, 0);
9566 WERROR
_spoolss_getprintprocessordirectory(pipes_struct
*p
, SPOOL_Q_GETPRINTPROCESSORDIRECTORY
*q_u
, SPOOL_R_GETPRINTPROCESSORDIRECTORY
*r_u
)
9568 uint32 level
= q_u
->level
;
9569 RPC_BUFFER
*buffer
= NULL
;
9570 uint32 offered
= q_u
->offered
;
9571 uint32
*needed
= &r_u
->needed
;
9574 /* that's an [in out] buffer */
9576 if (!q_u
->buffer
&& (offered
!=0)) {
9577 return WERR_INVALID_PARAM
;
9580 rpcbuf_move(q_u
->buffer
, &r_u
->buffer
);
9581 buffer
= r_u
->buffer
;
9583 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9589 result
= getprintprocessordirectory_level_1
9590 (&q_u
->name
, &q_u
->environment
, buffer
, offered
, needed
);
9593 result
= WERR_UNKNOWN_LEVEL
;
9599 /*******************************************************************
9600 Streams the monitor UI DLL name in UNICODE
9601 *******************************************************************/
9603 static WERROR
xcvtcp_monitorui( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9604 RPC_BUFFER
*out
, uint32
*needed
)
9606 const char *dllname
= "tcpmonui.dll";
9608 *needed
= (strlen(dllname
)+1) * 2;
9610 if ( rpcbuf_get_size(out
) < *needed
) {
9611 return WERR_INSUFFICIENT_BUFFER
;
9614 if ( !make_monitorui_buf( out
, dllname
) ) {
9621 /*******************************************************************
9622 Create a new TCP/IP port
9623 *******************************************************************/
9625 static WERROR
xcvtcp_addport( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9626 RPC_BUFFER
*out
, uint32
*needed
)
9628 NT_PORT_DATA_1 port1
;
9631 ZERO_STRUCT( port1
);
9633 /* convert to our internal port data structure */
9635 if ( !convert_port_data_1( &port1
, in
) ) {
9639 /* create the device URI and call the add_port_hook() */
9641 switch ( port1
.protocol
) {
9642 case PORT_PROTOCOL_DIRECT
:
9643 pstr_sprintf( device_uri
, "socket://%s:%d/", port1
.hostaddr
, port1
.port
);
9646 case PORT_PROTOCOL_LPR
:
9647 pstr_sprintf( device_uri
, "lpr://%s/%s", port1
.hostaddr
, port1
.queue
);
9651 return WERR_UNKNOWN_PORT
;
9654 return add_port_hook( token
, port1
.name
, device_uri
);
9657 /*******************************************************************
9658 *******************************************************************/
9660 struct xcv_api_table xcvtcp_cmds
[] = {
9661 { "MonitorUI", xcvtcp_monitorui
},
9662 { "AddPort", xcvtcp_addport
},
9666 static WERROR
process_xcvtcp_command( NT_USER_TOKEN
*token
, const char *command
,
9667 RPC_BUFFER
*inbuf
, RPC_BUFFER
*outbuf
,
9672 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9674 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9675 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9676 return xcvtcp_cmds
[i
].fn( token
, inbuf
, outbuf
, needed
);
9679 return WERR_BADFUNC
;
9682 /*******************************************************************
9683 *******************************************************************/
9684 #if 0 /* don't support management using the "Local Port" monitor */
9686 static WERROR
xcvlocal_monitorui( NT_USER_TOKEN
*token
, RPC_BUFFER
*in
,
9687 RPC_BUFFER
*out
, uint32
*needed
)
9689 const char *dllname
= "localui.dll";
9691 *needed
= (strlen(dllname
)+1) * 2;
9693 if ( rpcbuf_get_size(out
) < *needed
) {
9694 return WERR_INSUFFICIENT_BUFFER
;
9697 if ( !make_monitorui_buf( out
, dllname
)) {
9704 /*******************************************************************
9705 *******************************************************************/
9707 struct xcv_api_table xcvlocal_cmds
[] = {
9708 { "MonitorUI", xcvlocal_monitorui
},
9712 struct xcv_api_table xcvlocal_cmds
[] = {
9719 /*******************************************************************
9720 *******************************************************************/
9722 static WERROR
process_xcvlocal_command( NT_USER_TOKEN
*token
, const char *command
,
9723 RPC_BUFFER
*inbuf
, RPC_BUFFER
*outbuf
,
9728 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9730 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9731 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9732 return xcvlocal_cmds
[i
].fn( token
, inbuf
, outbuf
, needed
);
9734 return WERR_BADFUNC
;
9737 /*******************************************************************
9738 *******************************************************************/
9740 WERROR
_spoolss_xcvdataport(pipes_struct
*p
, SPOOL_Q_XCVDATAPORT
*q_u
, SPOOL_R_XCVDATAPORT
*r_u
)
9742 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, &q_u
->handle
);
9746 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u
->handle
)));
9750 /* Has to be a handle to the TCP/IP port monitor */
9752 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9753 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9757 /* requires administrative access to the server */
9759 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9760 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9761 return WERR_ACCESS_DENIED
;
9764 /* Get the command name. There's numerous commands supported by the
9765 TCPMON interface. */
9767 rpcstr_pull(command
, q_u
->dataname
.buffer
, sizeof(command
),
9768 q_u
->dataname
.uni_str_len
*2, 0);
9770 /* Allocate the outgoing buffer */
9772 rpcbuf_init( &r_u
->outdata
, q_u
->offered
, p
->mem_ctx
);
9774 switch ( Printer
->printer_type
) {
9775 case SPLHND_PORTMON_TCP
:
9776 return process_xcvtcp_command( p
->pipe_user
.nt_user_token
, command
,
9777 &q_u
->indata
, &r_u
->outdata
, &r_u
->needed
);
9778 case SPLHND_PORTMON_LOCAL
:
9779 return process_xcvlocal_command( p
->pipe_user
.nt_user_token
, command
,
9780 &q_u
->indata
, &r_u
->outdata
, &r_u
->needed
);
9783 return WERR_INVALID_PRINT_MONITOR
;