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.
10 * Copyright (C) Guenther Deschner 2009-2010.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
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. */
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/init_spoolss.h"
33 #include "librpc/gen_ndr/messaging.h"
36 /* macros stolen from s4 spoolss server */
37 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
38 ((info)?ndr_size_##fn(info, level, 0):0)
40 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
41 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
43 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
44 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
46 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
49 extern userdom_struct current_user_info
;
52 #define DBGC_CLASS DBGC_RPC_SRV
54 #ifndef MAX_OPEN_PRINTER_EXS
55 #define MAX_OPEN_PRINTER_EXS 50
58 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
60 static Printer_entry
*printers_list
;
62 typedef struct _counter_printer_0
{
63 struct _counter_printer_0
*next
;
64 struct _counter_printer_0
*prev
;
70 static counter_printer_0
*counter_list
;
72 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
73 static uint32_t smb_connections
= 0;
76 /* in printing/nt_printing.c */
78 extern struct standard_mapping printer_std_mapping
, printserver_std_mapping
;
80 /* API table for Xcv Monitor functions */
82 struct xcv_api_table
{
84 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, NT_USER_TOKEN
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
87 /********************************************************************
88 * Canonicalize servername.
89 ********************************************************************/
91 static const char *canon_servername(const char *servername
)
93 const char *pservername
= servername
;
94 while (*pservername
== '\\') {
100 /* translate between internal status numbers and NT status numbers */
101 static int nt_printj_status(int v
)
107 return JOB_STATUS_PAUSED
;
109 return JOB_STATUS_SPOOLING
;
111 return JOB_STATUS_PRINTING
;
113 return JOB_STATUS_ERROR
;
115 return JOB_STATUS_DELETING
;
117 return JOB_STATUS_OFFLINE
;
119 return JOB_STATUS_PAPEROUT
;
121 return JOB_STATUS_PRINTED
;
123 return JOB_STATUS_DELETED
;
125 return JOB_STATUS_BLOCKED_DEVQ
;
126 case LPQ_USER_INTERVENTION
:
127 return JOB_STATUS_USER_INTERVENTION
;
132 static int nt_printq_status(int v
)
136 return PRINTER_STATUS_PAUSED
;
145 /***************************************************************************
146 Disconnect from the client
147 ****************************************************************************/
149 static void srv_spoolss_replycloseprinter(int snum
, struct policy_handle
*handle
)
155 * Tell the specific printing tdb we no longer want messages for this printer
156 * by deregistering our PID.
159 if (!print_notify_deregister_pid(snum
))
160 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
162 /* weird if the test succeds !!! */
163 if (smb_connections
==0) {
164 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
168 status
= rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe
, talloc_tos(),
171 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
172 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
173 win_errstr(result
)));
175 /* if it's the last connection, deconnect the IPC$ share */
176 if (smb_connections
==1) {
178 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe
) );
179 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
181 messaging_deregister(smbd_messaging_context(),
182 MSG_PRINTER_NOTIFY2
, NULL
);
184 /* Tell the connections db we're no longer interested in
185 * printer notify messages. */
187 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY
);
193 /****************************************************************************
194 Functions to free a printer entry datastruct.
195 ****************************************************************************/
197 static int printer_entry_destructor(Printer_entry
*Printer
)
199 if (Printer
->notify
.client_connected
== true) {
202 if ( Printer
->printer_type
== SPLHND_SERVER
) {
204 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
205 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
206 snum
= print_queue_snum(Printer
->sharename
);
208 srv_spoolss_replycloseprinter(snum
,
209 &Printer
->notify
.client_hnd
);
213 Printer
->notify
.flags
=0;
214 Printer
->notify
.options
=0;
215 Printer
->notify
.localmachine
[0]='\0';
216 Printer
->notify
.printerlocal
=0;
217 TALLOC_FREE(Printer
->notify
.option
);
218 Printer
->notify
.client_connected
= false;
220 free_nt_devicemode( &Printer
->nt_devmode
);
221 free_a_printer( &Printer
->printer_info
, 2 );
223 /* Remove from the internal list. */
224 DLIST_REMOVE(printers_list
, Printer
);
228 /****************************************************************************
229 find printer index by handle
230 ****************************************************************************/
232 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
,
233 struct policy_handle
*hnd
)
235 Printer_entry
*find_printer
= NULL
;
237 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
238 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
245 /****************************************************************************
246 Close printer index by handle.
247 ****************************************************************************/
249 static bool close_printer_handle(pipes_struct
*p
, struct policy_handle
*hnd
)
251 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
254 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
259 close_policy_hnd(p
, hnd
);
264 /****************************************************************************
265 Delete a printer given a handle.
266 ****************************************************************************/
268 static WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *sharename
)
270 char *cmd
= lp_deleteprinter_cmd();
271 char *command
= NULL
;
273 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
274 bool is_print_op
= false;
276 /* can't fail if we don't try */
281 command
= talloc_asprintf(ctx
,
288 is_print_op
= user_has_privileges( token
, &se_printop
);
290 DEBUG(10,("Running [%s]\n", command
));
292 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
297 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
298 /* Tell everyone we updated smb.conf. */
299 message_send_all(smbd_messaging_context(),
300 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
306 /********** END SePrintOperatorPrivlege BLOCK **********/
308 DEBUGADD(10,("returned [%d]\n", ret
));
310 TALLOC_FREE(command
);
313 return WERR_BADFID
; /* What to return here? */
315 /* go ahead and re-read the services immediately */
317 reload_services(false);
320 if ( lp_servicenumber( sharename
) > 0 )
321 return WERR_ACCESS_DENIED
;
326 /****************************************************************************
327 Delete a printer given a handle.
328 ****************************************************************************/
330 static WERROR
delete_printer_handle(pipes_struct
*p
, struct policy_handle
*hnd
)
332 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
335 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
341 * It turns out that Windows allows delete printer on a handle
342 * opened by an admin user, then used on a pipe handle created
343 * by an anonymous user..... but they're working on security.... riiight !
347 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
348 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
349 return WERR_ACCESS_DENIED
;
352 /* this does not need a become root since the access check has been
353 done on the handle already */
355 if (del_a_printer( Printer
->sharename
) != 0) {
356 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
360 return delete_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
361 Printer
->sharename
);
364 /****************************************************************************
365 Return the snum of a printer corresponding to an handle.
366 ****************************************************************************/
368 static bool get_printer_snum(pipes_struct
*p
, struct policy_handle
*hnd
,
369 int *number
, struct share_params
**params
)
371 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
374 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
379 switch (Printer
->printer_type
) {
381 DEBUG(4,("short name:%s\n", Printer
->sharename
));
382 *number
= print_queue_snum(Printer
->sharename
);
383 return (*number
!= -1);
391 /****************************************************************************
392 Set printer handle type.
393 Check if it's \\server or \\server\printer
394 ****************************************************************************/
396 static bool set_printer_hnd_printertype(Printer_entry
*Printer
, const char *handlename
)
398 DEBUG(3,("Setting printer type=%s\n", handlename
));
400 if ( strlen(handlename
) < 3 ) {
401 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
405 /* it's a print server */
406 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
407 DEBUGADD(4,("Printer is a print server\n"));
408 Printer
->printer_type
= SPLHND_SERVER
;
410 /* it's a printer (set_printer_hnd_name() will handle port monitors */
412 DEBUGADD(4,("Printer is a printer\n"));
413 Printer
->printer_type
= SPLHND_PRINTER
;
419 /****************************************************************************
420 Set printer handle name.. Accept names like \\server, \\server\printer,
421 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
422 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
423 XcvDataPort() interface.
424 ****************************************************************************/
426 static bool set_printer_hnd_name(Printer_entry
*Printer
, const char *handlename
)
429 int n_services
=lp_numservices();
430 char *aprinter
, *printername
;
431 const char *servername
;
434 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
437 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
,
438 (unsigned long)strlen(handlename
)));
440 aprinter
= CONST_DISCARD(char *, handlename
);
441 if ( *handlename
== '\\' ) {
442 servername
= canon_servername(handlename
);
443 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
448 servername
= global_myname();
451 /* save the servername to fill in replies on this handle */
453 if ( !is_myname_or_ipaddr( servername
) )
456 fstrcpy( Printer
->servername
, servername
);
458 if ( Printer
->printer_type
== SPLHND_SERVER
)
461 if ( Printer
->printer_type
!= SPLHND_PRINTER
)
464 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
466 /* check for the Port Monitor Interface */
468 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
469 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
470 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
473 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
474 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
475 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
479 /* Search all sharenames first as this is easier than pulling
480 the printer_info_2 off of disk. Don't use find_service() since
481 that calls out to map_username() */
483 /* do another loop to look for printernames */
485 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
487 /* no point going on if this is not a printer */
489 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
492 fstrcpy(sname
, lp_servicename(snum
));
493 if ( strequal( aprinter
, sname
) ) {
498 /* no point looking up the printer object if
499 we aren't allowing printername != sharename */
501 if ( lp_force_printername(snum
) )
504 fstrcpy(sname
, lp_servicename(snum
));
508 /* This call doesn't fill in the location or comment from
509 * a CUPS server for efficiency with large numbers of printers.
513 result
= get_a_printer_search( NULL
, &printer
, 2, sname
);
514 if ( !W_ERROR_IS_OK(result
) ) {
515 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
516 sname
, win_errstr(result
)));
520 /* printername is always returned as \\server\printername */
521 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
522 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
523 printer
->info_2
->printername
));
524 free_a_printer( &printer
, 2);
530 if ( strequal(printername
, aprinter
) ) {
531 free_a_printer( &printer
, 2);
536 DEBUGADD(10, ("printername: %s\n", printername
));
538 free_a_printer( &printer
, 2);
541 free_a_printer( &printer
, 2);
544 DEBUGADD(4,("Printer not found\n"));
548 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
550 fstrcpy(Printer
->sharename
, sname
);
555 /****************************************************************************
556 Find first available printer slot. creates a printer handle for you.
557 ****************************************************************************/
559 static bool open_printer_hnd(pipes_struct
*p
, struct policy_handle
*hnd
,
560 const char *name
, uint32_t access_granted
)
562 Printer_entry
*new_printer
;
564 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
566 new_printer
= TALLOC_ZERO_P(NULL
, Printer_entry
);
567 if (new_printer
== NULL
) {
570 talloc_set_destructor(new_printer
, printer_entry_destructor
);
572 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
573 TALLOC_FREE(new_printer
);
577 /* Add to the internal list. */
578 DLIST_ADD(printers_list
, new_printer
);
580 new_printer
->notify
.option
=NULL
;
582 if (!set_printer_hnd_printertype(new_printer
, name
)) {
583 close_printer_handle(p
, hnd
);
587 if (!set_printer_hnd_name(new_printer
, name
)) {
588 close_printer_handle(p
, hnd
);
592 new_printer
->access_granted
= access_granted
;
594 DEBUG(5, ("%d printer handles active\n",
595 (int)num_pipe_handles(p
->pipe_handles
)));
600 /***************************************************************************
601 check to see if the client motify handle is monitoring the notification
602 given by (notify_type, notify_field).
603 **************************************************************************/
605 static bool is_monitoring_event_flags(uint32_t flags
, uint16_t notify_type
,
606 uint16_t notify_field
)
611 static bool is_monitoring_event(Printer_entry
*p
, uint16_t notify_type
,
612 uint16_t notify_field
)
614 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
618 * Flags should always be zero when the change notify
619 * is registered by the client's spooler. A user Win32 app
620 * might use the flags though instead of the NOTIFY_OPTION_INFO
629 return is_monitoring_event_flags(
630 p
->notify
.flags
, notify_type
, notify_field
);
632 for (i
= 0; i
< option
->count
; i
++) {
634 /* Check match for notify_type */
636 if (option
->types
[i
].type
!= notify_type
)
639 /* Check match for field */
641 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
642 if (option
->types
[i
].fields
[j
].field
== notify_field
) {
648 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
649 p
->servername
, p
->sharename
, notify_type
, notify_field
));
654 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
655 _data->data.integer[0] = _integer; \
656 _data->data.integer[1] = 0;
659 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
660 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
661 if (!_data->data.string.string) {\
662 _data->data.string.size = 0; \
664 _data->data.string.size = strlen_m_term(_p) * 2;
666 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
667 _data->data.devmode.devmode = _devmode;
669 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
670 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
671 if (!_data->data.sd.sd) { \
672 _data->data.sd.sd_size = 0; \
674 _data->data.sd.sd_size = _size;
676 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
681 struct spoolss_Time st
;
685 if (!init_systemtime(&st
, t
)) {
689 p
= talloc_array(mem_ctx
, char, len
);
695 * Systemtime must be linearized as a set of UINT16's.
696 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
699 SSVAL(p
, 0, st
.year
);
700 SSVAL(p
, 2, st
.month
);
701 SSVAL(p
, 4, st
.day_of_week
);
703 SSVAL(p
, 8, st
.hour
);
704 SSVAL(p
, 10, st
.minute
);
705 SSVAL(p
, 12, st
.second
);
706 SSVAL(p
, 14, st
.millisecond
);
712 /* Convert a notification message to a struct spoolss_Notify */
714 static void notify_one_value(struct spoolss_notify_msg
*msg
,
715 struct spoolss_Notify
*data
,
718 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
721 static void notify_string(struct spoolss_notify_msg
*msg
,
722 struct spoolss_Notify
*data
,
725 /* The length of the message includes the trailing \0 */
727 data
->data
.string
.size
= msg
->len
* 2;
728 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
729 if (!data
->data
.string
.string
) {
730 data
->data
.string
.size
= 0;
735 static void notify_system_time(struct spoolss_notify_msg
*msg
,
736 struct spoolss_Notify
*data
,
739 data
->data
.string
.string
= NULL
;
740 data
->data
.string
.size
= 0;
742 if (msg
->len
!= sizeof(time_t)) {
743 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
748 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
749 &data
->data
.string
.string
,
750 &data
->data
.string
.size
);
753 struct notify2_message_table
{
755 void (*fn
)(struct spoolss_notify_msg
*msg
,
756 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
759 static struct notify2_message_table printer_notify_table
[] = {
760 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string
},
761 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string
},
762 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string
},
763 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string
},
764 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string
},
765 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string
},
766 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string
},
767 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL
},
768 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string
},
769 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string
},
770 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL
},
771 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string
},
772 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
773 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value
},
774 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value
},
775 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL
},
776 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL
},
777 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL
},
778 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value
},
781 static struct notify2_message_table job_notify_table
[] = {
782 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL
},
783 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL
},
784 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL
},
785 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string
},
786 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL
},
787 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL
},
788 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL
},
789 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL
},
790 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL
},
791 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL
},
792 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value
},
793 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL
},
794 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
795 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string
},
796 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL
},
797 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL
},
798 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time
},
799 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL
},
800 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL
},
801 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL
},
802 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value
},
803 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL
},
804 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value
},
805 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL
},
809 /***********************************************************************
810 Allocate talloc context for container object
811 **********************************************************************/
813 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
818 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
823 /***********************************************************************
824 release all allocated memory and zero out structure
825 **********************************************************************/
827 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
833 talloc_destroy(ctr
->ctx
);
840 /***********************************************************************
841 **********************************************************************/
843 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
851 /***********************************************************************
852 **********************************************************************/
854 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
856 if ( !ctr
|| !ctr
->msg_groups
)
859 if ( idx
>= ctr
->num_groups
)
862 return &ctr
->msg_groups
[idx
];
866 /***********************************************************************
867 How many groups of change messages do we have ?
868 **********************************************************************/
870 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
875 return ctr
->num_groups
;
878 /***********************************************************************
879 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
880 **********************************************************************/
882 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
884 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
885 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
886 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
892 /* loop over all groups looking for a matching printer name */
894 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
895 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
899 /* add a new group? */
901 if ( i
== ctr
->num_groups
) {
904 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
905 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
908 ctr
->msg_groups
= groups
;
910 /* clear the new entry and set the printer name */
912 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
913 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
916 /* add the change messages; 'i' is the correct index now regardless */
918 msg_grp
= &ctr
->msg_groups
[i
];
922 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
923 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
926 msg_grp
->msgs
= msg_list
;
928 new_slot
= msg_grp
->num_msgs
-1;
929 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
931 /* need to allocate own copy of data */
934 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
935 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
937 return ctr
->num_groups
;
940 void construct_info_data(struct spoolss_Notify
*info_data
,
941 enum spoolss_NotifyType type
,
945 /***********************************************************************
946 Send a change notication message on all handles which have a call
948 **********************************************************************/
950 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
953 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
954 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
955 SPOOLSS_NOTIFY_MSG
*messages
;
956 int sending_msg_count
;
959 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
963 messages
= msg_group
->msgs
;
966 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
970 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
972 /* loop over all printers */
974 for (p
= printers_list
; p
; p
= p
->next
) {
975 struct spoolss_Notify
*notifies
;
980 /* Is there notification on this handle? */
982 if ( !p
->notify
.client_connected
)
985 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
987 /* For this printer? Print servers always receive
990 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
991 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
994 DEBUG(10,("Our printer\n"));
996 /* allocate the max entries possible */
998 notifies
= TALLOC_ZERO_ARRAY(mem_ctx
, struct spoolss_Notify
, msg_group
->num_msgs
);
1003 /* build the array of change notifications */
1005 sending_msg_count
= 0;
1007 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
1008 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
1010 /* Are we monitoring this event? */
1012 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1015 sending_msg_count
++;
1018 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1019 msg
->type
, msg
->field
, p
->sharename
));
1022 * if the is a printer notification handle and not a job notification
1023 * type, then set the id to 0. Other wise just use what was specified
1026 * When registering change notification on a print server handle
1027 * we always need to send back the id (snum) matching the printer
1028 * for which the change took place. For change notify registered
1029 * on a printer handle, this does not matter and the id should be 0.
1034 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1040 /* Convert unix jobid to smb jobid */
1042 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1043 id
= sysjob_to_jobid(msg
->id
);
1046 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1051 construct_info_data( ¬ifies
[count
], msg
->type
, msg
->field
, id
);
1054 case PRINTER_NOTIFY_TYPE
:
1055 if ( printer_notify_table
[msg
->field
].fn
)
1056 printer_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1059 case JOB_NOTIFY_TYPE
:
1060 if ( job_notify_table
[msg
->field
].fn
)
1061 job_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1065 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1072 if ( sending_msg_count
) {
1075 union spoolss_ReplyPrinterInfo info
;
1076 struct spoolss_NotifyInfo info0
;
1077 uint32_t reply_result
;
1079 info0
.version
= 0x2;
1080 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1081 info0
.count
= count
;
1082 info0
.notifies
= notifies
;
1084 info
.info0
= &info0
;
1086 status
= rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe
, mem_ctx
,
1087 &p
->notify
.client_hnd
,
1088 p
->notify
.change
, /* color */
1091 0, /* reply_type, must be 0 */
1094 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(werr
)) {
1095 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1096 notify_cli_pipe
->srv_name_slash
,
1099 switch (reply_result
) {
1102 case PRINTER_NOTIFY_INFO_DISCARDED
:
1103 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1104 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1113 DEBUG(8,("send_notify2_changes: Exit...\n"));
1117 /***********************************************************************
1118 **********************************************************************/
1120 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1123 uint32_t tv_sec
, tv_usec
;
1126 /* Unpack message */
1128 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "f",
1131 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "ddddddd",
1133 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1136 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "dd",
1137 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1139 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "B",
1140 &msg
->len
, &msg
->notify
.data
);
1142 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1143 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1145 tv
->tv_sec
= tv_sec
;
1146 tv
->tv_usec
= tv_usec
;
1149 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1150 msg
->notify
.value
[1]));
1152 dump_data(3, (uint8_t *)msg
->notify
.data
, msg
->len
);
1157 /********************************************************************
1158 Receive a notify2 message list
1159 ********************************************************************/
1161 static void receive_notify2_message_list(struct messaging_context
*msg
,
1164 struct server_id server_id
,
1167 size_t msg_count
, i
;
1168 char *buf
= (char *)data
->data
;
1171 SPOOLSS_NOTIFY_MSG notify
;
1172 SPOOLSS_NOTIFY_MSG_CTR messages
;
1175 if (data
->length
< 4) {
1176 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1180 msg_count
= IVAL(buf
, 0);
1183 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1185 if (msg_count
== 0) {
1186 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1190 /* initialize the container */
1192 ZERO_STRUCT( messages
);
1193 notify_msg_ctr_init( &messages
);
1196 * build message groups for each printer identified
1197 * in a change_notify msg. Remember that a PCN message
1198 * includes the handle returned for the srv_spoolss_replyopenprinter()
1199 * call. Therefore messages are grouped according to printer handle.
1202 for ( i
=0; i
<msg_count
; i
++ ) {
1203 struct timeval msg_tv
;
1205 if (msg_ptr
+ 4 - buf
> data
->length
) {
1206 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1210 msg_len
= IVAL(msg_ptr
,0);
1213 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1214 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1218 /* unpack messages */
1220 ZERO_STRUCT( notify
);
1221 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1224 /* add to correct list in container */
1226 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1228 /* free memory that might have been allocated by notify2_unpack_msg() */
1230 if ( notify
.len
!= 0 )
1231 SAFE_FREE( notify
.notify
.data
);
1234 /* process each group of messages */
1236 num_groups
= notify_msg_ctr_numgroups( &messages
);
1237 for ( i
=0; i
<num_groups
; i
++ )
1238 send_notify2_changes( &messages
, i
);
1243 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1244 (uint32_t)msg_count
));
1246 notify_msg_ctr_destroy( &messages
);
1251 /********************************************************************
1252 Send a message to ourself about new driver being installed
1253 so we can upgrade the information for each printer bound to this
1255 ********************************************************************/
1257 static bool srv_spoolss_drv_upgrade_printer(const char *drivername
)
1259 int len
= strlen(drivername
);
1264 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1267 messaging_send_buf(smbd_messaging_context(), procid_self(),
1268 MSG_PRINTER_DRVUPGRADE
,
1269 (uint8_t *)drivername
, len
+1);
1274 /**********************************************************************
1275 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1276 over all printers, upgrading ones as necessary
1277 **********************************************************************/
1279 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1282 struct server_id server_id
,
1287 int n_services
= lp_numservices();
1290 len
= MIN(data
->length
,sizeof(drivername
)-1);
1291 strncpy(drivername
, (const char *)data
->data
, len
);
1293 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1295 /* Iterate the printer list */
1297 for (snum
=0; snum
<n_services
; snum
++)
1299 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1302 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1304 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1305 if (!W_ERROR_IS_OK(result
))
1308 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1310 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1312 /* all we care about currently is the change_id */
1314 result
= mod_a_printer(printer
, 2);
1315 if (!W_ERROR_IS_OK(result
)) {
1316 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1317 win_errstr(result
)));
1321 free_a_printer(&printer
, 2);
1328 /********************************************************************
1329 Update the cache for all printq's with a registered client
1331 ********************************************************************/
1333 void update_monitored_printq_cache( void )
1335 Printer_entry
*printer
= printers_list
;
1338 /* loop through all printers and update the cache where
1339 client_connected == true */
1342 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1343 && printer
->notify
.client_connected
)
1345 snum
= print_queue_snum(printer
->sharename
);
1346 print_queue_status( snum
, NULL
, NULL
);
1349 printer
= printer
->next
;
1355 /****************************************************************
1356 _spoolss_OpenPrinter
1357 ****************************************************************/
1359 WERROR
_spoolss_OpenPrinter(pipes_struct
*p
,
1360 struct spoolss_OpenPrinter
*r
)
1362 struct spoolss_OpenPrinterEx e
;
1365 ZERO_STRUCT(e
.in
.userlevel
);
1367 e
.in
.printername
= r
->in
.printername
;
1368 e
.in
.datatype
= r
->in
.datatype
;
1369 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1370 e
.in
.access_mask
= r
->in
.access_mask
;
1373 e
.out
.handle
= r
->out
.handle
;
1375 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1377 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1378 /* OpenPrinterEx returns this for a bad
1379 * printer name. We must return WERR_INVALID_PRINTER_NAME
1382 werr
= WERR_INVALID_PRINTER_NAME
;
1388 /********************************************************************
1389 ********************************************************************/
1391 bool convert_devicemode(const char *printername
,
1392 const struct spoolss_DeviceMode
*devmode
,
1393 NT_DEVICEMODE
**pp_nt_devmode
)
1395 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1398 * Ensure nt_devmode is a valid pointer
1399 * as we will be overwriting it.
1402 if (nt_devmode
== NULL
) {
1403 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1404 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1408 fstrcpy(nt_devmode
->devicename
, devmode
->devicename
);
1409 fstrcpy(nt_devmode
->formname
, devmode
->formname
);
1411 nt_devmode
->devicename
[31] = '\0';
1412 nt_devmode
->formname
[31] = '\0';
1414 nt_devmode
->specversion
= devmode
->specversion
;
1415 nt_devmode
->driverversion
= devmode
->driverversion
;
1416 nt_devmode
->size
= devmode
->size
;
1417 nt_devmode
->fields
= devmode
->fields
;
1418 nt_devmode
->orientation
= devmode
->orientation
;
1419 nt_devmode
->papersize
= devmode
->papersize
;
1420 nt_devmode
->paperlength
= devmode
->paperlength
;
1421 nt_devmode
->paperwidth
= devmode
->paperwidth
;
1422 nt_devmode
->scale
= devmode
->scale
;
1423 nt_devmode
->copies
= devmode
->copies
;
1424 nt_devmode
->defaultsource
= devmode
->defaultsource
;
1425 nt_devmode
->printquality
= devmode
->printquality
;
1426 nt_devmode
->color
= devmode
->color
;
1427 nt_devmode
->duplex
= devmode
->duplex
;
1428 nt_devmode
->yresolution
= devmode
->yresolution
;
1429 nt_devmode
->ttoption
= devmode
->ttoption
;
1430 nt_devmode
->collate
= devmode
->collate
;
1432 nt_devmode
->logpixels
= devmode
->logpixels
;
1433 nt_devmode
->bitsperpel
= devmode
->bitsperpel
;
1434 nt_devmode
->pelswidth
= devmode
->pelswidth
;
1435 nt_devmode
->pelsheight
= devmode
->pelsheight
;
1436 nt_devmode
->displayflags
= devmode
->displayflags
;
1437 nt_devmode
->displayfrequency
= devmode
->displayfrequency
;
1438 nt_devmode
->icmmethod
= devmode
->icmmethod
;
1439 nt_devmode
->icmintent
= devmode
->icmintent
;
1440 nt_devmode
->mediatype
= devmode
->mediatype
;
1441 nt_devmode
->dithertype
= devmode
->dithertype
;
1442 nt_devmode
->reserved1
= devmode
->reserved1
;
1443 nt_devmode
->reserved2
= devmode
->reserved2
;
1444 nt_devmode
->panningwidth
= devmode
->panningwidth
;
1445 nt_devmode
->panningheight
= devmode
->panningheight
;
1448 * Only change private and driverextra if the incoming devmode
1449 * has a new one. JRA.
1452 if ((devmode
->__driverextra_length
!= 0) && (devmode
->driverextra_data
.data
!= NULL
)) {
1453 SAFE_FREE(nt_devmode
->nt_dev_private
);
1454 nt_devmode
->driverextra
= devmode
->__driverextra_length
;
1455 if((nt_devmode
->nt_dev_private
= SMB_MALLOC_ARRAY(uint8_t, nt_devmode
->driverextra
)) == NULL
)
1457 memcpy(nt_devmode
->nt_dev_private
, devmode
->driverextra_data
.data
, nt_devmode
->driverextra
);
1460 *pp_nt_devmode
= nt_devmode
;
1465 /****************************************************************
1466 _spoolss_OpenPrinterEx
1467 ****************************************************************/
1469 WERROR
_spoolss_OpenPrinterEx(pipes_struct
*p
,
1470 struct spoolss_OpenPrinterEx
*r
)
1473 Printer_entry
*Printer
=NULL
;
1475 if (!r
->in
.printername
) {
1476 return WERR_INVALID_PARAM
;
1479 /* some sanity check because you can open a printer or a print server */
1480 /* aka: \\server\printer or \\server */
1482 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1484 if (!open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0)) {
1485 ZERO_STRUCTP(r
->out
.handle
);
1486 return WERR_INVALID_PARAM
;
1489 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1491 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1492 "handle we created for printer %s\n", r
->in
.printername
));
1493 close_printer_handle(p
, r
->out
.handle
);
1494 ZERO_STRUCTP(r
->out
.handle
);
1495 return WERR_INVALID_PARAM
;
1499 * First case: the user is opening the print server:
1501 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1502 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1504 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1505 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1506 * or if the user is listed in the smb.conf printer admin parameter.
1508 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1509 * client view printer folder, but does not show the MSAPW.
1511 * Note: this test needs code to check access rights here too. Jeremy
1512 * could you look at this?
1514 * Second case: the user is opening a printer:
1515 * NT doesn't let us connect to a printer if the connecting user
1516 * doesn't have print permission.
1518 * Third case: user is opening a Port Monitor
1519 * access checks same as opening a handle to the print server.
1522 switch (Printer
->printer_type
)
1525 case SPLHND_PORTMON_TCP
:
1526 case SPLHND_PORTMON_LOCAL
:
1527 /* Printserver handles use global struct... */
1531 /* Map standard access rights to object specific access rights */
1533 se_map_standard(&r
->in
.access_mask
,
1534 &printserver_std_mapping
);
1536 /* Deny any object specific bits that don't apply to print
1537 servers (i.e printer and job specific bits) */
1539 r
->in
.access_mask
&= SPECIFIC_RIGHTS_MASK
;
1541 if (r
->in
.access_mask
&
1542 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1543 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1544 close_printer_handle(p
, r
->out
.handle
);
1545 ZERO_STRUCTP(r
->out
.handle
);
1546 return WERR_ACCESS_DENIED
;
1549 /* Allow admin access */
1551 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1553 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1555 if (!lp_ms_add_printer_wizard()) {
1556 close_printer_handle(p
, r
->out
.handle
);
1557 ZERO_STRUCTP(r
->out
.handle
);
1558 return WERR_ACCESS_DENIED
;
1561 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1562 and not a printer admin, then fail */
1564 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
1565 !user_has_privileges(p
->server_info
->ptok
,
1567 !token_contains_name_in_list(
1568 uidtoname(p
->server_info
->utok
.uid
),
1570 p
->server_info
->ptok
,
1571 lp_printer_admin(snum
))) {
1572 close_printer_handle(p
, r
->out
.handle
);
1573 ZERO_STRUCTP(r
->out
.handle
);
1574 return WERR_ACCESS_DENIED
;
1577 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1581 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1584 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1585 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1587 /* We fall through to return WERR_OK */
1590 case SPLHND_PRINTER
:
1591 /* NT doesn't let us connect to a printer if the connecting user
1592 doesn't have print permission. */
1594 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1595 close_printer_handle(p
, r
->out
.handle
);
1596 ZERO_STRUCTP(r
->out
.handle
);
1600 if (r
->in
.access_mask
== SEC_FLAG_MAXIMUM_ALLOWED
) {
1601 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1604 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1606 /* map an empty access mask to the minimum access mask */
1607 if (r
->in
.access_mask
== 0x0)
1608 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1611 * If we are not serving the printer driver for this printer,
1612 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1613 * will keep NT clients happy --jerry
1616 if (lp_use_client_driver(snum
)
1617 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1619 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1622 /* check smb.conf parameters and the the sec_desc */
1624 if ( !check_access(get_client_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1625 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1626 ZERO_STRUCTP(r
->out
.handle
);
1627 return WERR_ACCESS_DENIED
;
1630 if (!user_ok_token(uidtoname(p
->server_info
->utok
.uid
), NULL
,
1631 p
->server_info
->ptok
, snum
) ||
1632 !print_access_check(p
->server_info
, snum
,
1633 r
->in
.access_mask
)) {
1634 DEBUG(3, ("access DENIED for printer open\n"));
1635 close_printer_handle(p
, r
->out
.handle
);
1636 ZERO_STRUCTP(r
->out
.handle
);
1637 return WERR_ACCESS_DENIED
;
1640 if ((r
->in
.access_mask
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1641 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1642 close_printer_handle(p
, r
->out
.handle
);
1643 ZERO_STRUCTP(r
->out
.handle
);
1644 return WERR_ACCESS_DENIED
;
1647 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1648 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1650 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1652 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1653 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1658 /* sanity check to prevent programmer error */
1659 ZERO_STRUCTP(r
->out
.handle
);
1663 Printer
->access_granted
= r
->in
.access_mask
;
1666 * If the client sent a devmode in the OpenPrinter() call, then
1667 * save it here in case we get a job submission on this handle
1670 if ((Printer
->printer_type
!= SPLHND_SERVER
) &&
1671 r
->in
.devmode_ctr
.devmode
) {
1672 convert_devicemode(Printer
->sharename
,
1673 r
->in
.devmode_ctr
.devmode
,
1674 &Printer
->nt_devmode
);
1677 #if 0 /* JERRY -- I'm doubtful this is really effective */
1678 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1679 optimization in Windows 2000 clients --jerry */
1681 if ( (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1682 && (RA_WIN2K
== get_remote_arch()) )
1684 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1685 sys_usleep( 500000 );
1692 /****************************************************************************
1693 ****************************************************************************/
1695 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2
*r
,
1696 NT_PRINTER_INFO_LEVEL_2
*d
)
1698 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1704 d
->attributes
= r
->attributes
;
1705 d
->priority
= r
->priority
;
1706 d
->default_priority
= r
->defaultpriority
;
1707 d
->starttime
= r
->starttime
;
1708 d
->untiltime
= r
->untiltime
;
1709 d
->status
= r
->status
;
1710 d
->cjobs
= r
->cjobs
;
1712 fstrcpy(d
->servername
, r
->servername
);
1713 fstrcpy(d
->printername
, r
->printername
);
1714 fstrcpy(d
->sharename
, r
->sharename
);
1715 fstrcpy(d
->portname
, r
->portname
);
1716 fstrcpy(d
->drivername
, r
->drivername
);
1717 slprintf(d
->comment
, sizeof(d
->comment
)-1, "%s", r
->comment
);
1718 fstrcpy(d
->location
, r
->location
);
1719 fstrcpy(d
->sepfile
, r
->sepfile
);
1720 fstrcpy(d
->printprocessor
, r
->printprocessor
);
1721 fstrcpy(d
->datatype
, r
->datatype
);
1722 fstrcpy(d
->parameters
, r
->parameters
);
1727 /****************************************************************************
1728 ****************************************************************************/
1730 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1731 NT_PRINTER_INFO_LEVEL
*printer
)
1735 switch (info_ctr
->level
) {
1737 /* allocate memory if needed. Messy because
1738 convert_printer_info is used to update an existing
1739 printer or build a new one */
1741 if (!printer
->info_2
) {
1742 printer
->info_2
= TALLOC_ZERO_P(printer
, NT_PRINTER_INFO_LEVEL_2
);
1743 if (!printer
->info_2
) {
1744 DEBUG(0,("convert_printer_info: "
1745 "talloc() failed!\n"));
1750 ret
= printer_info2_to_nt_printer_info2(info_ctr
->info
.info2
,
1752 printer
->info_2
->setuptime
= time(NULL
);
1759 /****************************************************************
1760 _spoolss_ClosePrinter
1761 ****************************************************************/
1763 WERROR
_spoolss_ClosePrinter(pipes_struct
*p
,
1764 struct spoolss_ClosePrinter
*r
)
1766 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1768 if (Printer
&& Printer
->document_started
) {
1769 struct spoolss_EndDocPrinter e
;
1771 e
.in
.handle
= r
->in
.handle
;
1773 _spoolss_EndDocPrinter(p
, &e
);
1776 if (!close_printer_handle(p
, r
->in
.handle
))
1779 /* clear the returned printer handle. Observed behavior
1780 from Win2k server. Don't think this really matters.
1781 Previous code just copied the value of the closed
1784 ZERO_STRUCTP(r
->out
.handle
);
1789 /****************************************************************
1790 _spoolss_DeletePrinter
1791 ****************************************************************/
1793 WERROR
_spoolss_DeletePrinter(pipes_struct
*p
,
1794 struct spoolss_DeletePrinter
*r
)
1796 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1799 if (Printer
&& Printer
->document_started
) {
1800 struct spoolss_EndDocPrinter e
;
1802 e
.in
.handle
= r
->in
.handle
;
1804 _spoolss_EndDocPrinter(p
, &e
);
1807 result
= delete_printer_handle(p
, r
->in
.handle
);
1809 update_c_setprinter(false);
1814 /*******************************************************************
1815 * static function to lookup the version id corresponding to an
1816 * long architecture string
1817 ******************************************************************/
1819 static const struct print_architecture_table_node archi_table
[]= {
1821 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
1822 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
1823 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
1824 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
1825 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
1826 {"Windows IA64", SPL_ARCH_IA64
, 3 },
1827 {"Windows x64", SPL_ARCH_X64
, 3 },
1831 static int get_version_id(const char *arch
)
1835 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1837 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1838 return (archi_table
[i
].version
);
1844 /****************************************************************
1845 _spoolss_DeletePrinterDriver
1846 ****************************************************************/
1848 WERROR
_spoolss_DeletePrinterDriver(pipes_struct
*p
,
1849 struct spoolss_DeletePrinterDriver
*r
)
1852 struct spoolss_DriverInfo8
*info
= NULL
;
1853 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
1856 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1857 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1859 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1860 and not a printer admin, then fail */
1862 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
1863 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
1864 && !token_contains_name_in_list(
1865 uidtoname(p
->server_info
->utok
.uid
), NULL
,
1866 NULL
, p
->server_info
->ptok
,
1867 lp_printer_admin(-1)) )
1869 return WERR_ACCESS_DENIED
;
1872 /* check that we have a valid driver name first */
1874 if ((version
= get_version_id(r
->in
.architecture
)) == -1)
1875 return WERR_INVALID_ENVIRONMENT
;
1877 if (!W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
, &info
, r
->in
.driver
,
1881 /* try for Win2k driver if "Windows NT x86" */
1883 if ( version
== 2 ) {
1885 if (!W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
,
1890 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1894 /* otherwise it was a failure */
1896 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1902 if (printer_driver_in_use(info
)) {
1903 status
= WERR_PRINTER_DRIVER_IN_USE
;
1909 if (W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
,
1912 r
->in
.architecture
, 3)))
1914 /* if we get to here, we now have 2 driver info structures to remove */
1915 /* remove the Win2k driver first*/
1917 status_win2k
= delete_printer_driver(
1918 p
, info_win2k
, 3, false);
1919 free_a_printer_driver(info_win2k
);
1921 /* this should not have failed---if it did, report to client */
1922 if ( !W_ERROR_IS_OK(status_win2k
) )
1924 status
= status_win2k
;
1930 status
= delete_printer_driver(p
, info
, version
, false);
1932 /* if at least one of the deletes succeeded return OK */
1934 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
1938 free_a_printer_driver(info
);
1943 /****************************************************************
1944 _spoolss_DeletePrinterDriverEx
1945 ****************************************************************/
1947 WERROR
_spoolss_DeletePrinterDriverEx(pipes_struct
*p
,
1948 struct spoolss_DeletePrinterDriverEx
*r
)
1950 struct spoolss_DriverInfo8
*info
= NULL
;
1951 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
1955 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1956 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1958 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1959 and not a printer admin, then fail */
1961 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
1962 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
1963 && !token_contains_name_in_list(
1964 uidtoname(p
->server_info
->utok
.uid
), NULL
, NULL
,
1965 p
->server_info
->ptok
, lp_printer_admin(-1)) )
1967 return WERR_ACCESS_DENIED
;
1970 /* check that we have a valid driver name first */
1971 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
1972 /* this is what NT returns */
1973 return WERR_INVALID_ENVIRONMENT
;
1976 if (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
1977 version
= r
->in
.version
;
1979 status
= get_a_printer_driver(p
->mem_ctx
, &info
, r
->in
.driver
,
1980 r
->in
.architecture
, version
);
1982 if ( !W_ERROR_IS_OK(status
) )
1985 * if the client asked for a specific version,
1986 * or this is something other than Windows NT x86,
1990 if ( (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
1993 /* try for Win2k driver if "Windows NT x86" */
1996 if (!W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
, &info
, r
->in
.driver
,
1999 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2004 if (printer_driver_in_use(info
)) {
2005 status
= WERR_PRINTER_DRIVER_IN_USE
;
2010 * we have a couple of cases to consider.
2011 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2012 * then the delete should fail if **any** files overlap with
2014 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2015 * non-overlapping files
2016 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2017 * is set, the do not delete any files
2018 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2021 delete_files
= r
->in
.delete_flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2023 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2025 if (delete_files
&& printer_driver_files_in_use(info
, info
) & (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
)) {
2026 /* no idea of the correct error here */
2027 status
= WERR_ACCESS_DENIED
;
2032 /* also check for W32X86/3 if necessary; maybe we already have? */
2034 if ( (version
== 2) && ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2035 if (W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
, &info_win2k
,
2037 r
->in
.architecture
, 3)))
2040 if (delete_files
&& printer_driver_files_in_use(info
, info_win2k
) & (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) ) {
2041 /* no idea of the correct error here */
2042 free_a_printer_driver(info_win2k
);
2043 status
= WERR_ACCESS_DENIED
;
2047 /* if we get to here, we now have 2 driver info structures to remove */
2048 /* remove the Win2k driver first*/
2050 status_win2k
= delete_printer_driver(
2051 p
, info_win2k
, 3, delete_files
);
2052 free_a_printer_driver(info_win2k
);
2054 /* this should not have failed---if it did, report to client */
2056 if ( !W_ERROR_IS_OK(status_win2k
) )
2061 status
= delete_printer_driver(p
, info
, version
, delete_files
);
2063 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2066 free_a_printer_driver(info
);
2072 /****************************************************************************
2073 Internal routine for removing printerdata
2074 ***************************************************************************/
2076 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2078 return delete_printer_data( printer
->info_2
, key
, value
);
2081 /****************************************************************************
2082 Internal routine for storing printerdata
2083 ***************************************************************************/
2085 WERROR
set_printer_dataex(NT_PRINTER_INFO_LEVEL
*printer
,
2086 const char *key
, const char *value
,
2087 uint32_t type
, uint8_t *data
, int real_len
)
2089 /* the registry objects enforce uniqueness based on value name */
2091 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2094 /********************************************************************
2095 GetPrinterData on a printer server Handle.
2096 ********************************************************************/
2098 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2100 enum winreg_Type
*type
,
2101 union spoolss_PrinterData
*data
)
2103 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2105 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2111 if (!StrCaseCmp(value
, "BeepEnabled")) {
2117 if (!StrCaseCmp(value
, "EventLog")) {
2119 /* formally was 0x1b */
2124 if (!StrCaseCmp(value
, "NetPopup")) {
2130 if (!StrCaseCmp(value
, "MajorVersion")) {
2133 /* Windows NT 4.0 seems to not allow uploading of drivers
2134 to a server that reports 0x3 as the MajorVersion.
2135 need to investigate more how Win2k gets around this .
2138 if (RA_WINNT
== get_remote_arch()) {
2147 if (!StrCaseCmp(value
, "MinorVersion")) {
2154 * uint32_t size = 0x114
2155 * uint32_t major = 5
2156 * uint32_t minor = [0|1]
2157 * uint32_t build = [2195|2600]
2158 * extra unicode string = e.g. "Service Pack 3"
2160 if (!StrCaseCmp(value
, "OSVersion")) {
2162 enum ndr_err_code ndr_err
;
2163 struct spoolss_OSVersion os
;
2165 os
.major
= 5; /* Windows 2000 == 5.0 */
2167 os
.build
= 2195; /* build */
2168 os
.extra_string
= ""; /* leave extra string empty */
2170 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &os
,
2171 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2172 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2173 return WERR_GENERAL_FAILURE
;
2177 data
->binary
= blob
;
2183 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2186 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2187 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2192 if (!StrCaseCmp(value
, "Architecture")) {
2194 data
->string
= talloc_strdup(mem_ctx
,
2195 lp_parm_const_string(GLOBAL_SECTION_SNUM
, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86
));
2196 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2201 if (!StrCaseCmp(value
, "DsPresent")) {
2204 /* only show the publish check box if we are a
2205 member of a AD domain */
2207 if (lp_security() == SEC_ADS
) {
2215 if (!StrCaseCmp(value
, "DNSMachineName")) {
2216 const char *hostname
= get_mydnsfullname();
2219 return WERR_BADFILE
;
2223 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2224 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2231 return WERR_INVALID_PARAM
;
2234 /****************************************************************
2235 _spoolss_GetPrinterData
2236 ****************************************************************/
2238 WERROR
_spoolss_GetPrinterData(pipes_struct
*p
,
2239 struct spoolss_GetPrinterData
*r
)
2241 struct spoolss_GetPrinterDataEx r2
;
2243 r2
.in
.handle
= r
->in
.handle
;
2244 r2
.in
.key_name
= "PrinterDriverData";
2245 r2
.in
.value_name
= r
->in
.value_name
;
2246 r2
.in
.offered
= r
->in
.offered
;
2247 r2
.out
.type
= r
->out
.type
;
2248 r2
.out
.data
= r
->out
.data
;
2249 r2
.out
.needed
= r
->out
.needed
;
2251 return _spoolss_GetPrinterDataEx(p
, &r2
);
2254 /*********************************************************
2255 Connect to the client machine.
2256 **********************************************************/
2258 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2259 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2262 struct cli_state
*the_cli
;
2263 struct sockaddr_storage rm_addr
;
2264 char addr
[INET6_ADDRSTRLEN
];
2266 if ( is_zero_addr((struct sockaddr
*)client_ss
) ) {
2267 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2269 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20, false) ) {
2270 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2273 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2275 rm_addr
= *client_ss
;
2276 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2277 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2281 if (ismyaddr((struct sockaddr
*)&rm_addr
)) {
2282 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2287 /* setup the connection */
2288 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2289 &rm_addr
, 0, "IPC$", "IPC",
2293 0, lp_client_signing(), NULL
);
2295 if ( !NT_STATUS_IS_OK( ret
) ) {
2296 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2301 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2302 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2303 cli_shutdown(the_cli
);
2308 * Ok - we have an anonymous connection to the IPC$ share.
2309 * Now start the NT Domain stuff :-).
2312 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2313 if (!NT_STATUS_IS_OK(ret
)) {
2314 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2315 remote_machine
, nt_errstr(ret
)));
2316 cli_shutdown(the_cli
);
2323 /***************************************************************************
2324 Connect to the client.
2325 ****************************************************************************/
2327 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2328 uint32_t localprinter
, uint32_t type
,
2329 struct policy_handle
*handle
,
2330 struct sockaddr_storage
*client_ss
)
2336 * If it's the first connection, contact the client
2337 * and connect to the IPC$ share anonymously
2339 if (smb_connections
==0) {
2340 fstring unix_printer
;
2342 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2344 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ss
, unix_printer
))
2347 messaging_register(smbd_messaging_context(), NULL
,
2348 MSG_PRINTER_NOTIFY2
,
2349 receive_notify2_message_list
);
2350 /* Tell the connections db we're now interested in printer
2351 * notify messages. */
2352 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY
);
2356 * Tell the specific printing tdb we want messages for this printer
2357 * by registering our PID.
2360 if (!print_notify_register_pid(snum
))
2361 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2365 status
= rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe
, talloc_tos(),
2373 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
2374 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2375 win_errstr(result
)));
2377 return (W_ERROR_IS_OK(result
));
2380 /****************************************************************
2381 ****************************************************************/
2383 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2384 const struct spoolss_NotifyOption
*r
)
2386 struct spoolss_NotifyOption
*option
;
2393 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2400 if (!option
->count
) {
2404 option
->types
= talloc_zero_array(option
,
2405 struct spoolss_NotifyOptionType
, option
->count
);
2406 if (!option
->types
) {
2407 talloc_free(option
);
2411 for (i
=0; i
< option
->count
; i
++) {
2412 option
->types
[i
] = r
->types
[i
];
2414 if (option
->types
[i
].count
) {
2415 option
->types
[i
].fields
= talloc_zero_array(option
,
2416 union spoolss_Field
, option
->types
[i
].count
);
2417 if (!option
->types
[i
].fields
) {
2418 talloc_free(option
);
2421 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2422 option
->types
[i
].fields
[k
] =
2423 r
->types
[i
].fields
[k
];
2431 /****************************************************************
2432 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2434 * before replying OK: status=0 a rpc call is made to the workstation
2435 * asking ReplyOpenPrinter
2437 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2438 * called from api_spoolss_rffpcnex
2439 ****************************************************************/
2441 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct
*p
,
2442 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2445 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2446 struct sockaddr_storage client_ss
;
2448 /* store the notify value in the printer struct */
2450 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2453 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2454 "Invalid handle (%s:%u:%u).\n",
2455 OUR_HANDLE(r
->in
.handle
)));
2459 Printer
->notify
.flags
= r
->in
.flags
;
2460 Printer
->notify
.options
= r
->in
.options
;
2461 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2463 TALLOC_FREE(Printer
->notify
.option
);
2464 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2466 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2468 /* Connect to the client machine and send a ReplyOpenPrinter */
2470 if ( Printer
->printer_type
== SPLHND_SERVER
)
2472 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2473 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2476 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2477 "client_address is %s\n", p
->client_address
));
2479 if (!interpret_string_addr(&client_ss
, p
->client_address
,
2481 return WERR_SERVER_UNAVAILABLE
;
2484 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2485 Printer
->notify
.printerlocal
, 1,
2486 &Printer
->notify
.client_hnd
, &client_ss
))
2487 return WERR_SERVER_UNAVAILABLE
;
2489 Printer
->notify
.client_connected
= true;
2494 /*******************************************************************
2495 * fill a notify_info_data with the servername
2496 ********************************************************************/
2498 static void spoolss_notify_server_name(int snum
,
2499 struct spoolss_Notify
*data
,
2500 print_queue_struct
*queue
,
2501 NT_PRINTER_INFO_LEVEL
*printer
,
2502 TALLOC_CTX
*mem_ctx
)
2504 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->servername
);
2507 /*******************************************************************
2508 * fill a notify_info_data with the printername (not including the servername).
2509 ********************************************************************/
2511 static void spoolss_notify_printer_name(int snum
,
2512 struct spoolss_Notify
*data
,
2513 print_queue_struct
*queue
,
2514 NT_PRINTER_INFO_LEVEL
*printer
,
2515 TALLOC_CTX
*mem_ctx
)
2517 /* the notify name should not contain the \\server\ part */
2518 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2521 p
= printer
->info_2
->printername
;
2526 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2529 /*******************************************************************
2530 * fill a notify_info_data with the servicename
2531 ********************************************************************/
2533 static void spoolss_notify_share_name(int snum
,
2534 struct spoolss_Notify
*data
,
2535 print_queue_struct
*queue
,
2536 NT_PRINTER_INFO_LEVEL
*printer
,
2537 TALLOC_CTX
*mem_ctx
)
2539 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2542 /*******************************************************************
2543 * fill a notify_info_data with the port name
2544 ********************************************************************/
2546 static void spoolss_notify_port_name(int snum
,
2547 struct spoolss_Notify
*data
,
2548 print_queue_struct
*queue
,
2549 NT_PRINTER_INFO_LEVEL
*printer
,
2550 TALLOC_CTX
*mem_ctx
)
2552 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->portname
);
2555 /*******************************************************************
2556 * fill a notify_info_data with the printername
2557 * but it doesn't exist, have to see what to do
2558 ********************************************************************/
2560 static void spoolss_notify_driver_name(int snum
,
2561 struct spoolss_Notify
*data
,
2562 print_queue_struct
*queue
,
2563 NT_PRINTER_INFO_LEVEL
*printer
,
2564 TALLOC_CTX
*mem_ctx
)
2566 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->drivername
);
2569 /*******************************************************************
2570 * fill a notify_info_data with the comment
2571 ********************************************************************/
2573 static void spoolss_notify_comment(int snum
,
2574 struct spoolss_Notify
*data
,
2575 print_queue_struct
*queue
,
2576 NT_PRINTER_INFO_LEVEL
*printer
,
2577 TALLOC_CTX
*mem_ctx
)
2581 if (*printer
->info_2
->comment
== '\0') {
2582 p
= lp_comment(snum
);
2584 p
= printer
->info_2
->comment
;
2587 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->comment
);
2590 /*******************************************************************
2591 * fill a notify_info_data with the comment
2592 * location = "Room 1, floor 2, building 3"
2593 ********************************************************************/
2595 static void spoolss_notify_location(int snum
,
2596 struct spoolss_Notify
*data
,
2597 print_queue_struct
*queue
,
2598 NT_PRINTER_INFO_LEVEL
*printer
,
2599 TALLOC_CTX
*mem_ctx
)
2601 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->location
);
2604 /*******************************************************************
2605 * fill a notify_info_data with the device mode
2606 * jfm:xxxx don't to it for know but that's a real problem !!!
2607 ********************************************************************/
2609 static void spoolss_notify_devmode(int snum
,
2610 struct spoolss_Notify
*data
,
2611 print_queue_struct
*queue
,
2612 NT_PRINTER_INFO_LEVEL
*printer
,
2613 TALLOC_CTX
*mem_ctx
)
2615 /* for a dummy implementation we have to zero the fields */
2616 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2619 /*******************************************************************
2620 * fill a notify_info_data with the separator file name
2621 ********************************************************************/
2623 static void spoolss_notify_sepfile(int snum
,
2624 struct spoolss_Notify
*data
,
2625 print_queue_struct
*queue
,
2626 NT_PRINTER_INFO_LEVEL
*printer
,
2627 TALLOC_CTX
*mem_ctx
)
2629 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->sepfile
);
2632 /*******************************************************************
2633 * fill a notify_info_data with the print processor
2634 * jfm:xxxx return always winprint to indicate we don't do anything to it
2635 ********************************************************************/
2637 static void spoolss_notify_print_processor(int snum
,
2638 struct spoolss_Notify
*data
,
2639 print_queue_struct
*queue
,
2640 NT_PRINTER_INFO_LEVEL
*printer
,
2641 TALLOC_CTX
*mem_ctx
)
2643 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->printprocessor
);
2646 /*******************************************************************
2647 * fill a notify_info_data with the print processor options
2648 * jfm:xxxx send an empty string
2649 ********************************************************************/
2651 static void spoolss_notify_parameters(int snum
,
2652 struct spoolss_Notify
*data
,
2653 print_queue_struct
*queue
,
2654 NT_PRINTER_INFO_LEVEL
*printer
,
2655 TALLOC_CTX
*mem_ctx
)
2657 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->parameters
);
2660 /*******************************************************************
2661 * fill a notify_info_data with the data type
2662 * jfm:xxxx always send RAW as data type
2663 ********************************************************************/
2665 static void spoolss_notify_datatype(int snum
,
2666 struct spoolss_Notify
*data
,
2667 print_queue_struct
*queue
,
2668 NT_PRINTER_INFO_LEVEL
*printer
,
2669 TALLOC_CTX
*mem_ctx
)
2671 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->datatype
);
2674 /*******************************************************************
2675 * fill a notify_info_data with the security descriptor
2676 * jfm:xxxx send an null pointer to say no security desc
2677 * have to implement security before !
2678 ********************************************************************/
2680 static void spoolss_notify_security_desc(int snum
,
2681 struct spoolss_Notify
*data
,
2682 print_queue_struct
*queue
,
2683 NT_PRINTER_INFO_LEVEL
*printer
,
2684 TALLOC_CTX
*mem_ctx
)
2686 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
,
2687 printer
->info_2
->secdesc_buf
->sd_size
,
2688 printer
->info_2
->secdesc_buf
->sd
);
2691 /*******************************************************************
2692 * fill a notify_info_data with the attributes
2693 * jfm:xxxx a samba printer is always shared
2694 ********************************************************************/
2696 static void spoolss_notify_attributes(int snum
,
2697 struct spoolss_Notify
*data
,
2698 print_queue_struct
*queue
,
2699 NT_PRINTER_INFO_LEVEL
*printer
,
2700 TALLOC_CTX
*mem_ctx
)
2702 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->attributes
);
2705 /*******************************************************************
2706 * fill a notify_info_data with the priority
2707 ********************************************************************/
2709 static void spoolss_notify_priority(int snum
,
2710 struct spoolss_Notify
*data
,
2711 print_queue_struct
*queue
,
2712 NT_PRINTER_INFO_LEVEL
*printer
,
2713 TALLOC_CTX
*mem_ctx
)
2715 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->priority
);
2718 /*******************************************************************
2719 * fill a notify_info_data with the default priority
2720 ********************************************************************/
2722 static void spoolss_notify_default_priority(int snum
,
2723 struct spoolss_Notify
*data
,
2724 print_queue_struct
*queue
,
2725 NT_PRINTER_INFO_LEVEL
*printer
,
2726 TALLOC_CTX
*mem_ctx
)
2728 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->default_priority
);
2731 /*******************************************************************
2732 * fill a notify_info_data with the start time
2733 ********************************************************************/
2735 static void spoolss_notify_start_time(int snum
,
2736 struct spoolss_Notify
*data
,
2737 print_queue_struct
*queue
,
2738 NT_PRINTER_INFO_LEVEL
*printer
,
2739 TALLOC_CTX
*mem_ctx
)
2741 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->starttime
);
2744 /*******************************************************************
2745 * fill a notify_info_data with the until time
2746 ********************************************************************/
2748 static void spoolss_notify_until_time(int snum
,
2749 struct spoolss_Notify
*data
,
2750 print_queue_struct
*queue
,
2751 NT_PRINTER_INFO_LEVEL
*printer
,
2752 TALLOC_CTX
*mem_ctx
)
2754 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->untiltime
);
2757 /*******************************************************************
2758 * fill a notify_info_data with the status
2759 ********************************************************************/
2761 static void spoolss_notify_status(int snum
,
2762 struct spoolss_Notify
*data
,
2763 print_queue_struct
*queue
,
2764 NT_PRINTER_INFO_LEVEL
*printer
,
2765 TALLOC_CTX
*mem_ctx
)
2767 print_status_struct status
;
2769 print_queue_length(snum
, &status
);
2770 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
2773 /*******************************************************************
2774 * fill a notify_info_data with the number of jobs queued
2775 ********************************************************************/
2777 static void spoolss_notify_cjobs(int snum
,
2778 struct spoolss_Notify
*data
,
2779 print_queue_struct
*queue
,
2780 NT_PRINTER_INFO_LEVEL
*printer
,
2781 TALLOC_CTX
*mem_ctx
)
2783 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, print_queue_length(snum
, NULL
));
2786 /*******************************************************************
2787 * fill a notify_info_data with the average ppm
2788 ********************************************************************/
2790 static void spoolss_notify_average_ppm(int snum
,
2791 struct spoolss_Notify
*data
,
2792 print_queue_struct
*queue
,
2793 NT_PRINTER_INFO_LEVEL
*printer
,
2794 TALLOC_CTX
*mem_ctx
)
2796 /* always respond 8 pages per minutes */
2797 /* a little hard ! */
2798 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->averageppm
);
2801 /*******************************************************************
2802 * fill a notify_info_data with username
2803 ********************************************************************/
2805 static void spoolss_notify_username(int snum
,
2806 struct spoolss_Notify
*data
,
2807 print_queue_struct
*queue
,
2808 NT_PRINTER_INFO_LEVEL
*printer
,
2809 TALLOC_CTX
*mem_ctx
)
2811 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
2814 /*******************************************************************
2815 * fill a notify_info_data with job status
2816 ********************************************************************/
2818 static void spoolss_notify_job_status(int snum
,
2819 struct spoolss_Notify
*data
,
2820 print_queue_struct
*queue
,
2821 NT_PRINTER_INFO_LEVEL
*printer
,
2822 TALLOC_CTX
*mem_ctx
)
2824 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
2827 /*******************************************************************
2828 * fill a notify_info_data with job name
2829 ********************************************************************/
2831 static void spoolss_notify_job_name(int snum
,
2832 struct spoolss_Notify
*data
,
2833 print_queue_struct
*queue
,
2834 NT_PRINTER_INFO_LEVEL
*printer
,
2835 TALLOC_CTX
*mem_ctx
)
2837 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
2840 /*******************************************************************
2841 * fill a notify_info_data with job status
2842 ********************************************************************/
2844 static void spoolss_notify_job_status_string(int snum
,
2845 struct spoolss_Notify
*data
,
2846 print_queue_struct
*queue
,
2847 NT_PRINTER_INFO_LEVEL
*printer
,
2848 TALLOC_CTX
*mem_ctx
)
2851 * Now we're returning job status codes we just return a "" here. JRA.
2856 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2859 switch (queue
->status
) {
2864 p
= ""; /* NT provides the paused string */
2873 #endif /* NO LONGER NEEDED. */
2875 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2878 /*******************************************************************
2879 * fill a notify_info_data with job time
2880 ********************************************************************/
2882 static void spoolss_notify_job_time(int snum
,
2883 struct spoolss_Notify
*data
,
2884 print_queue_struct
*queue
,
2885 NT_PRINTER_INFO_LEVEL
*printer
,
2886 TALLOC_CTX
*mem_ctx
)
2888 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
2891 /*******************************************************************
2892 * fill a notify_info_data with job size
2893 ********************************************************************/
2895 static void spoolss_notify_job_size(int snum
,
2896 struct spoolss_Notify
*data
,
2897 print_queue_struct
*queue
,
2898 NT_PRINTER_INFO_LEVEL
*printer
,
2899 TALLOC_CTX
*mem_ctx
)
2901 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
2904 /*******************************************************************
2905 * fill a notify_info_data with page info
2906 ********************************************************************/
2907 static void spoolss_notify_total_pages(int snum
,
2908 struct spoolss_Notify
*data
,
2909 print_queue_struct
*queue
,
2910 NT_PRINTER_INFO_LEVEL
*printer
,
2911 TALLOC_CTX
*mem_ctx
)
2913 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
2916 /*******************************************************************
2917 * fill a notify_info_data with pages printed info.
2918 ********************************************************************/
2919 static void spoolss_notify_pages_printed(int snum
,
2920 struct spoolss_Notify
*data
,
2921 print_queue_struct
*queue
,
2922 NT_PRINTER_INFO_LEVEL
*printer
,
2923 TALLOC_CTX
*mem_ctx
)
2925 /* Add code when back-end tracks this */
2926 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
2929 /*******************************************************************
2930 Fill a notify_info_data with job position.
2931 ********************************************************************/
2933 static void spoolss_notify_job_position(int snum
,
2934 struct spoolss_Notify
*data
,
2935 print_queue_struct
*queue
,
2936 NT_PRINTER_INFO_LEVEL
*printer
,
2937 TALLOC_CTX
*mem_ctx
)
2939 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->job
);
2942 /*******************************************************************
2943 Fill a notify_info_data with submitted time.
2944 ********************************************************************/
2946 static void spoolss_notify_submitted_time(int snum
,
2947 struct spoolss_Notify
*data
,
2948 print_queue_struct
*queue
,
2949 NT_PRINTER_INFO_LEVEL
*printer
,
2950 TALLOC_CTX
*mem_ctx
)
2952 data
->data
.string
.string
= NULL
;
2953 data
->data
.string
.size
= 0;
2955 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
2956 &data
->data
.string
.string
,
2957 &data
->data
.string
.size
);
2961 struct s_notify_info_data_table
2963 enum spoolss_NotifyType type
;
2966 enum spoolss_NotifyTable variable_type
;
2967 void (*fn
) (int snum
, struct spoolss_Notify
*data
,
2968 print_queue_struct
*queue
,
2969 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
2972 /* A table describing the various print notification constants and
2973 whether the notification data is a pointer to a variable sized
2974 buffer, a one value uint32_t or a two value uint32_t. */
2976 static const struct s_notify_info_data_table notify_info_data_table
[] =
2978 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
2979 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
2980 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
2981 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
2982 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
2983 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
2984 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
2985 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
2986 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
2987 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
2988 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
2989 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
2990 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
2991 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
2992 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
2993 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
2994 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
2995 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
2996 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
2997 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
2998 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
2999 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3000 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3001 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3002 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3003 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3004 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3005 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3006 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3007 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3008 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3009 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3010 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3011 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3012 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3013 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3014 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3015 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3016 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3017 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3018 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3019 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3020 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3021 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3022 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3023 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3024 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3025 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3026 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3029 /*******************************************************************
3030 Return the variable_type of info_data structure.
3031 ********************************************************************/
3033 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3038 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3039 if ( (notify_info_data_table
[i
].type
== type
) &&
3040 (notify_info_data_table
[i
].field
== field
) ) {
3041 return notify_info_data_table
[i
].variable_type
;
3045 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3050 /****************************************************************************
3051 ****************************************************************************/
3053 static bool search_notify(enum spoolss_NotifyType type
,
3059 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3060 if (notify_info_data_table
[i
].type
== type
&&
3061 notify_info_data_table
[i
].field
== field
&&
3062 notify_info_data_table
[i
].fn
!= NULL
) {
3071 /****************************************************************************
3072 ****************************************************************************/
3074 void construct_info_data(struct spoolss_Notify
*info_data
,
3075 enum spoolss_NotifyType type
,
3079 info_data
->type
= type
;
3080 info_data
->field
.field
= field
;
3081 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3082 info_data
->job_id
= id
;
3085 /*******************************************************************
3087 * fill a notify_info struct with info asked
3089 ********************************************************************/
3091 static bool construct_notify_printer_info(Printer_entry
*print_hnd
,
3092 struct spoolss_NotifyInfo
*info
,
3094 const struct spoolss_NotifyOptionType
*option_type
,
3096 TALLOC_CTX
*mem_ctx
)
3099 enum spoolss_NotifyType type
;
3102 struct spoolss_Notify
*current_data
;
3103 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3104 print_queue_struct
*queue
=NULL
;
3106 type
= option_type
->type
;
3108 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3109 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3110 option_type
->count
, lp_servicename(snum
)));
3112 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3115 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3116 field
= option_type
->fields
[field_num
].field
;
3118 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3120 if (!search_notify(type
, field
, &j
) )
3123 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3124 struct spoolss_Notify
,
3126 if (info
->notifies
== NULL
) {
3127 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3128 free_a_printer(&printer
, 2);
3132 current_data
= &info
->notifies
[info
->count
];
3134 construct_info_data(current_data
, type
, field
, id
);
3136 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3137 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3139 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3145 free_a_printer(&printer
, 2);
3149 /*******************************************************************
3151 * fill a notify_info struct with info asked
3153 ********************************************************************/
3155 static bool construct_notify_jobs_info(print_queue_struct
*queue
,
3156 struct spoolss_NotifyInfo
*info
,
3157 NT_PRINTER_INFO_LEVEL
*printer
,
3159 const struct spoolss_NotifyOptionType
*option_type
,
3161 TALLOC_CTX
*mem_ctx
)
3164 enum spoolss_NotifyType type
;
3166 struct spoolss_Notify
*current_data
;
3168 DEBUG(4,("construct_notify_jobs_info\n"));
3170 type
= option_type
->type
;
3172 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3173 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3174 option_type
->count
));
3176 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3177 field
= option_type
->fields
[field_num
].field
;
3179 if (!search_notify(type
, field
, &j
) )
3182 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3183 struct spoolss_Notify
,
3185 if (info
->notifies
== NULL
) {
3186 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3190 current_data
=&(info
->notifies
[info
->count
]);
3192 construct_info_data(current_data
, type
, field
, id
);
3193 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3202 * JFM: The enumeration is not that simple, it's even non obvious.
3204 * let's take an example: I want to monitor the PRINTER SERVER for
3205 * the printer's name and the number of jobs currently queued.
3206 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3207 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3209 * I have 3 printers on the back of my server.
3211 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3214 * 1 printer 1 name 1
3215 * 2 printer 1 cjob 1
3216 * 3 printer 2 name 2
3217 * 4 printer 2 cjob 2
3218 * 5 printer 3 name 3
3219 * 6 printer 3 name 3
3221 * that's the print server case, the printer case is even worse.
3224 /*******************************************************************
3226 * enumerate all printers on the printserver
3227 * fill a notify_info struct with info asked
3229 ********************************************************************/
3231 static WERROR
printserver_notify_info(pipes_struct
*p
,
3232 struct policy_handle
*hnd
,
3233 struct spoolss_NotifyInfo
*info
,
3234 TALLOC_CTX
*mem_ctx
)
3237 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3238 int n_services
=lp_numservices();
3240 struct spoolss_NotifyOption
*option
;
3241 struct spoolss_NotifyOptionType option_type
;
3243 DEBUG(4,("printserver_notify_info\n"));
3248 option
= Printer
->notify
.option
;
3251 info
->notifies
= NULL
;
3254 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3255 sending a ffpcn() request first */
3260 for (i
=0; i
<option
->count
; i
++) {
3261 option_type
= option
->types
[i
];
3263 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3266 for (snum
=0; snum
<n_services
; snum
++)
3268 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3269 construct_notify_printer_info ( Printer
, info
, snum
, &option_type
, snum
, mem_ctx
);
3275 * Debugging information, don't delete.
3278 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3279 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3280 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3282 for (i
=0; i
<info
->count
; i
++) {
3283 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3284 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3285 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3292 /*******************************************************************
3294 * fill a notify_info struct with info asked
3296 ********************************************************************/
3298 static WERROR
printer_notify_info(pipes_struct
*p
, struct policy_handle
*hnd
,
3299 struct spoolss_NotifyInfo
*info
,
3300 TALLOC_CTX
*mem_ctx
)
3303 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3306 struct spoolss_NotifyOption
*option
;
3307 struct spoolss_NotifyOptionType option_type
;
3309 print_queue_struct
*queue
=NULL
;
3310 print_status_struct status
;
3312 DEBUG(4,("printer_notify_info\n"));
3317 option
= Printer
->notify
.option
;
3321 info
->notifies
= NULL
;
3324 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3325 sending a ffpcn() request first */
3330 get_printer_snum(p
, hnd
, &snum
, NULL
);
3332 for (i
=0; i
<option
->count
; i
++) {
3333 option_type
= option
->types
[i
];
3335 switch (option_type
.type
) {
3336 case PRINTER_NOTIFY_TYPE
:
3337 if(construct_notify_printer_info(Printer
, info
, snum
,
3343 case JOB_NOTIFY_TYPE
: {
3344 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3346 count
= print_queue_status(snum
, &queue
, &status
);
3348 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3351 for (j
=0; j
<count
; j
++) {
3352 construct_notify_jobs_info(&queue
[j
], info
,
3359 free_a_printer(&printer
, 2);
3369 * Debugging information, don't delete.
3372 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3373 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3374 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3376 for (i=0; i<info->count; i++) {
3377 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3378 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3379 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3385 /****************************************************************
3386 _spoolss_RouterRefreshPrinterChangeNotify
3387 ****************************************************************/
3389 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(pipes_struct
*p
,
3390 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3392 struct spoolss_NotifyInfo
*info
;
3394 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3395 WERROR result
= WERR_BADFID
;
3397 /* we always have a spoolss_NotifyInfo struct */
3398 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3400 result
= WERR_NOMEM
;
3404 *r
->out
.info
= info
;
3407 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3408 "Invalid handle (%s:%u:%u).\n",
3409 OUR_HANDLE(r
->in
.handle
)));
3413 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3416 * We are now using the change value, and
3417 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3418 * I don't have a global notification system, I'm sending back all the
3419 * informations even when _NOTHING_ has changed.
3422 /* We need to keep track of the change value to send back in
3423 RRPCN replies otherwise our updates are ignored. */
3425 Printer
->notify
.fnpcn
= true;
3427 if (Printer
->notify
.client_connected
) {
3428 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3429 "Saving change value in request [%x]\n",
3431 Printer
->notify
.change
= r
->in
.change_low
;
3434 /* just ignore the spoolss_NotifyOption */
3436 switch (Printer
->printer_type
) {
3438 result
= printserver_notify_info(p
, r
->in
.handle
,
3442 case SPLHND_PRINTER
:
3443 result
= printer_notify_info(p
, r
->in
.handle
,
3448 Printer
->notify
.fnpcn
= false;
3454 /********************************************************************
3455 * construct_printer_info_0
3456 * fill a printer_info_0 struct
3457 ********************************************************************/
3459 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3460 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3461 struct spoolss_PrinterInfo0
*r
,
3465 counter_printer_0
*session_counter
;
3467 print_status_struct status
;
3469 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3470 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3472 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3473 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3475 count
= print_queue_length(snum
, &status
);
3477 /* check if we already have a counter for this printer */
3478 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3479 if (session_counter
->snum
== snum
)
3483 /* it's the first time, add it to the list */
3484 if (session_counter
== NULL
) {
3485 session_counter
= SMB_MALLOC_P(counter_printer_0
);
3486 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3487 ZERO_STRUCTP(session_counter
);
3488 session_counter
->snum
= snum
;
3489 session_counter
->counter
= 0;
3490 DLIST_ADD(counter_list
, session_counter
);
3494 session_counter
->counter
++;
3500 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3502 init_systemtime(&r
->time
, gmtime(&setuptime
));
3505 * the global_counter should be stored in a TDB as it's common to all the clients
3506 * and should be zeroed on samba startup
3508 r
->global_counter
= session_counter
->counter
;
3510 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3511 SSVAL(&r
->version
, 0, 0x0005); /* NT 5 */
3512 SSVAL(&r
->version
, 2, 0x0893); /* build 2195 */
3513 r
->free_build
= SPOOLSS_RELEASE_BUILD
;
3515 r
->max_spooling
= 0;
3516 r
->session_counter
= session_counter
->counter
;
3517 r
->num_error_out_of_paper
= 0x0;
3518 r
->num_error_not_ready
= 0x0; /* number of print failure */
3520 r
->number_of_processors
= 0x1;
3521 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3522 r
->high_part_total_bytes
= 0x0;
3523 r
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3524 r
->last_error
= WERR_OK
;
3525 r
->status
= nt_printq_status(status
.status
);
3526 r
->enumerate_network_printers
= 0x0;
3527 r
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3528 r
->processor_architecture
= 0x0;
3529 r
->processor_level
= 0x6; /* 6 ???*/
3537 /****************************************************************************
3538 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3539 should be valid upon entry
3540 ****************************************************************************/
3542 static WERROR
convert_nt_devicemode(TALLOC_CTX
*mem_ctx
,
3543 struct spoolss_DeviceMode
*r
,
3544 const NT_DEVICEMODE
*ntdevmode
)
3546 if (!r
|| !ntdevmode
) {
3547 return WERR_INVALID_PARAM
;
3550 r
->devicename
= talloc_strdup(mem_ctx
, ntdevmode
->devicename
);
3551 W_ERROR_HAVE_NO_MEMORY(r
->devicename
);
3553 r
->specversion
= ntdevmode
->specversion
;
3554 r
->driverversion
= ntdevmode
->driverversion
;
3555 r
->size
= ntdevmode
->size
;
3556 r
->__driverextra_length
= ntdevmode
->driverextra
;
3557 r
->fields
= ntdevmode
->fields
;
3559 r
->orientation
= ntdevmode
->orientation
;
3560 r
->papersize
= ntdevmode
->papersize
;
3561 r
->paperlength
= ntdevmode
->paperlength
;
3562 r
->paperwidth
= ntdevmode
->paperwidth
;
3563 r
->scale
= ntdevmode
->scale
;
3564 r
->copies
= ntdevmode
->copies
;
3565 r
->defaultsource
= ntdevmode
->defaultsource
;
3566 r
->printquality
= ntdevmode
->printquality
;
3567 r
->color
= ntdevmode
->color
;
3568 r
->duplex
= ntdevmode
->duplex
;
3569 r
->yresolution
= ntdevmode
->yresolution
;
3570 r
->ttoption
= ntdevmode
->ttoption
;
3571 r
->collate
= ntdevmode
->collate
;
3573 r
->formname
= talloc_strdup(mem_ctx
, ntdevmode
->formname
);
3574 W_ERROR_HAVE_NO_MEMORY(r
->formname
);
3576 r
->logpixels
= ntdevmode
->logpixels
;
3577 r
->bitsperpel
= ntdevmode
->bitsperpel
;
3578 r
->pelswidth
= ntdevmode
->pelswidth
;
3579 r
->pelsheight
= ntdevmode
->pelsheight
;
3580 r
->displayflags
= ntdevmode
->displayflags
;
3581 r
->displayfrequency
= ntdevmode
->displayfrequency
;
3582 r
->icmmethod
= ntdevmode
->icmmethod
;
3583 r
->icmintent
= ntdevmode
->icmintent
;
3584 r
->mediatype
= ntdevmode
->mediatype
;
3585 r
->dithertype
= ntdevmode
->dithertype
;
3586 r
->reserved1
= ntdevmode
->reserved1
;
3587 r
->reserved2
= ntdevmode
->reserved2
;
3588 r
->panningwidth
= ntdevmode
->panningwidth
;
3589 r
->panningheight
= ntdevmode
->panningheight
;
3591 if (ntdevmode
->nt_dev_private
!= NULL
) {
3592 r
->driverextra_data
= data_blob_talloc(mem_ctx
,
3593 ntdevmode
->nt_dev_private
,
3594 ntdevmode
->driverextra
);
3595 W_ERROR_HAVE_NO_MEMORY(r
->driverextra_data
.data
);
3602 /****************************************************************************
3603 Create a spoolss_DeviceMode struct. Returns talloced memory.
3604 ****************************************************************************/
3606 struct spoolss_DeviceMode
*construct_dev_mode(TALLOC_CTX
*mem_ctx
,
3607 const char *servicename
)
3610 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3611 struct spoolss_DeviceMode
*devmode
= NULL
;
3613 DEBUG(7,("construct_dev_mode\n"));
3615 DEBUGADD(8,("getting printer characteristics\n"));
3617 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
3620 if (!printer
->info_2
->devmode
) {
3621 DEBUG(5, ("BONG! There was no device mode!\n"));
3625 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
3627 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3631 DEBUGADD(8,("loading DEVICEMODE\n"));
3633 result
= convert_nt_devicemode(mem_ctx
, devmode
, printer
->info_2
->devmode
);
3634 if (!W_ERROR_IS_OK(result
)) {
3635 TALLOC_FREE(devmode
);
3639 free_a_printer(&printer
,2);
3644 /********************************************************************
3645 * construct_printer_info1
3646 * fill a spoolss_PrinterInfo1 struct
3647 ********************************************************************/
3649 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
3650 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3652 struct spoolss_PrinterInfo1
*r
,
3657 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
3658 ntprinter
->info_2
->printername
,
3659 ntprinter
->info_2
->drivername
,
3660 ntprinter
->info_2
->location
);
3661 W_ERROR_HAVE_NO_MEMORY(r
->description
);
3663 if (*ntprinter
->info_2
->comment
== '\0') {
3664 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3666 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
); /* saved comment */
3668 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3670 r
->name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3671 W_ERROR_HAVE_NO_MEMORY(r
->name
);
3676 /********************************************************************
3677 * construct_printer_info2
3678 * fill a spoolss_PrinterInfo2 struct
3679 ********************************************************************/
3681 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
3682 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3683 struct spoolss_PrinterInfo2
*r
,
3688 print_status_struct status
;
3690 count
= print_queue_length(snum
, &status
);
3692 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3693 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3694 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3695 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3696 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
3697 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
3698 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
3699 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3700 r
->drivername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
3701 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
3703 if (*ntprinter
->info_2
->comment
== '\0') {
3704 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3706 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
);
3708 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3710 r
->location
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->location
);
3711 W_ERROR_HAVE_NO_MEMORY(r
->location
);
3712 r
->sepfile
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->sepfile
);
3713 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
3714 r
->printprocessor
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printprocessor
);
3715 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
3716 r
->datatype
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->datatype
);
3717 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
3718 r
->parameters
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->parameters
);
3719 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
3721 r
->attributes
= ntprinter
->info_2
->attributes
;
3723 r
->priority
= ntprinter
->info_2
->priority
;
3724 r
->defaultpriority
= ntprinter
->info_2
->default_priority
;
3725 r
->starttime
= ntprinter
->info_2
->starttime
;
3726 r
->untiltime
= ntprinter
->info_2
->untiltime
;
3727 r
->status
= nt_printq_status(status
.status
);
3729 r
->averageppm
= ntprinter
->info_2
->averageppm
;
3731 r
->devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
3733 DEBUG(8,("Returning NULL Devicemode!\n"));
3738 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
3739 /* don't use talloc_steal() here unless you do a deep steal of all
3740 the SEC_DESC members */
3742 r
->secdesc
= dup_sec_desc(mem_ctx
, ntprinter
->info_2
->secdesc_buf
->sd
);
3748 /********************************************************************
3749 * construct_printer_info3
3750 * fill a spoolss_PrinterInfo3 struct
3751 ********************************************************************/
3753 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
3754 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3755 struct spoolss_PrinterInfo3
*r
,
3758 /* These are the components of the SD we are returning. */
3760 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
3761 /* don't use talloc_steal() here unless you do a deep steal of all
3762 the SEC_DESC members */
3764 r
->secdesc
= dup_sec_desc(mem_ctx
,
3765 ntprinter
->info_2
->secdesc_buf
->sd
);
3766 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
3772 /********************************************************************
3773 * construct_printer_info4
3774 * fill a spoolss_PrinterInfo4 struct
3775 ********************************************************************/
3777 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
3778 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3779 struct spoolss_PrinterInfo4
*r
,
3782 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3783 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3784 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3785 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3787 r
->attributes
= ntprinter
->info_2
->attributes
;
3792 /********************************************************************
3793 * construct_printer_info5
3794 * fill a spoolss_PrinterInfo5 struct
3795 ********************************************************************/
3797 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
3798 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3799 struct spoolss_PrinterInfo5
*r
,
3802 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3803 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3804 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
3805 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3807 r
->attributes
= ntprinter
->info_2
->attributes
;
3809 /* these two are not used by NT+ according to MSDN */
3811 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
3812 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
3817 /********************************************************************
3818 * construct_printer_info_6
3819 * fill a spoolss_PrinterInfo6 struct
3820 ********************************************************************/
3822 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
3823 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3824 struct spoolss_PrinterInfo6
*r
,
3828 print_status_struct status
;
3830 count
= print_queue_length(snum
, &status
);
3832 r
->status
= nt_printq_status(status
.status
);
3837 /********************************************************************
3838 * construct_printer_info7
3839 * fill a spoolss_PrinterInfo7 struct
3840 ********************************************************************/
3842 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
3843 Printer_entry
*print_hnd
,
3844 struct spoolss_PrinterInfo7
*r
,
3849 if (is_printer_published(print_hnd
, snum
, &guid
)) {
3850 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
3851 r
->action
= DSPRINT_PUBLISH
;
3853 r
->guid
= talloc_strdup(mem_ctx
, "");
3854 r
->action
= DSPRINT_UNPUBLISH
;
3856 W_ERROR_HAVE_NO_MEMORY(r
->guid
);
3861 /********************************************************************
3862 * construct_printer_info8
3863 * fill a spoolss_PrinterInfo8 struct
3864 ********************************************************************/
3866 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
3867 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3868 struct spoolss_DeviceModeInfo
*r
,
3871 r
->devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
3873 DEBUG(8,("Returning NULL Devicemode!\n"));
3880 /********************************************************************
3881 ********************************************************************/
3883 static bool snum_is_shared_printer(int snum
)
3885 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
3888 /********************************************************************
3889 Spoolss_enumprinters.
3890 ********************************************************************/
3892 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
3895 union spoolss_PrinterInfo
**info_p
,
3899 int n_services
= lp_numservices();
3900 union spoolss_PrinterInfo
*info
= NULL
;
3902 WERROR result
= WERR_OK
;
3907 for (snum
= 0; snum
< n_services
; snum
++) {
3909 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3911 if (!snum_is_shared_printer(snum
)) {
3915 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3916 lp_servicename(snum
), snum
));
3918 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
3919 union spoolss_PrinterInfo
,
3922 result
= WERR_NOMEM
;
3926 result
= get_a_printer(NULL
, &ntprinter
, 2,
3927 lp_const_servicename(snum
));
3928 if (!W_ERROR_IS_OK(result
)) {
3934 result
= construct_printer_info0(info
, ntprinter
,
3935 &info
[count
].info0
, snum
);
3938 result
= construct_printer_info1(info
, ntprinter
, flags
,
3939 &info
[count
].info1
, snum
);
3942 result
= construct_printer_info2(info
, ntprinter
,
3943 &info
[count
].info2
, snum
);
3946 result
= construct_printer_info4(info
, ntprinter
,
3947 &info
[count
].info4
, snum
);
3950 result
= construct_printer_info5(info
, ntprinter
,
3951 &info
[count
].info5
, snum
);
3955 result
= WERR_UNKNOWN_LEVEL
;
3956 free_a_printer(&ntprinter
, 2);
3960 free_a_printer(&ntprinter
, 2);
3961 if (!W_ERROR_IS_OK(result
)) {
3972 if (!W_ERROR_IS_OK(result
)) {
3982 /********************************************************************
3983 * handle enumeration of printers at level 0
3984 ********************************************************************/
3986 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
3988 const char *servername
,
3989 union spoolss_PrinterInfo
**info
,
3992 DEBUG(4,("enum_all_printers_info_0\n"));
3994 return enum_all_printers_info_level(mem_ctx
, 0, flags
, info
, count
);
3998 /********************************************************************
3999 ********************************************************************/
4001 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4003 union spoolss_PrinterInfo
**info
,
4006 DEBUG(4,("enum_all_printers_info_1\n"));
4008 return enum_all_printers_info_level(mem_ctx
, 1, flags
, info
, count
);
4011 /********************************************************************
4012 enum_all_printers_info_1_local.
4013 *********************************************************************/
4015 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4016 union spoolss_PrinterInfo
**info
,
4019 DEBUG(4,("enum_all_printers_info_1_local\n"));
4021 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4024 /********************************************************************
4025 enum_all_printers_info_1_name.
4026 *********************************************************************/
4028 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4030 union spoolss_PrinterInfo
**info
,
4033 const char *s
= name
;
4035 DEBUG(4,("enum_all_printers_info_1_name\n"));
4037 if ((name
[0] == '\\') && (name
[1] == '\\')) {
4041 if (!is_myname_or_ipaddr(s
)) {
4042 return WERR_INVALID_NAME
;
4045 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4048 /********************************************************************
4049 enum_all_printers_info_1_network.
4050 *********************************************************************/
4052 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4054 union spoolss_PrinterInfo
**info
,
4057 const char *s
= name
;
4059 DEBUG(4,("enum_all_printers_info_1_network\n"));
4061 /* If we respond to a enum_printers level 1 on our name with flags
4062 set to PRINTER_ENUM_REMOTE with a list of printers then these
4063 printers incorrectly appear in the APW browse list.
4064 Specifically the printers for the server appear at the workgroup
4065 level where all the other servers in the domain are
4066 listed. Windows responds to this call with a
4067 WERR_CAN_NOT_COMPLETE so we should do the same. */
4069 if (name
[0] == '\\' && name
[1] == '\\') {
4073 if (is_myname_or_ipaddr(s
)) {
4074 return WERR_CAN_NOT_COMPLETE
;
4077 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_NAME
, info
, count
);
4080 /********************************************************************
4081 * api_spoolss_enumprinters
4083 * called from api_spoolss_enumprinters (see this to understand)
4084 ********************************************************************/
4086 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4087 union spoolss_PrinterInfo
**info
,
4090 DEBUG(4,("enum_all_printers_info_2\n"));
4092 return enum_all_printers_info_level(mem_ctx
, 2, 0, info
, count
);
4095 /********************************************************************
4096 * handle enumeration of printers at level 1
4097 ********************************************************************/
4099 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4102 union spoolss_PrinterInfo
**info
,
4105 /* Not all the flags are equals */
4107 if (flags
& PRINTER_ENUM_LOCAL
) {
4108 return enum_all_printers_info_1_local(mem_ctx
, info
, count
);
4111 if (flags
& PRINTER_ENUM_NAME
) {
4112 return enum_all_printers_info_1_name(mem_ctx
, name
, info
, count
);
4115 if (flags
& PRINTER_ENUM_NETWORK
) {
4116 return enum_all_printers_info_1_network(mem_ctx
, name
, info
, count
);
4119 return WERR_OK
; /* NT4sp5 does that */
4122 /********************************************************************
4123 * handle enumeration of printers at level 2
4124 ********************************************************************/
4126 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4128 const char *servername
,
4129 union spoolss_PrinterInfo
**info
,
4132 if (flags
& PRINTER_ENUM_LOCAL
) {
4133 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4136 if (flags
& PRINTER_ENUM_NAME
) {
4137 if (!is_myname_or_ipaddr(canon_servername(servername
))) {
4138 return WERR_INVALID_NAME
;
4141 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4144 if (flags
& PRINTER_ENUM_REMOTE
) {
4145 return WERR_UNKNOWN_LEVEL
;
4151 /********************************************************************
4152 * handle enumeration of printers at level 4
4153 ********************************************************************/
4155 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4157 const char *servername
,
4158 union spoolss_PrinterInfo
**info
,
4161 DEBUG(4,("enum_all_printers_info_4\n"));
4163 return enum_all_printers_info_level(mem_ctx
, 4, flags
, info
, count
);
4167 /********************************************************************
4168 * handle enumeration of printers at level 5
4169 ********************************************************************/
4171 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4173 const char *servername
,
4174 union spoolss_PrinterInfo
**info
,
4177 DEBUG(4,("enum_all_printers_info_5\n"));
4179 return enum_all_printers_info_level(mem_ctx
, 5, flags
, info
, count
);
4182 /****************************************************************
4183 _spoolss_EnumPrinters
4184 ****************************************************************/
4186 WERROR
_spoolss_EnumPrinters(pipes_struct
*p
,
4187 struct spoolss_EnumPrinters
*r
)
4189 const char *name
= NULL
;
4192 /* that's an [in out] buffer */
4194 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4195 return WERR_INVALID_PARAM
;
4198 DEBUG(4,("_spoolss_EnumPrinters\n"));
4202 *r
->out
.info
= NULL
;
4206 * flags==PRINTER_ENUM_NAME
4207 * if name=="" then enumerates all printers
4208 * if name!="" then enumerate the printer
4209 * flags==PRINTER_ENUM_REMOTE
4210 * name is NULL, enumerate printers
4211 * Level 2: name!="" enumerates printers, name can't be NULL
4212 * Level 3: doesn't exist
4213 * Level 4: does a local registry lookup
4214 * Level 5: same as Level 2
4218 name
= talloc_strdup_upper(p
->mem_ctx
, r
->in
.server
);
4219 W_ERROR_HAVE_NO_MEMORY(name
);
4222 switch (r
->in
.level
) {
4224 result
= enumprinters_level0(p
->mem_ctx
, r
->in
.flags
, name
,
4225 r
->out
.info
, r
->out
.count
);
4228 result
= enumprinters_level1(p
->mem_ctx
, r
->in
.flags
, name
,
4229 r
->out
.info
, r
->out
.count
);
4232 result
= enumprinters_level2(p
->mem_ctx
, r
->in
.flags
, name
,
4233 r
->out
.info
, r
->out
.count
);
4236 result
= enumprinters_level4(p
->mem_ctx
, r
->in
.flags
, name
,
4237 r
->out
.info
, r
->out
.count
);
4240 result
= enumprinters_level5(p
->mem_ctx
, r
->in
.flags
, name
,
4241 r
->out
.info
, r
->out
.count
);
4244 return WERR_UNKNOWN_LEVEL
;
4247 if (!W_ERROR_IS_OK(result
)) {
4251 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4252 spoolss_EnumPrinters
,
4253 *r
->out
.info
, r
->in
.level
,
4255 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4256 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4258 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4261 /****************************************************************
4263 ****************************************************************/
4265 WERROR
_spoolss_GetPrinter(pipes_struct
*p
,
4266 struct spoolss_GetPrinter
*r
)
4268 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4269 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4270 WERROR result
= WERR_OK
;
4274 /* that's an [in out] buffer */
4276 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4277 return WERR_INVALID_PARAM
;
4282 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4286 result
= get_a_printer(Printer
, &ntprinter
, 2,
4287 lp_const_servicename(snum
));
4288 if (!W_ERROR_IS_OK(result
)) {
4292 switch (r
->in
.level
) {
4294 result
= construct_printer_info0(p
->mem_ctx
, ntprinter
,
4295 &r
->out
.info
->info0
, snum
);
4298 result
= construct_printer_info1(p
->mem_ctx
, ntprinter
,
4300 &r
->out
.info
->info1
, snum
);
4303 result
= construct_printer_info2(p
->mem_ctx
, ntprinter
,
4304 &r
->out
.info
->info2
, snum
);
4307 result
= construct_printer_info3(p
->mem_ctx
, ntprinter
,
4308 &r
->out
.info
->info3
, snum
);
4311 result
= construct_printer_info4(p
->mem_ctx
, ntprinter
,
4312 &r
->out
.info
->info4
, snum
);
4315 result
= construct_printer_info5(p
->mem_ctx
, ntprinter
,
4316 &r
->out
.info
->info5
, snum
);
4319 result
= construct_printer_info6(p
->mem_ctx
, ntprinter
,
4320 &r
->out
.info
->info6
, snum
);
4323 result
= construct_printer_info7(p
->mem_ctx
, Printer
,
4324 &r
->out
.info
->info7
, snum
);
4327 result
= construct_printer_info8(p
->mem_ctx
, ntprinter
,
4328 &r
->out
.info
->info8
, snum
);
4331 result
= WERR_UNKNOWN_LEVEL
;
4335 free_a_printer(&ntprinter
, 2);
4337 if (!W_ERROR_IS_OK(result
)) {
4338 TALLOC_FREE(r
->out
.info
);
4342 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
,
4343 r
->out
.info
, r
->in
.level
);
4344 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4346 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4349 /********************************************************************
4350 ********************************************************************/
4352 static const char **string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4353 const char **string_array
,
4354 const char *cservername
)
4356 int i
, num_strings
= 0;
4357 const char **array
= NULL
;
4359 if (!string_array
) {
4363 for (i
=0; string_array
[i
] && string_array
[i
][0] != '\0'; i
++) {
4365 const char *str
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4366 cservername
, string_array
[i
]);
4373 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4380 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4381 &array
, &num_strings
);
4387 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4389 if (in && strlen(in)) { \
4390 out = talloc_strdup(mem_ctx, in); \
4391 W_ERROR_HAVE_NO_MEMORY(out); \
4397 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4399 if (in && strlen(in)) { \
4400 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4402 out = talloc_strdup(mem_ctx, ""); \
4404 W_ERROR_HAVE_NO_MEMORY(out); \
4407 /********************************************************************
4408 * fill a spoolss_DriverInfo1 struct
4409 ********************************************************************/
4411 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4412 struct spoolss_DriverInfo1
*r
,
4413 const struct spoolss_DriverInfo8
*driver
,
4414 const char *servername
)
4416 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4417 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4422 /********************************************************************
4423 * fill a spoolss_DriverInfo2 struct
4424 ********************************************************************/
4426 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4427 struct spoolss_DriverInfo2
*r
,
4428 const struct spoolss_DriverInfo8
*driver
,
4429 const char *servername
)
4432 const char *cservername
= canon_servername(servername
);
4434 r
->version
= driver
->version
;
4436 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4437 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4438 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4439 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4441 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4442 driver
->driver_path
,
4445 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4449 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4450 driver
->config_file
,
4456 /********************************************************************
4457 * fill a spoolss_DriverInfo3 struct
4458 ********************************************************************/
4460 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4461 struct spoolss_DriverInfo3
*r
,
4462 const struct spoolss_DriverInfo8
*driver
,
4463 const char *servername
)
4465 const char *cservername
= canon_servername(servername
);
4467 r
->version
= driver
->version
;
4469 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4470 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4471 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4472 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4474 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4475 driver
->driver_path
,
4478 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4482 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4483 driver
->config_file
,
4486 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4490 FILL_DRIVER_STRING(mem_ctx
,
4491 driver
->monitor_name
,
4494 FILL_DRIVER_STRING(mem_ctx
,
4495 driver
->default_datatype
,
4496 r
->default_datatype
);
4498 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4499 driver
->dependent_files
,
4504 /********************************************************************
4505 * fill a spoolss_DriverInfo4 struct
4506 ********************************************************************/
4508 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
4509 struct spoolss_DriverInfo4
*r
,
4510 const struct spoolss_DriverInfo8
*driver
,
4511 const char *servername
)
4513 const char *cservername
= canon_servername(servername
);
4515 r
->version
= driver
->version
;
4517 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4518 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4519 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4520 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4522 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4523 driver
->driver_path
,
4526 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4530 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4531 driver
->config_file
,
4534 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4538 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4539 driver
->dependent_files
,
4542 FILL_DRIVER_STRING(mem_ctx
,
4543 driver
->monitor_name
,
4546 FILL_DRIVER_STRING(mem_ctx
,
4547 driver
->default_datatype
,
4548 r
->default_datatype
);
4550 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4551 driver
->previous_names
,
4557 /********************************************************************
4558 * fill a spoolss_DriverInfo5 struct
4559 ********************************************************************/
4561 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
4562 struct spoolss_DriverInfo5
*r
,
4563 const struct spoolss_DriverInfo8
*driver
,
4564 const char *servername
)
4566 const char *cservername
= canon_servername(servername
);
4568 r
->version
= driver
->version
;
4570 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4571 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4572 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4573 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4575 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4576 driver
->driver_path
,
4579 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4583 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4584 driver
->config_file
,
4587 r
->driver_attributes
= 0;
4588 r
->config_version
= 0;
4589 r
->driver_version
= 0;
4593 /********************************************************************
4594 * fill a spoolss_DriverInfo6 struct
4595 ********************************************************************/
4597 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
4598 struct spoolss_DriverInfo6
*r
,
4599 const struct spoolss_DriverInfo8
*driver
,
4600 const char *servername
)
4602 const char *cservername
= canon_servername(servername
);
4604 r
->version
= driver
->version
;
4606 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4607 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4608 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4609 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4611 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4612 driver
->driver_path
,
4615 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4619 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4620 driver
->config_file
,
4623 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4627 FILL_DRIVER_STRING(mem_ctx
,
4628 driver
->monitor_name
,
4631 FILL_DRIVER_STRING(mem_ctx
,
4632 driver
->default_datatype
,
4633 r
->default_datatype
);
4635 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4636 driver
->dependent_files
,
4638 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4639 driver
->previous_names
,
4642 r
->driver_date
= driver
->driver_date
;
4643 r
->driver_version
= driver
->driver_version
;
4645 FILL_DRIVER_STRING(mem_ctx
,
4646 driver
->manufacturer_name
,
4647 r
->manufacturer_name
);
4648 FILL_DRIVER_STRING(mem_ctx
,
4649 driver
->manufacturer_url
,
4650 r
->manufacturer_url
);
4651 FILL_DRIVER_STRING(mem_ctx
,
4652 driver
->hardware_id
,
4654 FILL_DRIVER_STRING(mem_ctx
,
4661 /********************************************************************
4662 * fill a spoolss_DriverInfo8 struct
4663 ********************************************************************/
4665 static WERROR
fill_printer_driver_info8(TALLOC_CTX
*mem_ctx
,
4666 struct spoolss_DriverInfo8
*r
,
4667 const struct spoolss_DriverInfo8
*driver
,
4668 const char *servername
)
4670 const char *cservername
= canon_servername(servername
);
4672 r
->version
= driver
->version
;
4674 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4675 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4676 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4677 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4679 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4680 driver
->driver_path
,
4683 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4687 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4688 driver
->config_file
,
4691 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4695 FILL_DRIVER_STRING(mem_ctx
,
4696 driver
->monitor_name
,
4699 FILL_DRIVER_STRING(mem_ctx
,
4700 driver
->default_datatype
,
4701 r
->default_datatype
);
4703 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4704 driver
->dependent_files
,
4706 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4707 driver
->previous_names
,
4710 r
->driver_date
= driver
->driver_date
;
4711 r
->driver_version
= driver
->driver_version
;
4713 FILL_DRIVER_STRING(mem_ctx
,
4714 driver
->manufacturer_name
,
4715 r
->manufacturer_name
);
4716 FILL_DRIVER_STRING(mem_ctx
,
4717 driver
->manufacturer_url
,
4718 r
->manufacturer_url
);
4719 FILL_DRIVER_STRING(mem_ctx
,
4720 driver
->hardware_id
,
4722 FILL_DRIVER_STRING(mem_ctx
,
4726 FILL_DRIVER_STRING(mem_ctx
,
4727 driver
->print_processor
,
4728 r
->print_processor
);
4729 FILL_DRIVER_STRING(mem_ctx
,
4730 driver
->vendor_setup
,
4733 r
->color_profiles
= string_array_from_driver_info(mem_ctx
,
4734 driver
->color_profiles
,
4737 FILL_DRIVER_STRING(mem_ctx
,
4741 r
->printer_driver_attributes
= driver
->printer_driver_attributes
;
4743 r
->core_driver_dependencies
= string_array_from_driver_info(mem_ctx
,
4744 driver
->core_driver_dependencies
,
4747 r
->min_inbox_driver_ver_date
= driver
->min_inbox_driver_ver_date
;
4748 r
->min_inbox_driver_ver_version
= driver
->min_inbox_driver_ver_version
;
4753 #if 0 /* disabled until marshalling issues are resolved - gd */
4754 /********************************************************************
4755 ********************************************************************/
4757 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
4758 struct spoolss_DriverFileInfo
*r
,
4759 const char *cservername
,
4760 const char *file_name
,
4761 enum spoolss_DriverFileType file_type
,
4762 uint32_t file_version
)
4764 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4765 cservername
, file_name
);
4766 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
4767 r
->file_type
= file_type
;
4768 r
->file_version
= file_version
;
4773 /********************************************************************
4774 ********************************************************************/
4776 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
4777 const struct spoolss_DriverInfo8
*driver
,
4778 const char *cservername
,
4779 struct spoolss_DriverFileInfo
**info_p
,
4782 struct spoolss_DriverFileInfo
*info
= NULL
;
4790 if (strlen(driver
->driver_path
)) {
4791 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4792 struct spoolss_DriverFileInfo
,
4794 W_ERROR_HAVE_NO_MEMORY(info
);
4795 result
= fill_spoolss_DriverFileInfo(info
,
4798 driver
->driver_path
,
4799 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
4801 W_ERROR_NOT_OK_RETURN(result
);
4805 if (strlen(driver
->config_file
)) {
4806 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4807 struct spoolss_DriverFileInfo
,
4809 W_ERROR_HAVE_NO_MEMORY(info
);
4810 result
= fill_spoolss_DriverFileInfo(info
,
4813 driver
->config_file
,
4814 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
4816 W_ERROR_NOT_OK_RETURN(result
);
4820 if (strlen(driver
->data_file
)) {
4821 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4822 struct spoolss_DriverFileInfo
,
4824 W_ERROR_HAVE_NO_MEMORY(info
);
4825 result
= fill_spoolss_DriverFileInfo(info
,
4829 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
4831 W_ERROR_NOT_OK_RETURN(result
);
4835 if (strlen(driver
->help_file
)) {
4836 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4837 struct spoolss_DriverFileInfo
,
4839 W_ERROR_HAVE_NO_MEMORY(info
);
4840 result
= fill_spoolss_DriverFileInfo(info
,
4844 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
4846 W_ERROR_NOT_OK_RETURN(result
);
4850 for (i
=0; driver
->dependent_files
[i
] && driver
->dependent_files
[i
][0] != '\0'; i
++) {
4851 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4852 struct spoolss_DriverFileInfo
,
4854 W_ERROR_HAVE_NO_MEMORY(info
);
4855 result
= fill_spoolss_DriverFileInfo(info
,
4858 driver
->dependent_files
[i
],
4859 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
4861 W_ERROR_NOT_OK_RETURN(result
);
4871 /********************************************************************
4872 * fill a spoolss_DriverInfo101 struct
4873 ********************************************************************/
4875 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
4876 struct spoolss_DriverInfo101
*r
,
4877 const struct spoolss_DriverInfo8
*driver
,
4878 const char *servername
)
4880 const char *cservername
= canon_servername(servername
);
4883 r
->version
= driver
->version
;
4885 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4886 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4887 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4888 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4890 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
4894 if (!W_ERROR_IS_OK(result
)) {
4898 FILL_DRIVER_STRING(mem_ctx
,
4899 driver
->monitor_name
,
4902 FILL_DRIVER_STRING(mem_ctx
,
4903 driver
->default_datatype
,
4904 r
->default_datatype
);
4906 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4907 driver
->previous_names
,
4909 r
->driver_date
= driver
->driver_date
;
4910 r
->driver_version
= driver
->driver_version
;
4912 FILL_DRIVER_STRING(mem_ctx
,
4913 driver
->manufacturer_name
,
4914 r
->manufacturer_name
);
4915 FILL_DRIVER_STRING(mem_ctx
,
4916 driver
->manufacturer_url
,
4917 r
->manufacturer_url
);
4918 FILL_DRIVER_STRING(mem_ctx
,
4919 driver
->hardware_id
,
4921 FILL_DRIVER_STRING(mem_ctx
,
4928 /********************************************************************
4929 ********************************************************************/
4931 static WERROR
construct_printer_driver_info_level(TALLOC_CTX
*mem_ctx
,
4933 union spoolss_DriverInfo
*r
,
4935 const char *servername
,
4936 const char *architecture
,
4939 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4940 struct spoolss_DriverInfo8
*driver
;
4943 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
4945 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4946 win_errstr(result
)));
4948 if (!W_ERROR_IS_OK(result
)) {
4949 return WERR_INVALID_PRINTER_NAME
;
4952 result
= get_a_printer_driver(mem_ctx
, &driver
, printer
->info_2
->drivername
,
4953 architecture
, version
);
4955 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4956 win_errstr(result
)));
4958 if (!W_ERROR_IS_OK(result
)) {
4960 * Is this a W2k client ?
4964 free_a_printer(&printer
, 2);
4965 return WERR_UNKNOWN_PRINTER_DRIVER
;
4968 /* Yes - try again with a WinNT driver. */
4970 result
= get_a_printer_driver(mem_ctx
, &driver
, printer
->info_2
->drivername
,
4971 architecture
, version
);
4972 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4973 win_errstr(result
)));
4974 if (!W_ERROR_IS_OK(result
)) {
4975 free_a_printer(&printer
, 2);
4976 return WERR_UNKNOWN_PRINTER_DRIVER
;
4982 result
= fill_printer_driver_info1(mem_ctx
, &r
->info1
, driver
, servername
);
4985 result
= fill_printer_driver_info2(mem_ctx
, &r
->info2
, driver
, servername
);
4988 result
= fill_printer_driver_info3(mem_ctx
, &r
->info3
, driver
, servername
);
4991 result
= fill_printer_driver_info4(mem_ctx
, &r
->info4
, driver
, servername
);
4994 result
= fill_printer_driver_info5(mem_ctx
, &r
->info5
, driver
, servername
);
4997 result
= fill_printer_driver_info6(mem_ctx
, &r
->info6
, driver
, servername
);
5000 result
= fill_printer_driver_info8(mem_ctx
, &r
->info8
, driver
, servername
);
5002 #if 0 /* disabled until marshalling issues are resolved - gd */
5004 result
= fill_printer_driver_info101(mem_ctx
, &r
->info101
, driver
, servername
);
5008 result
= WERR_UNKNOWN_LEVEL
;
5012 free_a_printer(&printer
, 2);
5013 free_a_printer_driver(driver
);
5018 /****************************************************************
5019 _spoolss_GetPrinterDriver2
5020 ****************************************************************/
5022 WERROR
_spoolss_GetPrinterDriver2(pipes_struct
*p
,
5023 struct spoolss_GetPrinterDriver2
*r
)
5025 Printer_entry
*printer
;
5028 const char *servername
;
5031 /* that's an [in out] buffer */
5033 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5034 return WERR_INVALID_PARAM
;
5037 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5039 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5040 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5041 return WERR_INVALID_PRINTER_NAME
;
5045 *r
->out
.server_major_version
= 0;
5046 *r
->out
.server_minor_version
= 0;
5048 servername
= get_server_name(printer
);
5050 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5054 result
= construct_printer_driver_info_level(p
->mem_ctx
, r
->in
.level
,
5058 r
->in
.client_major_version
);
5059 if (!W_ERROR_IS_OK(result
)) {
5060 TALLOC_FREE(r
->out
.info
);
5064 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
,
5065 r
->out
.info
, r
->in
.level
);
5066 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5068 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5072 /****************************************************************
5073 _spoolss_StartPagePrinter
5074 ****************************************************************/
5076 WERROR
_spoolss_StartPagePrinter(pipes_struct
*p
,
5077 struct spoolss_StartPagePrinter
*r
)
5079 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5082 DEBUG(3,("_spoolss_StartPagePrinter: "
5083 "Error in startpageprinter printer handle\n"));
5087 Printer
->page_started
= true;
5091 /****************************************************************
5092 _spoolss_EndPagePrinter
5093 ****************************************************************/
5095 WERROR
_spoolss_EndPagePrinter(pipes_struct
*p
,
5096 struct spoolss_EndPagePrinter
*r
)
5100 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5103 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5104 OUR_HANDLE(r
->in
.handle
)));
5108 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5111 Printer
->page_started
= false;
5112 print_job_endpage(snum
, Printer
->jobid
);
5117 /****************************************************************
5118 _spoolss_StartDocPrinter
5119 ****************************************************************/
5121 WERROR
_spoolss_StartDocPrinter(pipes_struct
*p
,
5122 struct spoolss_StartDocPrinter
*r
)
5124 struct spoolss_DocumentInfo1
*info_1
;
5126 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5129 DEBUG(2,("_spoolss_StartDocPrinter: "
5130 "Invalid handle (%s:%u:%u)\n",
5131 OUR_HANDLE(r
->in
.handle
)));
5135 if (r
->in
.level
!= 1) {
5136 return WERR_UNKNOWN_LEVEL
;
5139 info_1
= r
->in
.info
.info1
;
5142 * a nice thing with NT is it doesn't listen to what you tell it.
5143 * when asked to send _only_ RAW datas, it tries to send datas
5146 * So I add checks like in NT Server ...
5149 if (info_1
->datatype
) {
5150 if (strcmp(info_1
->datatype
, "RAW") != 0) {
5152 return WERR_INVALID_DATATYPE
;
5156 /* get the share number of the printer */
5157 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5161 Printer
->jobid
= print_job_start(p
->server_info
, snum
,
5162 info_1
->document_name
,
5163 Printer
->nt_devmode
);
5165 /* An error occured in print_job_start() so return an appropriate
5168 if (Printer
->jobid
== -1) {
5169 return map_werror_from_unix(errno
);
5172 Printer
->document_started
= true;
5173 *r
->out
.job_id
= Printer
->jobid
;
5178 /****************************************************************
5179 _spoolss_EndDocPrinter
5180 ****************************************************************/
5182 WERROR
_spoolss_EndDocPrinter(pipes_struct
*p
,
5183 struct spoolss_EndDocPrinter
*r
)
5185 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5189 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5190 OUR_HANDLE(r
->in
.handle
)));
5194 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5198 Printer
->document_started
= false;
5199 print_job_end(snum
, Printer
->jobid
, NORMAL_CLOSE
);
5200 /* error codes unhandled so far ... */
5205 /****************************************************************
5206 _spoolss_WritePrinter
5207 ****************************************************************/
5209 WERROR
_spoolss_WritePrinter(pipes_struct
*p
,
5210 struct spoolss_WritePrinter
*r
)
5212 ssize_t buffer_written
;
5214 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5217 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5218 OUR_HANDLE(r
->in
.handle
)));
5219 *r
->out
.num_written
= r
->in
._data_size
;
5223 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5226 buffer_written
= print_job_write(snum
, Printer
->jobid
,
5227 (const char *)r
->in
.data
.data
,
5229 (size_t)r
->in
._data_size
);
5230 if (buffer_written
== (ssize_t
)-1) {
5231 *r
->out
.num_written
= 0;
5232 if (errno
== ENOSPC
)
5233 return WERR_NO_SPOOL_SPACE
;
5235 return WERR_ACCESS_DENIED
;
5238 *r
->out
.num_written
= r
->in
._data_size
;
5243 /********************************************************************
5244 * api_spoolss_getprinter
5245 * called from the spoolss dispatcher
5247 ********************************************************************/
5249 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5253 WERROR errcode
= WERR_BADFUNC
;
5254 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5257 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5258 OUR_HANDLE(handle
)));
5262 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5266 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5267 errcode
= print_queue_pause(p
->server_info
, snum
);
5269 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5270 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5271 errcode
= print_queue_resume(p
->server_info
, snum
);
5273 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5274 errcode
= print_queue_purge(p
->server_info
, snum
);
5277 return WERR_UNKNOWN_LEVEL
;
5284 /****************************************************************
5285 _spoolss_AbortPrinter
5286 * From MSDN: "Deletes printer's spool file if printer is configured
5288 ****************************************************************/
5290 WERROR
_spoolss_AbortPrinter(pipes_struct
*p
,
5291 struct spoolss_AbortPrinter
*r
)
5293 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5295 WERROR errcode
= WERR_OK
;
5298 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5299 OUR_HANDLE(r
->in
.handle
)));
5303 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5306 print_job_delete(p
->server_info
, snum
, Printer
->jobid
, &errcode
);
5311 /********************************************************************
5312 * called by spoolss_api_setprinter
5313 * when updating a printer description
5314 ********************************************************************/
5316 static WERROR
update_printer_sec(struct policy_handle
*handle
,
5317 pipes_struct
*p
, struct sec_desc_buf
*secdesc_ctr
)
5319 struct sec_desc_buf
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5323 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5325 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5326 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5327 OUR_HANDLE(handle
)));
5329 result
= WERR_BADFID
;
5334 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5335 result
= WERR_INVALID_PARAM
;
5339 /* Check the user has permissions to change the security
5340 descriptor. By experimentation with two NT machines, the user
5341 requires Full Access to the printer to change security
5344 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5345 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5346 result
= WERR_ACCESS_DENIED
;
5350 /* NT seems to like setting the security descriptor even though
5351 nothing may have actually changed. */
5353 if ( !nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
)) {
5354 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5355 result
= WERR_BADFID
;
5359 if (DEBUGLEVEL
>= 10) {
5360 struct security_acl
*the_acl
;
5363 the_acl
= old_secdesc_ctr
->sd
->dacl
;
5364 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5365 PRINTERNAME(snum
), the_acl
->num_aces
));
5367 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5368 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5369 &the_acl
->aces
[i
].trustee
),
5370 the_acl
->aces
[i
].access_mask
));
5373 the_acl
= secdesc_ctr
->sd
->dacl
;
5376 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5377 PRINTERNAME(snum
), the_acl
->num_aces
));
5379 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5380 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5381 &the_acl
->aces
[i
].trustee
),
5382 the_acl
->aces
[i
].access_mask
));
5385 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5389 new_secdesc_ctr
= sec_desc_merge_buf(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5390 if (!new_secdesc_ctr
) {
5391 result
= WERR_NOMEM
;
5395 if (security_descriptor_equal(new_secdesc_ctr
->sd
, old_secdesc_ctr
->sd
)) {
5400 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5407 /********************************************************************
5408 Canonicalize printer info from a client
5410 ATTN: It does not matter what we set the servername to hear
5411 since we do the necessary work in get_a_printer() to set it to
5412 the correct value based on what the client sent in the
5413 _spoolss_open_printer_ex().
5414 ********************************************************************/
5416 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5418 fstring printername
;
5421 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5422 "portname=%s drivername=%s comment=%s location=%s\n",
5423 info
->servername
, info
->printername
, info
->sharename
,
5424 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5426 /* we force some elements to "correct" values */
5427 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5428 fstrcpy(info
->sharename
, lp_servicename(snum
));
5430 /* check to see if we allow printername != sharename */
5432 if ( lp_force_printername(snum
) ) {
5433 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5434 global_myname(), info
->sharename
);
5437 /* make sure printername is in \\server\printername format */
5439 fstrcpy( printername
, info
->printername
);
5441 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5442 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5446 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5447 global_myname(), p
);
5450 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5451 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5458 /****************************************************************************
5459 ****************************************************************************/
5461 static WERROR
add_port_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
5463 char *cmd
= lp_addport_cmd();
5464 char *command
= NULL
;
5466 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5467 bool is_print_op
= false;
5470 return WERR_ACCESS_DENIED
;
5473 command
= talloc_asprintf(ctx
,
5474 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
5480 is_print_op
= user_has_privileges( token
, &se_printop
);
5482 DEBUG(10,("Running [%s]\n", command
));
5484 /********* BEGIN SePrintOperatorPrivilege **********/
5489 ret
= smbrun(command
, NULL
);
5494 /********* END SePrintOperatorPrivilege **********/
5496 DEBUGADD(10,("returned [%d]\n", ret
));
5498 TALLOC_FREE(command
);
5501 return WERR_ACCESS_DENIED
;
5507 /****************************************************************************
5508 ****************************************************************************/
5510 bool add_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
5512 char *cmd
= lp_addprinter_cmd();
5514 char *command
= NULL
;
5518 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5519 bool is_print_op
= false;
5520 char *remote_machine
= talloc_strdup(ctx
, "%m");
5522 if (!remote_machine
) {
5525 remote_machine
= talloc_sub_basic(ctx
,
5526 current_user_info
.smb_name
,
5527 current_user_info
.domain
,
5529 if (!remote_machine
) {
5533 command
= talloc_asprintf(ctx
,
5534 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5535 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5536 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5537 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5543 is_print_op
= user_has_privileges( token
, &se_printop
);
5545 DEBUG(10,("Running [%s]\n", command
));
5547 /********* BEGIN SePrintOperatorPrivilege **********/
5552 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
5553 /* Tell everyone we updated smb.conf. */
5554 message_send_all(smbd_messaging_context(),
5555 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
5561 /********* END SePrintOperatorPrivilege **********/
5563 DEBUGADD(10,("returned [%d]\n", ret
));
5565 TALLOC_FREE(command
);
5566 TALLOC_FREE(remote_machine
);
5574 /* reload our services immediately */
5576 reload_services(false);
5580 /* Get lines and convert them back to dos-codepage */
5581 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
5582 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5585 /* Set the portname to what the script says the portname should be. */
5586 /* but don't require anything to be return from the script exit a good error code */
5589 /* Set the portname to what the script says the portname should be. */
5590 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5591 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5594 TALLOC_FREE(qlines
);
5599 /********************************************************************
5600 * Called by spoolss_api_setprinter
5601 * when updating a printer description.
5602 ********************************************************************/
5604 static WERROR
update_printer(pipes_struct
*p
, struct policy_handle
*handle
,
5605 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
5606 struct spoolss_DeviceMode
*devmode
)
5609 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5610 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5615 DEBUG(8,("update_printer\n"));
5620 result
= WERR_BADFID
;
5624 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
5625 result
= WERR_BADFID
;
5629 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
5630 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
5631 result
= WERR_BADFID
;
5635 DEBUGADD(8,("Converting info_2 struct\n"));
5638 * convert_printer_info converts the incoming
5639 * info from the client and overwrites the info
5640 * just read from the tdb in the pointer 'printer'.
5643 if (!convert_printer_info(info_ctr
, printer
)) {
5644 result
= WERR_NOMEM
;
5649 /* we have a valid devmode
5650 convert it and link it*/
5652 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5653 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5654 &printer
->info_2
->devmode
)) {
5655 result
= WERR_NOMEM
;
5660 /* Do sanity check on the requested changes for Samba */
5662 if (!check_printer_ok(printer
->info_2
, snum
)) {
5663 result
= WERR_INVALID_PARAM
;
5667 /* FIXME!!! If the driver has changed we really should verify that
5668 it is installed before doing much else --jerry */
5670 /* Check calling user has permission to update printer description */
5672 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5673 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5674 result
= WERR_ACCESS_DENIED
;
5678 /* Call addprinter hook */
5679 /* Check changes to see if this is really needed */
5681 if ( *lp_addprinter_cmd()
5682 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
5683 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
5684 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
5685 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
5687 /* add_printer_hook() will call reload_services() */
5689 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
5691 result
= WERR_ACCESS_DENIED
;
5697 * When a *new* driver is bound to a printer, the drivername is used to
5698 * lookup previously saved driver initialization info, which is then
5699 * bound to the printer, simulating what happens in the Windows arch.
5701 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
5703 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5704 printer
->info_2
->drivername
));
5706 notify_printer_driver(snum
, printer
->info_2
->drivername
);
5710 * flag which changes actually occured. This is a small subset of
5711 * all the possible changes. We also have to update things in the
5715 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
5716 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->comment
);
5717 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
5718 REG_SZ
, buffer
.data
, buffer
.length
);
5720 notify_printer_comment(snum
, printer
->info_2
->comment
);
5723 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
5724 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->sharename
);
5725 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
5726 REG_SZ
, buffer
.data
, buffer
.length
);
5728 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
5731 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
5734 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
5737 pname
= printer
->info_2
->printername
;
5740 push_reg_sz(talloc_tos(), &buffer
, pname
);
5741 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
5742 REG_SZ
, buffer
.data
, buffer
.length
);
5744 notify_printer_printername( snum
, pname
);
5747 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
5748 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->portname
);
5749 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
5750 REG_SZ
, buffer
.data
, buffer
.length
);
5752 notify_printer_port(snum
, printer
->info_2
->portname
);
5755 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
5756 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->location
);
5757 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
5758 REG_SZ
, buffer
.data
, buffer
.length
);
5760 notify_printer_location(snum
, printer
->info_2
->location
);
5763 /* here we need to update some more DsSpooler keys */
5764 /* uNCName, serverName, shortServerName */
5766 push_reg_sz(talloc_tos(), &buffer
, global_myname());
5767 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
5768 REG_SZ
, buffer
.data
, buffer
.length
);
5769 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
5770 REG_SZ
, buffer
.data
, buffer
.length
);
5772 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
5773 global_myname(), printer
->info_2
->sharename
);
5774 push_reg_sz(talloc_tos(), &buffer
, asc_buffer
);
5775 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
5776 REG_SZ
, buffer
.data
, buffer
.length
);
5778 /* Update printer info */
5779 result
= mod_a_printer(printer
, 2);
5782 free_a_printer(&printer
, 2);
5783 free_a_printer(&old_printer
, 2);
5789 /****************************************************************************
5790 ****************************************************************************/
5791 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
,
5792 struct policy_handle
*handle
,
5793 struct spoolss_SetPrinterInfo7
*info7
)
5797 Printer_entry
*Printer
;
5799 if ( lp_security() != SEC_ADS
) {
5800 return WERR_UNKNOWN_LEVEL
;
5803 Printer
= find_printer_index_by_hnd(p
, handle
);
5805 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
5810 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5813 nt_printer_publish(Printer
, snum
, info7
->action
);
5817 return WERR_UNKNOWN_LEVEL
;
5821 /********************************************************************
5822 ********************************************************************/
5824 static WERROR
update_printer_devmode(pipes_struct
*p
, struct policy_handle
*handle
,
5825 struct spoolss_DeviceMode
*devmode
)
5828 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5829 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5832 DEBUG(8,("update_printer_devmode\n"));
5837 result
= WERR_BADFID
;
5841 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
5842 result
= WERR_BADFID
;
5846 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
)))) {
5847 result
= WERR_BADFID
;
5852 /* we have a valid devmode
5853 convert it and link it*/
5855 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5856 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5857 &printer
->info_2
->devmode
)) {
5858 result
= WERR_NOMEM
;
5863 /* Check calling user has permission to update printer description */
5865 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5866 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5867 result
= WERR_ACCESS_DENIED
;
5872 /* Update printer info */
5873 result
= mod_a_printer(printer
, 2);
5876 free_a_printer(&printer
, 2);
5882 /****************************************************************
5884 ****************************************************************/
5886 WERROR
_spoolss_SetPrinter(pipes_struct
*p
,
5887 struct spoolss_SetPrinter
*r
)
5891 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5894 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5895 OUR_HANDLE(r
->in
.handle
)));
5899 /* check the level */
5900 switch (r
->in
.info_ctr
->level
) {
5902 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
5904 result
= update_printer(p
, r
->in
.handle
,
5906 r
->in
.devmode_ctr
->devmode
);
5907 if (!W_ERROR_IS_OK(result
))
5909 if (r
->in
.secdesc_ctr
->sd
)
5910 result
= update_printer_sec(r
->in
.handle
, p
,
5914 return update_printer_sec(r
->in
.handle
, p
,
5917 return publish_or_unpublish_printer(p
, r
->in
.handle
,
5918 r
->in
.info_ctr
->info
.info7
);
5920 return update_printer_devmode(p
, r
->in
.handle
,
5921 r
->in
.devmode_ctr
->devmode
);
5923 return WERR_UNKNOWN_LEVEL
;
5927 /****************************************************************
5928 _spoolss_FindClosePrinterNotify
5929 ****************************************************************/
5931 WERROR
_spoolss_FindClosePrinterNotify(pipes_struct
*p
,
5932 struct spoolss_FindClosePrinterNotify
*r
)
5934 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5937 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5938 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
5942 if (Printer
->notify
.client_connected
== true) {
5945 if ( Printer
->printer_type
== SPLHND_SERVER
)
5947 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
5948 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
5951 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
5954 Printer
->notify
.flags
=0;
5955 Printer
->notify
.options
=0;
5956 Printer
->notify
.localmachine
[0]='\0';
5957 Printer
->notify
.printerlocal
=0;
5958 TALLOC_FREE(Printer
->notify
.option
);
5959 Printer
->notify
.client_connected
= false;
5964 /****************************************************************
5966 ****************************************************************/
5968 WERROR
_spoolss_AddJob(pipes_struct
*p
,
5969 struct spoolss_AddJob
*r
)
5971 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5972 return WERR_INVALID_PARAM
;
5975 /* this is what a NT server returns for AddJob. AddJob must fail on
5976 * non-local printers */
5978 if (r
->in
.level
!= 1) {
5979 return WERR_UNKNOWN_LEVEL
;
5982 return WERR_INVALID_PARAM
;
5985 /****************************************************************************
5987 ****************************************************************************/
5989 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
5990 struct spoolss_JobInfo1
*r
,
5991 const print_queue_struct
*queue
,
5992 int position
, int snum
,
5993 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
5997 t
= gmtime(&queue
->time
);
5999 r
->job_id
= queue
->job
;
6001 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6002 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6003 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6004 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6005 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6006 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6007 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6008 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6009 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6010 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6011 r
->text_status
= talloc_strdup(mem_ctx
, "");
6012 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6014 r
->status
= nt_printj_status(queue
->status
);
6015 r
->priority
= queue
->priority
;
6016 r
->position
= position
;
6017 r
->total_pages
= queue
->page_count
;
6018 r
->pages_printed
= 0; /* ??? */
6020 init_systemtime(&r
->submitted
, t
);
6025 /****************************************************************************
6027 ****************************************************************************/
6029 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6030 struct spoolss_JobInfo2
*r
,
6031 const print_queue_struct
*queue
,
6032 int position
, int snum
,
6033 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6034 struct spoolss_DeviceMode
*devmode
)
6038 t
= gmtime(&queue
->time
);
6040 r
->job_id
= queue
->job
;
6042 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6043 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6044 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6045 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6046 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6047 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6048 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6049 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6050 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6051 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6052 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6053 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6054 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6055 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6056 r
->parameters
= talloc_strdup(mem_ctx
, "");
6057 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6058 r
->driver_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
6059 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6061 r
->devmode
= devmode
;
6063 r
->text_status
= talloc_strdup(mem_ctx
, "");
6064 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6068 r
->status
= nt_printj_status(queue
->status
);
6069 r
->priority
= queue
->priority
;
6070 r
->position
= position
;
6073 r
->total_pages
= queue
->page_count
;
6074 r
->size
= queue
->size
;
6075 init_systemtime(&r
->submitted
, t
);
6077 r
->pages_printed
= 0; /* ??? */
6082 /****************************************************************************
6084 ****************************************************************************/
6086 static WERROR
fill_job_info3(TALLOC_CTX
*mem_ctx
,
6087 struct spoolss_JobInfo3
*r
,
6088 const print_queue_struct
*queue
,
6089 const print_queue_struct
*next_queue
,
6090 int position
, int snum
,
6091 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
6093 r
->job_id
= queue
->job
;
6096 r
->next_job_id
= next_queue
->job
;
6103 /****************************************************************************
6104 Enumjobs at level 1.
6105 ****************************************************************************/
6107 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6108 const print_queue_struct
*queue
,
6109 uint32_t num_queues
, int snum
,
6110 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6111 union spoolss_JobInfo
**info_p
,
6114 union spoolss_JobInfo
*info
;
6116 WERROR result
= WERR_OK
;
6118 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6119 W_ERROR_HAVE_NO_MEMORY(info
);
6121 *count
= num_queues
;
6123 for (i
=0; i
<*count
; i
++) {
6124 result
= fill_job_info1(info
,
6130 if (!W_ERROR_IS_OK(result
)) {
6136 if (!W_ERROR_IS_OK(result
)) {
6147 /****************************************************************************
6148 Enumjobs at level 2.
6149 ****************************************************************************/
6151 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6152 const print_queue_struct
*queue
,
6153 uint32_t num_queues
, int snum
,
6154 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6155 union spoolss_JobInfo
**info_p
,
6158 union spoolss_JobInfo
*info
;
6160 WERROR result
= WERR_OK
;
6162 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6163 W_ERROR_HAVE_NO_MEMORY(info
);
6165 *count
= num_queues
;
6167 for (i
=0; i
<*count
; i
++) {
6169 struct spoolss_DeviceMode
*devmode
;
6171 devmode
= construct_dev_mode(info
, lp_const_servicename(snum
));
6173 result
= WERR_NOMEM
;
6177 result
= fill_job_info2(info
,
6184 if (!W_ERROR_IS_OK(result
)) {
6190 if (!W_ERROR_IS_OK(result
)) {
6201 /****************************************************************************
6202 Enumjobs at level 3.
6203 ****************************************************************************/
6205 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
6206 const print_queue_struct
*queue
,
6207 uint32_t num_queues
, int snum
,
6208 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6209 union spoolss_JobInfo
**info_p
,
6212 union spoolss_JobInfo
*info
;
6214 WERROR result
= WERR_OK
;
6216 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6217 W_ERROR_HAVE_NO_MEMORY(info
);
6219 *count
= num_queues
;
6221 for (i
=0; i
<*count
; i
++) {
6222 const print_queue_struct
*next_queue
= NULL
;
6225 next_queue
= &queue
[i
+1];
6228 result
= fill_job_info3(info
,
6235 if (!W_ERROR_IS_OK(result
)) {
6241 if (!W_ERROR_IS_OK(result
)) {
6252 /****************************************************************
6254 ****************************************************************/
6256 WERROR
_spoolss_EnumJobs(pipes_struct
*p
,
6257 struct spoolss_EnumJobs
*r
)
6260 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6262 print_status_struct prt_status
;
6263 print_queue_struct
*queue
= NULL
;
6266 /* that's an [in out] buffer */
6268 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6269 return WERR_INVALID_PARAM
;
6272 DEBUG(4,("_spoolss_EnumJobs\n"));
6276 *r
->out
.info
= NULL
;
6278 /* lookup the printer snum and tdb entry */
6280 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6284 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6285 if (!W_ERROR_IS_OK(result
)) {
6289 count
= print_queue_status(snum
, &queue
, &prt_status
);
6290 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6291 count
, prt_status
.status
, prt_status
.message
));
6295 free_a_printer(&ntprinter
, 2);
6299 switch (r
->in
.level
) {
6301 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
6302 ntprinter
, r
->out
.info
, r
->out
.count
);
6305 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
6306 ntprinter
, r
->out
.info
, r
->out
.count
);
6309 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
6310 ntprinter
, r
->out
.info
, r
->out
.count
);
6313 result
= WERR_UNKNOWN_LEVEL
;
6318 free_a_printer(&ntprinter
, 2);
6320 if (!W_ERROR_IS_OK(result
)) {
6324 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6326 *r
->out
.info
, r
->in
.level
,
6328 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6329 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6331 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6334 /****************************************************************
6335 _spoolss_ScheduleJob
6336 ****************************************************************/
6338 WERROR
_spoolss_ScheduleJob(pipes_struct
*p
,
6339 struct spoolss_ScheduleJob
*r
)
6344 /****************************************************************
6345 ****************************************************************/
6347 static WERROR
spoolss_setjob_1(TALLOC_CTX
*mem_ctx
,
6348 const char *printer_name
,
6350 struct spoolss_SetJobInfo1
*r
)
6354 if (!print_job_get_name(mem_ctx
, printer_name
, job_id
, &old_doc_name
)) {
6358 if (strequal(old_doc_name
, r
->document_name
)) {
6362 if (!print_job_set_name(printer_name
, job_id
, r
->document_name
)) {
6369 /****************************************************************
6371 ****************************************************************/
6373 WERROR
_spoolss_SetJob(pipes_struct
*p
,
6374 struct spoolss_SetJob
*r
)
6377 WERROR errcode
= WERR_BADFUNC
;
6379 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6383 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
6384 return WERR_INVALID_PRINTER_NAME
;
6387 switch (r
->in
.command
) {
6388 case SPOOLSS_JOB_CONTROL_CANCEL
:
6389 case SPOOLSS_JOB_CONTROL_DELETE
:
6390 if (print_job_delete(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6394 case SPOOLSS_JOB_CONTROL_PAUSE
:
6395 if (print_job_pause(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6399 case SPOOLSS_JOB_CONTROL_RESTART
:
6400 case SPOOLSS_JOB_CONTROL_RESUME
:
6401 if (print_job_resume(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6409 return WERR_UNKNOWN_LEVEL
;
6412 if (!W_ERROR_IS_OK(errcode
)) {
6416 if (r
->in
.ctr
== NULL
) {
6420 switch (r
->in
.ctr
->level
) {
6422 errcode
= spoolss_setjob_1(p
->mem_ctx
, lp_const_servicename(snum
),
6424 r
->in
.ctr
->info
.info1
);
6430 return WERR_UNKNOWN_LEVEL
;
6436 /****************************************************************************
6437 Enumerates all printer drivers by level and architecture.
6438 ****************************************************************************/
6440 static WERROR
enumprinterdrivers_level_by_architecture(TALLOC_CTX
*mem_ctx
,
6441 const char *servername
,
6442 const char *architecture
,
6444 union spoolss_DriverInfo
**info_p
,
6450 fstring
*list
= NULL
;
6451 struct spoolss_DriverInfo8
*driver
;
6452 union spoolss_DriverInfo
*info
= NULL
;
6454 WERROR result
= WERR_OK
;
6459 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6461 ndrivers
= get_ntdrivers(&list
, architecture
, version
);
6462 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6463 ndrivers
, architecture
, version
));
6465 if (ndrivers
== -1) {
6466 result
= WERR_NOMEM
;
6470 if (ndrivers
!= 0) {
6471 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
6472 union spoolss_DriverInfo
,
6475 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6476 "failed to enlarge driver info buffer!\n"));
6477 result
= WERR_NOMEM
;
6482 for (i
=0; i
<ndrivers
; i
++) {
6483 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6484 ZERO_STRUCT(driver
);
6485 result
= get_a_printer_driver(mem_ctx
, &driver
, list
[i
],
6486 architecture
, version
);
6487 if (!W_ERROR_IS_OK(result
)) {
6493 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
6494 driver
, servername
);
6497 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
6498 driver
, servername
);
6501 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
6502 driver
, servername
);
6505 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
6506 driver
, servername
);
6509 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
6510 driver
, servername
);
6513 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
6514 driver
, servername
);
6517 result
= fill_printer_driver_info8(info
, &info
[count
+i
].info8
,
6518 driver
, servername
);
6521 result
= WERR_UNKNOWN_LEVEL
;
6525 free_a_printer_driver(driver
);
6527 if (!W_ERROR_IS_OK(result
)) {
6539 if (!W_ERROR_IS_OK(result
)) {
6550 /****************************************************************************
6551 Enumerates all printer drivers by level.
6552 ****************************************************************************/
6554 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
6555 const char *servername
,
6556 const char *architecture
,
6558 union spoolss_DriverInfo
**info_p
,
6562 WERROR result
= WERR_OK
;
6564 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_ALL
)) {
6566 for (a
=0; archi_table
[a
].long_archi
!= NULL
; a
++) {
6568 union spoolss_DriverInfo
*info
= NULL
;
6571 result
= enumprinterdrivers_level_by_architecture(mem_ctx
,
6573 archi_table
[a
].long_archi
,
6577 if (!W_ERROR_IS_OK(result
)) {
6581 for (i
=0; i
< count
; i
++) {
6582 ADD_TO_ARRAY(mem_ctx
, union spoolss_DriverInfo
,
6583 info
[i
], info_p
, count_p
);
6590 return enumprinterdrivers_level_by_architecture(mem_ctx
,
6598 /****************************************************************
6599 _spoolss_EnumPrinterDrivers
6600 ****************************************************************/
6602 WERROR
_spoolss_EnumPrinterDrivers(pipes_struct
*p
,
6603 struct spoolss_EnumPrinterDrivers
*r
)
6605 const char *cservername
;
6608 /* that's an [in out] buffer */
6610 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6611 return WERR_INVALID_PARAM
;
6614 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6618 *r
->out
.info
= NULL
;
6620 cservername
= canon_servername(r
->in
.server
);
6622 if (!is_myname_or_ipaddr(cservername
)) {
6623 return WERR_UNKNOWN_PRINTER_DRIVER
;
6626 result
= enumprinterdrivers_level(p
->mem_ctx
, cservername
,
6631 if (!W_ERROR_IS_OK(result
)) {
6635 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6636 spoolss_EnumPrinterDrivers
,
6637 *r
->out
.info
, r
->in
.level
,
6639 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6640 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6642 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6645 /****************************************************************************
6646 ****************************************************************************/
6648 static WERROR
fill_form_info_1(TALLOC_CTX
*mem_ctx
,
6649 struct spoolss_FormInfo1
*r
,
6650 const nt_forms_struct
*form
)
6652 r
->form_name
= talloc_strdup(mem_ctx
, form
->name
);
6653 W_ERROR_HAVE_NO_MEMORY(r
->form_name
);
6655 r
->flags
= form
->flag
;
6656 r
->size
.width
= form
->width
;
6657 r
->size
.height
= form
->length
;
6658 r
->area
.left
= form
->left
;
6659 r
->area
.top
= form
->top
;
6660 r
->area
.right
= form
->right
;
6661 r
->area
.bottom
= form
->bottom
;
6666 /****************************************************************
6667 spoolss_enumforms_level1
6668 ****************************************************************/
6670 static WERROR
spoolss_enumforms_level1(TALLOC_CTX
*mem_ctx
,
6671 const nt_forms_struct
*builtin_forms
,
6672 uint32_t num_builtin_forms
,
6673 const nt_forms_struct
*user_forms
,
6674 uint32_t num_user_forms
,
6675 union spoolss_FormInfo
**info_p
,
6678 union spoolss_FormInfo
*info
;
6679 WERROR result
= WERR_OK
;
6682 *count
= num_builtin_forms
+ num_user_forms
;
6684 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_FormInfo
, *count
);
6685 W_ERROR_HAVE_NO_MEMORY(info
);
6687 /* construct the list of form structures */
6688 for (i
=0; i
<num_builtin_forms
; i
++) {
6689 DEBUGADD(6,("Filling builtin form number [%d]\n",i
));
6690 result
= fill_form_info_1(info
, &info
[i
].info1
,
6692 if (!W_ERROR_IS_OK(result
)) {
6697 for (i
=0; i
<num_user_forms
; i
++) {
6698 DEBUGADD(6,("Filling user form number [%d]\n",i
));
6699 result
= fill_form_info_1(info
, &info
[i
+num_builtin_forms
].info1
,
6701 if (!W_ERROR_IS_OK(result
)) {
6707 if (!W_ERROR_IS_OK(result
)) {
6718 /****************************************************************
6720 ****************************************************************/
6722 WERROR
_spoolss_EnumForms(pipes_struct
*p
,
6723 struct spoolss_EnumForms
*r
)
6726 nt_forms_struct
*user_forms
= NULL
;
6727 nt_forms_struct
*builtin_forms
= NULL
;
6728 uint32_t num_user_forms
;
6729 uint32_t num_builtin_forms
;
6733 *r
->out
.info
= NULL
;
6735 /* that's an [in out] buffer */
6737 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
6738 return WERR_INVALID_PARAM
;
6741 DEBUG(4,("_spoolss_EnumForms\n"));
6742 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
6743 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
6745 num_builtin_forms
= get_builtin_ntforms(&builtin_forms
);
6746 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms
));
6747 num_user_forms
= get_ntforms(&user_forms
);
6748 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms
));
6750 if (num_user_forms
+ num_builtin_forms
== 0) {
6751 SAFE_FREE(builtin_forms
);
6752 SAFE_FREE(user_forms
);
6753 return WERR_NO_MORE_ITEMS
;
6756 switch (r
->in
.level
) {
6758 result
= spoolss_enumforms_level1(p
->mem_ctx
,
6767 result
= WERR_UNKNOWN_LEVEL
;
6771 SAFE_FREE(user_forms
);
6772 SAFE_FREE(builtin_forms
);
6774 if (!W_ERROR_IS_OK(result
)) {
6778 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6780 *r
->out
.info
, r
->in
.level
,
6782 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6783 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6785 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6788 /****************************************************************
6789 ****************************************************************/
6791 static WERROR
find_form_byname(const char *name
,
6792 nt_forms_struct
*form
)
6794 nt_forms_struct
*list
= NULL
;
6795 int num_forms
= 0, i
= 0;
6797 if (get_a_builtin_ntform_by_string(name
, form
)) {
6801 num_forms
= get_ntforms(&list
);
6802 DEBUGADD(5,("Number of forms [%d]\n", num_forms
));
6804 if (num_forms
== 0) {
6808 /* Check if the requested name is in the list of form structures */
6809 for (i
= 0; i
< num_forms
; i
++) {
6811 DEBUG(4,("checking form %s (want %s)\n", list
[i
].name
, name
));
6813 if (strequal(name
, list
[i
].name
)) {
6814 DEBUGADD(6,("Found form %s number [%d]\n", name
, i
));
6826 /****************************************************************
6828 ****************************************************************/
6830 WERROR
_spoolss_GetForm(pipes_struct
*p
,
6831 struct spoolss_GetForm
*r
)
6834 nt_forms_struct form
;
6836 /* that's an [in out] buffer */
6838 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6839 return WERR_INVALID_PARAM
;
6842 DEBUG(4,("_spoolss_GetForm\n"));
6843 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
6844 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
6846 result
= find_form_byname(r
->in
.form_name
, &form
);
6847 if (!W_ERROR_IS_OK(result
)) {
6848 TALLOC_FREE(r
->out
.info
);
6852 switch (r
->in
.level
) {
6854 result
= fill_form_info_1(p
->mem_ctx
,
6855 &r
->out
.info
->info1
,
6860 result
= WERR_UNKNOWN_LEVEL
;
6864 if (!W_ERROR_IS_OK(result
)) {
6865 TALLOC_FREE(r
->out
.info
);
6869 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
,
6870 r
->out
.info
, r
->in
.level
);
6871 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
6873 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6876 /****************************************************************************
6877 ****************************************************************************/
6879 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
6880 struct spoolss_PortInfo1
*r
,
6883 r
->port_name
= talloc_strdup(mem_ctx
, name
);
6884 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
6889 /****************************************************************************
6890 TODO: This probably needs distinguish between TCP/IP and Local ports
6892 ****************************************************************************/
6894 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
6895 struct spoolss_PortInfo2
*r
,
6898 r
->port_name
= talloc_strdup(mem_ctx
, name
);
6899 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
6901 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
6902 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
6904 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
6905 W_ERROR_HAVE_NO_MEMORY(r
->description
);
6907 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
6914 /****************************************************************************
6915 wrapper around the enumer ports command
6916 ****************************************************************************/
6918 static WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
6920 char *cmd
= lp_enumports_cmd();
6921 char **qlines
= NULL
;
6922 char *command
= NULL
;
6930 /* if no hook then just fill in the default port */
6933 if (!(qlines
= TALLOC_ARRAY( NULL
, char*, 2 ))) {
6936 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
6937 TALLOC_FREE(qlines
);
6944 /* we have a valid enumport command */
6946 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
6951 DEBUG(10,("Running [%s]\n", command
));
6952 ret
= smbrun(command
, &fd
);
6953 DEBUG(10,("Returned [%d]\n", ret
));
6954 TALLOC_FREE(command
);
6959 return WERR_ACCESS_DENIED
;
6963 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
6964 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6974 /****************************************************************************
6976 ****************************************************************************/
6978 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
6979 union spoolss_PortInfo
**info_p
,
6982 union spoolss_PortInfo
*info
= NULL
;
6984 WERROR result
= WERR_OK
;
6985 char **qlines
= NULL
;
6988 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
6989 if (!W_ERROR_IS_OK(result
)) {
6994 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
6996 DEBUG(10,("Returning WERR_NOMEM\n"));
6997 result
= WERR_NOMEM
;
7001 for (i
=0; i
<numlines
; i
++) {
7002 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7003 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7004 if (!W_ERROR_IS_OK(result
)) {
7009 TALLOC_FREE(qlines
);
7012 if (!W_ERROR_IS_OK(result
)) {
7014 TALLOC_FREE(qlines
);
7026 /****************************************************************************
7028 ****************************************************************************/
7030 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7031 union spoolss_PortInfo
**info_p
,
7034 union spoolss_PortInfo
*info
= NULL
;
7036 WERROR result
= WERR_OK
;
7037 char **qlines
= NULL
;
7040 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7041 if (!W_ERROR_IS_OK(result
)) {
7046 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7048 DEBUG(10,("Returning WERR_NOMEM\n"));
7049 result
= WERR_NOMEM
;
7053 for (i
=0; i
<numlines
; i
++) {
7054 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7055 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7056 if (!W_ERROR_IS_OK(result
)) {
7061 TALLOC_FREE(qlines
);
7064 if (!W_ERROR_IS_OK(result
)) {
7066 TALLOC_FREE(qlines
);
7078 /****************************************************************
7080 ****************************************************************/
7082 WERROR
_spoolss_EnumPorts(pipes_struct
*p
,
7083 struct spoolss_EnumPorts
*r
)
7087 /* that's an [in out] buffer */
7089 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7090 return WERR_INVALID_PARAM
;
7093 DEBUG(4,("_spoolss_EnumPorts\n"));
7097 *r
->out
.info
= NULL
;
7099 switch (r
->in
.level
) {
7101 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7105 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7109 return WERR_UNKNOWN_LEVEL
;
7112 if (!W_ERROR_IS_OK(result
)) {
7116 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7118 *r
->out
.info
, r
->in
.level
,
7120 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7121 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7123 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7126 /****************************************************************************
7127 ****************************************************************************/
7129 static WERROR
spoolss_addprinterex_level_2(pipes_struct
*p
,
7131 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7132 struct spoolss_DeviceMode
*devmode
,
7133 struct security_descriptor
*sec_desc
,
7134 struct spoolss_UserLevelCtr
*user_ctr
,
7135 struct policy_handle
*handle
)
7137 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7140 WERROR err
= WERR_OK
;
7142 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7143 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7147 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7148 if (!convert_printer_info(info_ctr
, printer
)) {
7149 free_a_printer(&printer
, 2);
7153 /* samba does not have a concept of local, non-shared printers yet, so
7154 * make sure we always setup sharename - gd */
7155 if ((printer
->info_2
->sharename
[0] == '\0') && (printer
->info_2
->printername
!= '\0')) {
7156 DEBUG(5, ("spoolss_addprinterex_level_2: "
7157 "no sharename has been set, setting printername %s as sharename\n",
7158 printer
->info_2
->printername
));
7159 fstrcpy(printer
->info_2
->sharename
, printer
->info_2
->printername
);
7162 /* check to see if the printer already exists */
7164 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7165 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7166 printer
->info_2
->sharename
));
7167 free_a_printer(&printer
, 2);
7168 return WERR_PRINTER_ALREADY_EXISTS
;
7171 if (!lp_force_printername(GLOBAL_SECTION_SNUM
)) {
7172 if ((snum
= print_queue_snum(printer
->info_2
->printername
)) != -1) {
7173 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7174 printer
->info_2
->printername
));
7175 free_a_printer(&printer
, 2);
7176 return WERR_PRINTER_ALREADY_EXISTS
;
7180 /* validate printer info struct */
7181 if (!info_ctr
->info
.info2
->printername
||
7182 strlen(info_ctr
->info
.info2
->printername
) == 0) {
7183 free_a_printer(&printer
,2);
7184 return WERR_INVALID_PRINTER_NAME
;
7186 if (!info_ctr
->info
.info2
->portname
||
7187 strlen(info_ctr
->info
.info2
->portname
) == 0) {
7188 free_a_printer(&printer
,2);
7189 return WERR_UNKNOWN_PORT
;
7191 if (!info_ctr
->info
.info2
->drivername
||
7192 strlen(info_ctr
->info
.info2
->drivername
) == 0) {
7193 free_a_printer(&printer
,2);
7194 return WERR_UNKNOWN_PRINTER_DRIVER
;
7196 if (!info_ctr
->info
.info2
->printprocessor
||
7197 strlen(info_ctr
->info
.info2
->printprocessor
) == 0) {
7198 free_a_printer(&printer
,2);
7199 return WERR_UNKNOWN_PRINTPROCESSOR
;
7202 /* FIXME!!! smbd should check to see if the driver is installed before
7203 trying to add a printer like this --jerry */
7205 if (*lp_addprinter_cmd() ) {
7206 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
7208 free_a_printer(&printer
,2);
7209 return WERR_ACCESS_DENIED
;
7212 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7213 "smb.conf parameter \"addprinter command\" is defined. This"
7214 "parameter must exist for this call to succeed\n",
7215 printer
->info_2
->sharename
));
7218 /* use our primary netbios name since get_a_printer() will convert
7219 it to what the client expects on a case by case basis */
7221 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7222 printer
->info_2
->sharename
);
7225 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7226 free_a_printer(&printer
,2);
7227 return WERR_ACCESS_DENIED
;
7230 /* you must be a printer admin to add a new printer */
7231 if (!print_access_check(p
->server_info
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7232 free_a_printer(&printer
,2);
7233 return WERR_ACCESS_DENIED
;
7237 * Do sanity check on the requested changes for Samba.
7240 if (!check_printer_ok(printer
->info_2
, snum
)) {
7241 free_a_printer(&printer
,2);
7242 return WERR_INVALID_PARAM
;
7246 * When a printer is created, the drivername bound to the printer is used
7247 * to lookup previously saved driver initialization info, which is then
7248 * bound to the new printer, simulating what happens in the Windows arch.
7253 /* A valid devmode was included, convert and link it
7255 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7257 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7258 &printer
->info_2
->devmode
)) {
7263 /* write the ASCII on disk */
7264 err
= mod_a_printer(printer
, 2);
7265 if (!W_ERROR_IS_OK(err
)) {
7266 free_a_printer(&printer
,2);
7270 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7271 /* Handle open failed - remove addition. */
7272 del_a_printer(printer
->info_2
->sharename
);
7273 free_a_printer(&printer
,2);
7274 ZERO_STRUCTP(handle
);
7275 return WERR_ACCESS_DENIED
;
7278 update_c_setprinter(false);
7279 free_a_printer(&printer
,2);
7284 /****************************************************************
7285 _spoolss_AddPrinterEx
7286 ****************************************************************/
7288 WERROR
_spoolss_AddPrinterEx(pipes_struct
*p
,
7289 struct spoolss_AddPrinterEx
*r
)
7291 switch (r
->in
.info_ctr
->level
) {
7293 /* we don't handle yet */
7294 /* but I know what to do ... */
7295 return WERR_UNKNOWN_LEVEL
;
7297 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
7299 r
->in
.devmode_ctr
->devmode
,
7300 r
->in
.secdesc_ctr
->sd
,
7301 r
->in
.userlevel_ctr
,
7304 return WERR_UNKNOWN_LEVEL
;
7308 /****************************************************************
7310 ****************************************************************/
7312 WERROR
_spoolss_AddPrinter(pipes_struct
*p
,
7313 struct spoolss_AddPrinter
*r
)
7315 struct spoolss_AddPrinterEx a
;
7316 struct spoolss_UserLevelCtr userlevel_ctr
;
7318 ZERO_STRUCT(userlevel_ctr
);
7320 userlevel_ctr
.level
= 1;
7322 a
.in
.server
= r
->in
.server
;
7323 a
.in
.info_ctr
= r
->in
.info_ctr
;
7324 a
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
7325 a
.in
.secdesc_ctr
= r
->in
.secdesc_ctr
;
7326 a
.in
.userlevel_ctr
= &userlevel_ctr
;
7327 a
.out
.handle
= r
->out
.handle
;
7329 return _spoolss_AddPrinterEx(p
, &a
);
7332 /****************************************************************
7333 _spoolss_AddPrinterDriverEx
7334 ****************************************************************/
7336 WERROR
_spoolss_AddPrinterDriverEx(pipes_struct
*p
,
7337 struct spoolss_AddPrinterDriverEx
*r
)
7339 WERROR err
= WERR_OK
;
7340 char *driver_name
= NULL
;
7344 switch (p
->hdr_req
.opnum
) {
7345 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
7346 fn
= "_spoolss_AddPrinterDriver";
7348 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
7349 fn
= "_spoolss_AddPrinterDriverEx";
7352 return WERR_INVALID_PARAM
;
7356 * we only support the semantics of AddPrinterDriver()
7357 * i.e. only copy files that are newer than existing ones
7360 if (r
->in
.flags
== 0) {
7361 return WERR_INVALID_PARAM
;
7364 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
7365 return WERR_ACCESS_DENIED
;
7369 if (r
->in
.info_ctr
->level
!= 3 && r
->in
.info_ctr
->level
!= 6) {
7370 /* Clever hack from Martin Zielinski <mz@seh.de>
7371 * to allow downgrade from level 8 (Vista).
7373 DEBUG(0,("%s: level %d not yet implemented\n", fn
,
7374 r
->in
.info_ctr
->level
));
7375 return WERR_UNKNOWN_LEVEL
;
7378 DEBUG(5,("Cleaning driver's information\n"));
7379 err
= clean_up_driver_struct(p
, r
->in
.info_ctr
);
7380 if (!W_ERROR_IS_OK(err
))
7383 DEBUG(5,("Moving driver to final destination\n"));
7384 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(p
, r
->in
.info_ctr
,
7389 if (add_a_printer_driver(p
->mem_ctx
, r
->in
.info_ctr
, &driver_name
, &version
)!=0) {
7390 err
= WERR_ACCESS_DENIED
;
7395 * I think this is where he DrvUpgradePrinter() hook would be
7396 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7397 * server. Right now, we just need to send ourselves a message
7398 * to update each printer bound to this driver. --jerry
7401 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7402 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7410 /****************************************************************
7411 _spoolss_AddPrinterDriver
7412 ****************************************************************/
7414 WERROR
_spoolss_AddPrinterDriver(pipes_struct
*p
,
7415 struct spoolss_AddPrinterDriver
*r
)
7417 struct spoolss_AddPrinterDriverEx a
;
7419 switch (r
->in
.info_ctr
->level
) {
7426 return WERR_UNKNOWN_LEVEL
;
7429 a
.in
.servername
= r
->in
.servername
;
7430 a
.in
.info_ctr
= r
->in
.info_ctr
;
7431 a
.in
.flags
= APD_COPY_NEW_FILES
;
7433 return _spoolss_AddPrinterDriverEx(p
, &a
);
7436 /****************************************************************************
7437 ****************************************************************************/
7439 struct _spoolss_paths
{
7445 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
7447 static const struct _spoolss_paths spoolss_paths
[]= {
7448 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
7449 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
7452 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
7453 const char *servername
,
7454 const char *environment
,
7458 const char *pservername
= NULL
;
7459 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
7460 const char *short_archi
;
7464 /* environment may be empty */
7465 if (environment
&& strlen(environment
)) {
7466 long_archi
= environment
;
7469 /* servername may be empty */
7470 if (servername
&& strlen(servername
)) {
7471 pservername
= canon_servername(servername
);
7473 if (!is_myname_or_ipaddr(pservername
)) {
7474 return WERR_INVALID_PARAM
;
7478 if (!(short_archi
= get_short_archi(long_archi
))) {
7479 return WERR_INVALID_ENVIRONMENT
;
7482 switch (component
) {
7483 case SPOOLSS_PRTPROCS_PATH
:
7484 case SPOOLSS_DRIVER_PATH
:
7486 *path
= talloc_asprintf(mem_ctx
,
7489 spoolss_paths
[component
].share
,
7492 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
7493 SPOOLSS_DEFAULT_SERVER_PATH
,
7494 spoolss_paths
[component
].dir
,
7499 return WERR_INVALID_PARAM
;
7509 /****************************************************************************
7510 ****************************************************************************/
7512 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
7513 const char *servername
,
7514 const char *environment
,
7515 struct spoolss_DriverDirectoryInfo1
*r
)
7520 werr
= compose_spoolss_server_path(mem_ctx
,
7523 SPOOLSS_DRIVER_PATH
,
7525 if (!W_ERROR_IS_OK(werr
)) {
7529 DEBUG(4,("printer driver directory: [%s]\n", path
));
7531 r
->directory_name
= path
;
7536 /****************************************************************
7537 _spoolss_GetPrinterDriverDirectory
7538 ****************************************************************/
7540 WERROR
_spoolss_GetPrinterDriverDirectory(pipes_struct
*p
,
7541 struct spoolss_GetPrinterDriverDirectory
*r
)
7545 /* that's an [in out] buffer */
7547 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7548 return WERR_INVALID_PARAM
;
7551 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7556 /* r->in.level is ignored */
7558 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
7561 &r
->out
.info
->info1
);
7562 if (!W_ERROR_IS_OK(werror
)) {
7563 TALLOC_FREE(r
->out
.info
);
7567 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
,
7568 r
->out
.info
, r
->in
.level
);
7569 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7571 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7574 /****************************************************************
7575 _spoolss_EnumPrinterData
7576 ****************************************************************/
7578 WERROR
_spoolss_EnumPrinterData(pipes_struct
*p
,
7579 struct spoolss_EnumPrinterData
*r
)
7582 struct spoolss_EnumPrinterDataEx r2
;
7584 struct spoolss_PrinterEnumValues
*info
, *val
= NULL
;
7587 r2
.in
.handle
= r
->in
.handle
;
7588 r2
.in
.key_name
= "PrinterDriverData";
7590 r2
.out
.count
= &count
;
7591 r2
.out
.info
= &info
;
7592 r2
.out
.needed
= &needed
;
7594 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
7595 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
7596 r2
.in
.offered
= needed
;
7597 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
7599 if (!W_ERROR_IS_OK(result
)) {
7604 * The NT machine wants to know the biggest size of value and data
7606 * cf: MSDN EnumPrinterData remark section
7609 if (!r
->in
.value_offered
&& !r
->in
.data_offered
) {
7610 uint32_t biggest_valuesize
= 0;
7611 uint32_t biggest_datasize
= 0;
7614 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7616 for (i
=0; i
<count
; i
++) {
7618 name_length
= strlen(info
[i
].value_name
);
7619 if (strlen(info
[i
].value_name
) > biggest_valuesize
) {
7620 biggest_valuesize
= name_length
;
7623 if (info
[i
].data_length
> biggest_datasize
) {
7624 biggest_datasize
= info
[i
].data_length
;
7627 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7631 /* the value is an UNICODE string but real_value_size is the length
7632 in bytes including the trailing 0 */
7634 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
7635 *r
->out
.data_needed
= biggest_datasize
;
7637 DEBUG(6,("final values: [%d], [%d]\n",
7638 *r
->out
.value_needed
, *r
->out
.data_needed
));
7643 if (r
->in
.enum_index
< count
) {
7644 val
= &info
[r
->in
.enum_index
];
7648 /* out_value should default to "" or else NT4 has
7649 problems unmarshalling the response */
7651 if (r
->in
.value_offered
) {
7652 *r
->out
.value_needed
= 1;
7653 r
->out
.value_name
= talloc_strdup(r
, "");
7654 if (!r
->out
.value_name
) {
7658 r
->out
.value_name
= NULL
;
7659 *r
->out
.value_needed
= 0;
7662 /* the data is counted in bytes */
7664 *r
->out
.data_needed
= r
->in
.data_offered
;
7666 result
= WERR_NO_MORE_ITEMS
;
7670 * - counted in bytes in the request
7671 * - counted in UNICODE chars in the max reply
7672 * - counted in bytes in the real size
7674 * take a pause *before* coding not *during* coding
7678 if (r
->in
.value_offered
) {
7679 r
->out
.value_name
= talloc_strdup(r
, val
->value_name
);
7680 if (!r
->out
.value_name
) {
7683 *r
->out
.value_needed
= val
->value_name_len
;
7685 r
->out
.value_name
= NULL
;
7686 *r
->out
.value_needed
= 0;
7691 *r
->out
.type
= val
->type
;
7693 /* data - counted in bytes */
7696 * See the section "Dynamically Typed Query Parameters"
7700 if (r
->out
.data
&& val
->data
&& val
->data
->data
&&
7701 val
->data_length
&& r
->in
.data_offered
) {
7702 memcpy(r
->out
.data
, val
->data
->data
,
7703 MIN(val
->data_length
,r
->in
.data_offered
));
7706 *r
->out
.data_needed
= val
->data_length
;
7714 /****************************************************************
7715 _spoolss_SetPrinterData
7716 ****************************************************************/
7718 WERROR
_spoolss_SetPrinterData(pipes_struct
*p
,
7719 struct spoolss_SetPrinterData
*r
)
7721 struct spoolss_SetPrinterDataEx r2
;
7723 r2
.in
.handle
= r
->in
.handle
;
7724 r2
.in
.key_name
= "PrinterDriverData";
7725 r2
.in
.value_name
= r
->in
.value_name
;
7726 r2
.in
.type
= r
->in
.type
;
7727 r2
.in
.data
= r
->in
.data
;
7728 r2
.in
.offered
= r
->in
.offered
;
7730 return _spoolss_SetPrinterDataEx(p
, &r2
);
7733 /****************************************************************
7734 _spoolss_ResetPrinter
7735 ****************************************************************/
7737 WERROR
_spoolss_ResetPrinter(pipes_struct
*p
,
7738 struct spoolss_ResetPrinter
*r
)
7740 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7743 DEBUG(5,("_spoolss_ResetPrinter\n"));
7746 * All we do is to check to see if the handle and queue is valid.
7747 * This call really doesn't mean anything to us because we only
7748 * support RAW printing. --jerry
7752 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7753 OUR_HANDLE(r
->in
.handle
)));
7757 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7761 /* blindly return success */
7765 /****************************************************************
7766 _spoolss_DeletePrinterData
7767 ****************************************************************/
7769 WERROR
_spoolss_DeletePrinterData(pipes_struct
*p
,
7770 struct spoolss_DeletePrinterData
*r
)
7772 struct spoolss_DeletePrinterDataEx r2
;
7774 r2
.in
.handle
= r
->in
.handle
;
7775 r2
.in
.key_name
= "PrinterDriverData";
7776 r2
.in
.value_name
= r
->in
.value_name
;
7778 return _spoolss_DeletePrinterDataEx(p
, &r2
);
7781 /****************************************************************
7783 ****************************************************************/
7785 WERROR
_spoolss_AddForm(pipes_struct
*p
,
7786 struct spoolss_AddForm
*r
)
7788 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
7789 nt_forms_struct tmpForm
;
7791 WERROR status
= WERR_OK
;
7792 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7793 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7796 nt_forms_struct
*list
=NULL
;
7797 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7800 DEBUG(5,("_spoolss_AddForm\n"));
7803 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7804 OUR_HANDLE(r
->in
.handle
)));
7809 /* forms can be added on printer or on the print server handle */
7811 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7813 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7816 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7817 if (!W_ERROR_IS_OK(status
))
7821 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7822 and not a printer admin, then fail */
7824 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
7825 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
7826 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
7828 p
->server_info
->ptok
,
7829 lp_printer_admin(snum
))) {
7830 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7831 status
= WERR_ACCESS_DENIED
;
7835 switch (form
->flags
) {
7836 case SPOOLSS_FORM_USER
:
7837 case SPOOLSS_FORM_BUILTIN
:
7838 case SPOOLSS_FORM_PRINTER
:
7841 status
= WERR_INVALID_PARAM
;
7845 /* can't add if builtin */
7847 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
7848 status
= WERR_FILE_EXISTS
;
7852 count
= get_ntforms(&list
);
7854 for (i
=0; i
< count
; i
++) {
7855 if (strequal(form
->form_name
, list
[i
].name
)) {
7856 status
= WERR_FILE_EXISTS
;
7861 if(!add_a_form(&list
, form
, &count
)) {
7862 status
= WERR_NOMEM
;
7867 write_ntforms(&list
, count
);
7871 * ChangeID must always be set if this is a printer
7874 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7875 status
= mod_a_printer(printer
, 2);
7879 free_a_printer(&printer
, 2);
7885 /****************************************************************
7887 ****************************************************************/
7889 WERROR
_spoolss_DeleteForm(pipes_struct
*p
,
7890 struct spoolss_DeleteForm
*r
)
7892 const char *form_name
= r
->in
.form_name
;
7893 nt_forms_struct tmpForm
;
7895 nt_forms_struct
*list
=NULL
;
7896 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7898 WERROR status
= WERR_OK
;
7899 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7900 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7903 DEBUG(5,("_spoolss_DeleteForm\n"));
7906 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7907 OUR_HANDLE(r
->in
.handle
)));
7911 /* forms can be deleted on printer of on the print server handle */
7913 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7915 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7918 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7919 if (!W_ERROR_IS_OK(status
))
7923 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
7924 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
7925 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
7927 p
->server_info
->ptok
,
7928 lp_printer_admin(snum
))) {
7929 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7930 return WERR_ACCESS_DENIED
;
7934 /* can't delete if builtin */
7936 if (get_a_builtin_ntform_by_string(form_name
,&tmpForm
)) {
7937 status
= WERR_INVALID_PARAM
;
7941 count
= get_ntforms(&list
);
7944 ret
= delete_a_form(&list
, form_name
, &count
, &status
);
7951 * ChangeID must always be set if this is a printer
7954 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7955 status
= mod_a_printer(printer
, 2);
7959 free_a_printer(&printer
, 2);
7965 /****************************************************************
7967 ****************************************************************/
7969 WERROR
_spoolss_SetForm(pipes_struct
*p
,
7970 struct spoolss_SetForm
*r
)
7972 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
7973 nt_forms_struct tmpForm
;
7975 WERROR status
= WERR_OK
;
7976 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7977 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7980 nt_forms_struct
*list
=NULL
;
7981 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7983 DEBUG(5,("_spoolss_SetForm\n"));
7986 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7987 OUR_HANDLE(r
->in
.handle
)));
7991 /* forms can be modified on printer of on the print server handle */
7993 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7995 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7998 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7999 if (!W_ERROR_IS_OK(status
))
8003 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8004 and not a printer admin, then fail */
8006 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8007 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8008 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8010 p
->server_info
->ptok
,
8011 lp_printer_admin(snum
))) {
8012 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8013 status
= WERR_ACCESS_DENIED
;
8017 /* can't set if builtin */
8018 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
8019 status
= WERR_INVALID_PARAM
;
8023 count
= get_ntforms(&list
);
8024 update_a_form(&list
, form
, count
);
8026 write_ntforms(&list
, count
);
8030 * ChangeID must always be set if this is a printer
8033 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8034 status
= mod_a_printer(printer
, 2);
8039 free_a_printer(&printer
, 2);
8045 /****************************************************************************
8046 fill_print_processor1
8047 ****************************************************************************/
8049 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8050 struct spoolss_PrintProcessorInfo1
*r
,
8051 const char *print_processor_name
)
8053 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8054 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8059 /****************************************************************************
8060 enumprintprocessors level 1.
8061 ****************************************************************************/
8063 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8064 union spoolss_PrintProcessorInfo
**info_p
,
8067 union spoolss_PrintProcessorInfo
*info
;
8070 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8071 W_ERROR_HAVE_NO_MEMORY(info
);
8075 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8076 if (!W_ERROR_IS_OK(result
)) {
8081 if (!W_ERROR_IS_OK(result
)) {
8092 /****************************************************************
8093 _spoolss_EnumPrintProcessors
8094 ****************************************************************/
8096 WERROR
_spoolss_EnumPrintProcessors(pipes_struct
*p
,
8097 struct spoolss_EnumPrintProcessors
*r
)
8101 /* that's an [in out] buffer */
8103 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8104 return WERR_INVALID_PARAM
;
8107 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8110 * Enumerate the print processors ...
8112 * Just reply with "winprint", to keep NT happy
8113 * and I can use my nice printer checker.
8118 *r
->out
.info
= NULL
;
8120 switch (r
->in
.level
) {
8122 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8126 return WERR_UNKNOWN_LEVEL
;
8129 if (!W_ERROR_IS_OK(result
)) {
8133 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8134 spoolss_EnumPrintProcessors
,
8135 *r
->out
.info
, r
->in
.level
,
8137 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8138 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8140 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8143 /****************************************************************************
8144 fill_printprocdatatype1
8145 ****************************************************************************/
8147 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8148 struct spoolss_PrintProcDataTypesInfo1
*r
,
8149 const char *name_array
)
8151 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8152 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8157 /****************************************************************************
8158 enumprintprocdatatypes level 1.
8159 ****************************************************************************/
8161 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8162 union spoolss_PrintProcDataTypesInfo
**info_p
,
8166 union spoolss_PrintProcDataTypesInfo
*info
;
8168 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8169 W_ERROR_HAVE_NO_MEMORY(info
);
8173 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8174 if (!W_ERROR_IS_OK(result
)) {
8179 if (!W_ERROR_IS_OK(result
)) {
8190 /****************************************************************
8191 _spoolss_EnumPrintProcDataTypes
8192 ****************************************************************/
8194 WERROR
_spoolss_EnumPrintProcDataTypes(pipes_struct
*p
,
8195 struct spoolss_EnumPrintProcDataTypes
*r
)
8199 /* that's an [in out] buffer */
8201 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8202 return WERR_INVALID_PARAM
;
8205 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8209 *r
->out
.info
= NULL
;
8211 switch (r
->in
.level
) {
8213 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8217 return WERR_UNKNOWN_LEVEL
;
8220 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8221 spoolss_EnumPrintProcDataTypes
,
8222 *r
->out
.info
, r
->in
.level
,
8224 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8225 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8227 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8230 /****************************************************************************
8232 ****************************************************************************/
8234 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8235 struct spoolss_MonitorInfo1
*r
,
8236 const char *monitor_name
)
8238 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8239 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8244 /****************************************************************************
8246 ****************************************************************************/
8248 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8249 struct spoolss_MonitorInfo2
*r
,
8250 const char *monitor_name
,
8251 const char *environment
,
8252 const char *dll_name
)
8254 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8255 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8256 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8257 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8258 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8259 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8264 /****************************************************************************
8265 enumprintmonitors level 1.
8266 ****************************************************************************/
8268 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8269 union spoolss_MonitorInfo
**info_p
,
8272 union spoolss_MonitorInfo
*info
;
8273 WERROR result
= WERR_OK
;
8275 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8276 W_ERROR_HAVE_NO_MEMORY(info
);
8280 result
= fill_monitor_1(info
, &info
[0].info1
,
8282 if (!W_ERROR_IS_OK(result
)) {
8286 result
= fill_monitor_1(info
, &info
[1].info1
,
8288 if (!W_ERROR_IS_OK(result
)) {
8293 if (!W_ERROR_IS_OK(result
)) {
8304 /****************************************************************************
8305 enumprintmonitors level 2.
8306 ****************************************************************************/
8308 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
8309 union spoolss_MonitorInfo
**info_p
,
8312 union spoolss_MonitorInfo
*info
;
8313 WERROR result
= WERR_OK
;
8315 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8316 W_ERROR_HAVE_NO_MEMORY(info
);
8320 result
= fill_monitor_2(info
, &info
[0].info2
,
8322 "Windows NT X86", /* FIXME */
8324 if (!W_ERROR_IS_OK(result
)) {
8328 result
= fill_monitor_2(info
, &info
[1].info2
,
8330 "Windows NT X86", /* FIXME */
8332 if (!W_ERROR_IS_OK(result
)) {
8337 if (!W_ERROR_IS_OK(result
)) {
8348 /****************************************************************
8349 _spoolss_EnumMonitors
8350 ****************************************************************/
8352 WERROR
_spoolss_EnumMonitors(pipes_struct
*p
,
8353 struct spoolss_EnumMonitors
*r
)
8357 /* that's an [in out] buffer */
8359 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8360 return WERR_INVALID_PARAM
;
8363 DEBUG(5,("_spoolss_EnumMonitors\n"));
8366 * Enumerate the print monitors ...
8368 * Just reply with "Local Port", to keep NT happy
8369 * and I can use my nice printer checker.
8374 *r
->out
.info
= NULL
;
8376 switch (r
->in
.level
) {
8378 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
8382 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
8386 return WERR_UNKNOWN_LEVEL
;
8389 if (!W_ERROR_IS_OK(result
)) {
8393 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8394 spoolss_EnumMonitors
,
8395 *r
->out
.info
, r
->in
.level
,
8397 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8398 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8400 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8403 /****************************************************************************
8404 ****************************************************************************/
8406 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
8407 const print_queue_struct
*queue
,
8408 int count
, int snum
,
8409 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8411 struct spoolss_JobInfo1
*r
)
8416 for (i
=0; i
<count
; i
++) {
8417 if (queue
[i
].job
== (int)jobid
) {
8423 if (found
== false) {
8424 /* NT treats not found as bad param... yet another bad choice */
8425 return WERR_INVALID_PARAM
;
8428 return fill_job_info1(mem_ctx
,
8436 /****************************************************************************
8437 ****************************************************************************/
8439 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
8440 const print_queue_struct
*queue
,
8441 int count
, int snum
,
8442 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8444 struct spoolss_JobInfo2
*r
)
8448 struct spoolss_DeviceMode
*devmode
;
8449 NT_DEVICEMODE
*nt_devmode
;
8452 for (i
=0; i
<count
; i
++) {
8453 if (queue
[i
].job
== (int)jobid
) {
8459 if (found
== false) {
8460 /* NT treats not found as bad param... yet another bad
8462 return WERR_INVALID_PARAM
;
8466 * if the print job does not have a DEVMODE associated with it,
8467 * just use the one for the printer. A NULL devicemode is not
8468 * a failure condition
8471 nt_devmode
= print_job_devmode(lp_const_servicename(snum
), jobid
);
8473 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
8474 W_ERROR_HAVE_NO_MEMORY(devmode
);
8475 result
= convert_nt_devicemode(devmode
, devmode
, nt_devmode
);
8476 if (!W_ERROR_IS_OK(result
)) {
8480 devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
8481 W_ERROR_HAVE_NO_MEMORY(devmode
);
8484 return fill_job_info2(mem_ctx
,
8493 /****************************************************************
8495 ****************************************************************/
8497 WERROR
_spoolss_GetJob(pipes_struct
*p
,
8498 struct spoolss_GetJob
*r
)
8500 WERROR result
= WERR_OK
;
8501 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8504 print_queue_struct
*queue
= NULL
;
8505 print_status_struct prt_status
;
8507 /* that's an [in out] buffer */
8509 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8510 return WERR_INVALID_PARAM
;
8513 DEBUG(5,("_spoolss_GetJob\n"));
8517 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8521 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8522 if (!W_ERROR_IS_OK(result
)) {
8526 count
= print_queue_status(snum
, &queue
, &prt_status
);
8528 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8529 count
, prt_status
.status
, prt_status
.message
));
8531 switch (r
->in
.level
) {
8533 result
= getjob_level_1(p
->mem_ctx
,
8534 queue
, count
, snum
, ntprinter
,
8535 r
->in
.job_id
, &r
->out
.info
->info1
);
8538 result
= getjob_level_2(p
->mem_ctx
,
8539 queue
, count
, snum
, ntprinter
,
8540 r
->in
.job_id
, &r
->out
.info
->info2
);
8543 result
= WERR_UNKNOWN_LEVEL
;
8548 free_a_printer(&ntprinter
, 2);
8550 if (!W_ERROR_IS_OK(result
)) {
8551 TALLOC_FREE(r
->out
.info
);
8555 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, r
->out
.info
,
8557 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8559 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8562 /****************************************************************
8563 _spoolss_GetPrinterDataEx
8564 ****************************************************************/
8566 WERROR
_spoolss_GetPrinterDataEx(pipes_struct
*p
,
8567 struct spoolss_GetPrinterDataEx
*r
)
8570 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8571 struct regval_blob
*val
= NULL
;
8572 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8574 WERROR result
= WERR_OK
;
8577 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8579 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8580 r
->in
.key_name
, r
->in
.value_name
));
8582 /* in case of problem, return some default values */
8585 *r
->out
.type
= REG_NONE
;
8588 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8589 OUR_HANDLE(r
->in
.handle
)));
8590 result
= WERR_BADFID
;
8594 /* Is the handle to a printer or to the server? */
8596 if (Printer
->printer_type
== SPLHND_SERVER
) {
8598 union spoolss_PrinterData data
;
8600 result
= getprinterdata_printer_server(p
->mem_ctx
,
8604 if (!W_ERROR_IS_OK(result
)) {
8608 result
= push_spoolss_PrinterData(p
->mem_ctx
, &blob
,
8609 *r
->out
.type
, &data
);
8610 if (!W_ERROR_IS_OK(result
)) {
8614 *r
->out
.needed
= blob
.length
;
8616 if (r
->in
.offered
>= *r
->out
.needed
) {
8617 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
8620 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8623 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8624 result
= WERR_BADFID
;
8628 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8629 if (!W_ERROR_IS_OK(result
)) {
8633 /* check to see if the keyname is valid */
8634 if (!strlen(r
->in
.key_name
)) {
8635 result
= WERR_INVALID_PARAM
;
8639 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8641 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
8642 strequal(r
->in
.value_name
, "ChangeId")) {
8643 *r
->out
.type
= REG_DWORD
;
8645 if (r
->in
.offered
>= *r
->out
.needed
) {
8646 SIVAL(r
->out
.data
, 0, printer
->info_2
->changeid
);
8652 if (lookup_printerkey(printer
->info_2
->data
, r
->in
.key_name
) == -1) {
8653 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8654 "Invalid keyname [%s]\n", r
->in
.key_name
));
8655 result
= WERR_BADFILE
;
8659 val
= get_printer_data(printer
->info_2
,
8660 r
->in
.key_name
, r
->in
.value_name
);
8662 result
= WERR_BADFILE
;
8666 *r
->out
.needed
= regval_size(val
);
8667 *r
->out
.type
= regval_type(val
);
8669 if (r
->in
.offered
>= *r
->out
.needed
) {
8670 memcpy(r
->out
.data
, regval_data_p(val
), regval_size(val
));
8674 free_a_printer(&printer
, 2);
8677 if (!W_ERROR_IS_OK(result
)) {
8681 *r
->out
.type
= SPOOLSS_BUFFER_OK(*r
->out
.type
, REG_NONE
);
8682 r
->out
.data
= SPOOLSS_BUFFER_OK(r
->out
.data
, r
->out
.data
);
8684 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8687 /****************************************************************
8688 _spoolss_SetPrinterDataEx
8689 ****************************************************************/
8691 WERROR
_spoolss_SetPrinterDataEx(pipes_struct
*p
,
8692 struct spoolss_SetPrinterDataEx
*r
)
8694 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8696 WERROR result
= WERR_OK
;
8697 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8700 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8702 /* From MSDN documentation of SetPrinterDataEx: pass request to
8703 SetPrinterData if key is "PrinterDriverData" */
8706 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8707 OUR_HANDLE(r
->in
.handle
)));
8711 if (Printer
->printer_type
== SPLHND_SERVER
) {
8712 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8713 "Not implemented for server handles yet\n"));
8714 return WERR_INVALID_PARAM
;
8717 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8722 * Access check : NT returns "access denied" if you make a
8723 * SetPrinterData call without the necessary privildge.
8724 * we were originally returning OK if nothing changed
8725 * which made Win2k issue **a lot** of SetPrinterData
8726 * when connecting to a printer --jerry
8729 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8730 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8731 "change denied by handle access permissions\n"));
8732 return WERR_ACCESS_DENIED
;
8735 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8736 if (!W_ERROR_IS_OK(result
)) {
8740 /* check for OID in valuename */
8742 oid_string
= strchr(r
->in
.value_name
, ',');
8748 /* save the registry data */
8750 result
= set_printer_dataex(printer
, r
->in
.key_name
, r
->in
.value_name
,
8751 r
->in
.type
, r
->in
.data
, r
->in
.offered
);
8753 if (W_ERROR_IS_OK(result
)) {
8754 /* save the OID if one was specified */
8756 char *str
= talloc_asprintf(p
->mem_ctx
, "%s\\%s",
8757 r
->in
.key_name
, SPOOL_OID_KEY
);
8759 result
= WERR_NOMEM
;
8764 * I'm not checking the status here on purpose. Don't know
8765 * if this is right, but I'm returning the status from the
8766 * previous set_printer_dataex() call. I have no idea if
8767 * this is right. --jerry
8770 set_printer_dataex(printer
, str
, r
->in
.value_name
,
8771 REG_SZ
, (uint8_t *)oid_string
,
8772 strlen(oid_string
)+1);
8775 result
= mod_a_printer(printer
, 2);
8779 free_a_printer(&printer
, 2);
8784 /****************************************************************
8785 _spoolss_DeletePrinterDataEx
8786 ****************************************************************/
8788 WERROR
_spoolss_DeletePrinterDataEx(pipes_struct
*p
,
8789 struct spoolss_DeletePrinterDataEx
*r
)
8791 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8793 WERROR status
= WERR_OK
;
8794 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8796 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8799 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8800 "Invalid handle (%s:%u:%u).\n",
8801 OUR_HANDLE(r
->in
.handle
)));
8805 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8808 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8809 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8810 "printer properties change denied by handle\n"));
8811 return WERR_ACCESS_DENIED
;
8814 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
8818 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8819 if (!W_ERROR_IS_OK(status
))
8822 status
= delete_printer_dataex( printer
, r
->in
.key_name
, r
->in
.value_name
);
8824 if ( W_ERROR_IS_OK(status
) )
8825 mod_a_printer( printer
, 2 );
8827 free_a_printer(&printer
, 2);
8832 /****************************************************************
8833 _spoolss_EnumPrinterKey
8834 ****************************************************************/
8836 WERROR
_spoolss_EnumPrinterKey(pipes_struct
*p
,
8837 struct spoolss_EnumPrinterKey
*r
)
8839 fstring
*keynames
= NULL
;
8841 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8842 NT_PRINTER_DATA
*data
;
8843 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8845 WERROR result
= WERR_BADFILE
;
8847 const char **array
= NULL
;
8850 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8853 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8854 OUR_HANDLE(r
->in
.handle
)));
8858 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8862 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8863 if (!W_ERROR_IS_OK(result
)) {
8867 /* get the list of subkey names */
8869 data
= printer
->info_2
->data
;
8871 num_keys
= get_printer_subkeys(data
, r
->in
.key_name
, &keynames
);
8872 if (num_keys
== -1) {
8873 result
= WERR_BADFILE
;
8877 array
= talloc_zero_array(r
->out
.key_buffer
, const char *, num_keys
+ 2);
8879 result
= WERR_NOMEM
;
8884 array
[0] = talloc_strdup(array
, "");
8886 result
= WERR_NOMEM
;
8891 for (i
=0; i
< num_keys
; i
++) {
8893 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8896 array
[i
] = talloc_strdup(array
, keynames
[i
]);
8898 result
= WERR_NOMEM
;
8903 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
8904 result
= WERR_NOMEM
;
8908 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
8909 *r
->out
.needed
= blob
.length
;
8911 if (r
->in
.offered
< *r
->out
.needed
) {
8912 result
= WERR_MORE_DATA
;
8915 r
->out
.key_buffer
->string_array
= array
;
8919 if (!W_ERROR_IS_OK(result
)) {
8921 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
8926 free_a_printer(&printer
, 2);
8927 SAFE_FREE(keynames
);
8932 /****************************************************************
8933 _spoolss_DeletePrinterKey
8934 ****************************************************************/
8936 WERROR
_spoolss_DeletePrinterKey(pipes_struct
*p
,
8937 struct spoolss_DeletePrinterKey
*r
)
8939 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8940 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8944 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8947 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8948 OUR_HANDLE(r
->in
.handle
)));
8952 /* if keyname == NULL, return error */
8954 if ( !r
->in
.key_name
)
8955 return WERR_INVALID_PARAM
;
8957 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8960 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8961 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8962 "printer properties change denied by handle\n"));
8963 return WERR_ACCESS_DENIED
;
8966 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8967 if (!W_ERROR_IS_OK(status
))
8970 /* delete the key and all subneys */
8972 status
= delete_all_printer_data( printer
->info_2
, r
->in
.key_name
);
8974 if ( W_ERROR_IS_OK(status
) )
8975 status
= mod_a_printer(printer
, 2);
8977 free_a_printer( &printer
, 2 );
8982 /****************************************************************
8983 ****************************************************************/
8985 static WERROR
registry_value_to_printer_enum_value(TALLOC_CTX
*mem_ctx
,
8986 struct regval_blob
*v
,
8987 struct spoolss_PrinterEnumValues
*r
)
8989 r
->data
= TALLOC_ZERO_P(mem_ctx
, DATA_BLOB
);
8990 W_ERROR_HAVE_NO_MEMORY(r
->data
);
8992 r
->value_name
= talloc_strdup(mem_ctx
, regval_name(v
));
8993 W_ERROR_HAVE_NO_MEMORY(r
->value_name
);
8995 r
->value_name_len
= strlen_m_term(regval_name(v
)) * 2;
8997 r
->type
= regval_type(v
);
8998 r
->data_length
= regval_size(v
);
9000 if (r
->data_length
) {
9001 *r
->data
= data_blob_talloc(r
->data
, regval_data_p(v
), regval_size(v
));
9007 /****************************************************************
9008 _spoolss_EnumPrinterDataEx
9009 ****************************************************************/
9011 WERROR
_spoolss_EnumPrinterDataEx(pipes_struct
*p
,
9012 struct spoolss_EnumPrinterDataEx
*r
)
9015 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9016 struct spoolss_PrinterEnumValues
*info
= NULL
;
9017 NT_PRINTER_DATA
*p_data
;
9018 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9024 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9028 *r
->out
.info
= NULL
;
9031 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9032 OUR_HANDLE(r
->in
.handle
)));
9037 * first check for a keyname of NULL or "". Win2k seems to send
9038 * this a lot and we should send back WERR_INVALID_PARAM
9039 * no need to spend time looking up the printer in this case.
9043 if (!strlen(r
->in
.key_name
)) {
9044 result
= WERR_INVALID_PARAM
;
9048 /* get the printer off of disk */
9050 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9054 ZERO_STRUCT(printer
);
9055 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9056 if (!W_ERROR_IS_OK(result
)) {
9060 /* now look for a match on the key name */
9062 p_data
= printer
->info_2
->data
;
9064 key_index
= lookup_printerkey(p_data
, r
->in
.key_name
);
9065 if (key_index
== -1) {
9066 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9068 result
= WERR_INVALID_PARAM
;
9072 /* allocate the memory for the array of pointers -- if necessary */
9074 count
= regval_ctr_numvals(p_data
->keys
[key_index
].values
);
9076 result
= WERR_OK
; /* ??? */
9080 info
= TALLOC_ZERO_ARRAY(p
->mem_ctx
,
9081 struct spoolss_PrinterEnumValues
,
9084 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9085 result
= WERR_NOMEM
;
9090 * loop through all params and build the array to pass
9091 * back to the client
9094 for (i
=0; i
< count
; i
++) {
9096 struct regval_blob
*val
;
9098 /* lookup the registry value */
9100 val
= regval_ctr_specific_value(p_data
->keys
[key_index
].values
, i
);
9102 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
)));
9106 result
= registry_value_to_printer_enum_value(info
, val
, &info
[i
]);
9107 if (!W_ERROR_IS_OK(result
)) {
9112 #if 0 /* FIXME - gd */
9113 /* housekeeping information in the reply */
9115 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9116 * the hand marshalled container size is a multiple
9117 * of 4 bytes for RPC alignment.
9121 needed
+= 4-(needed
% 4);
9124 *r
->out
.count
= count
;
9125 *r
->out
.info
= info
;
9130 free_a_printer(&printer
, 2);
9133 if (!W_ERROR_IS_OK(result
)) {
9137 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
9138 spoolss_EnumPrinterDataEx
,
9141 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9142 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
9144 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9147 /****************************************************************************
9148 ****************************************************************************/
9150 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
9151 const char *servername
,
9152 const char *environment
,
9153 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
9158 werr
= compose_spoolss_server_path(mem_ctx
,
9161 SPOOLSS_PRTPROCS_PATH
,
9163 if (!W_ERROR_IS_OK(werr
)) {
9167 DEBUG(4,("print processor directory: [%s]\n", path
));
9169 r
->directory_name
= path
;
9174 /****************************************************************
9175 _spoolss_GetPrintProcessorDirectory
9176 ****************************************************************/
9178 WERROR
_spoolss_GetPrintProcessorDirectory(pipes_struct
*p
,
9179 struct spoolss_GetPrintProcessorDirectory
*r
)
9183 /* that's an [in out] buffer */
9185 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9186 return WERR_INVALID_PARAM
;
9189 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9194 /* r->in.level is ignored */
9196 /* We always should reply with a local print processor directory so that
9197 * users are not forced to have a [prnproc$] share on the Samba spoolss
9198 * server - Guenther */
9200 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9201 NULL
, /* r->in.server */
9203 &r
->out
.info
->info1
);
9204 if (!W_ERROR_IS_OK(result
)) {
9205 TALLOC_FREE(r
->out
.info
);
9209 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
,
9210 r
->out
.info
, r
->in
.level
);
9211 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9213 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9216 /*******************************************************************
9217 ********************************************************************/
9219 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9220 const char *dllname
)
9222 enum ndr_err_code ndr_err
;
9223 struct spoolss_MonitorUi ui
;
9225 ui
.dll_name
= dllname
;
9227 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, &ui
,
9228 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9229 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9230 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9232 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9235 /*******************************************************************
9236 Streams the monitor UI DLL name in UNICODE
9237 *******************************************************************/
9239 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9240 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9241 DATA_BLOB
*out
, uint32_t *needed
)
9243 const char *dllname
= "tcpmonui.dll";
9245 *needed
= (strlen(dllname
)+1) * 2;
9247 if (out
->length
< *needed
) {
9248 return WERR_INSUFFICIENT_BUFFER
;
9251 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9258 /*******************************************************************
9259 ********************************************************************/
9261 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9262 struct spoolss_PortData1
*port1
,
9263 const DATA_BLOB
*buf
)
9265 enum ndr_err_code ndr_err
;
9266 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port1
,
9267 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9268 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9269 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9271 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9274 /*******************************************************************
9275 ********************************************************************/
9277 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9278 struct spoolss_PortData2
*port2
,
9279 const DATA_BLOB
*buf
)
9281 enum ndr_err_code ndr_err
;
9282 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port2
,
9283 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9284 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9285 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9287 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9290 /*******************************************************************
9291 Create a new TCP/IP port
9292 *******************************************************************/
9294 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9295 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9296 DATA_BLOB
*out
, uint32_t *needed
)
9298 struct spoolss_PortData1 port1
;
9299 struct spoolss_PortData2 port2
;
9300 char *device_uri
= NULL
;
9303 const char *portname
;
9304 const char *hostaddress
;
9306 uint32_t port_number
;
9309 /* peek for spoolss_PortData version */
9311 if (!in
|| (in
->length
< (128 + 4))) {
9312 return WERR_GENERAL_FAILURE
;
9315 version
= IVAL(in
->data
, 128);
9321 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9325 portname
= port1
.portname
;
9326 hostaddress
= port1
.hostaddress
;
9327 queue
= port1
.queue
;
9328 protocol
= port1
.protocol
;
9329 port_number
= port1
.port_number
;
9335 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9339 portname
= port2
.portname
;
9340 hostaddress
= port2
.hostaddress
;
9341 queue
= port2
.queue
;
9342 protocol
= port2
.protocol
;
9343 port_number
= port2
.port_number
;
9347 DEBUG(1,("xcvtcp_addport: "
9348 "unknown version of port_data: %d\n", version
));
9349 return WERR_UNKNOWN_PORT
;
9352 /* create the device URI and call the add_port_hook() */
9355 case PROTOCOL_RAWTCP_TYPE
:
9356 device_uri
= talloc_asprintf(mem_ctx
,
9357 "socket://%s:%d/", hostaddress
,
9361 case PROTOCOL_LPR_TYPE
:
9362 device_uri
= talloc_asprintf(mem_ctx
,
9363 "lpr://%s/%s", hostaddress
, queue
);
9367 return WERR_UNKNOWN_PORT
;
9374 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
9377 /*******************************************************************
9378 *******************************************************************/
9380 struct xcv_api_table xcvtcp_cmds
[] = {
9381 { "MonitorUI", xcvtcp_monitorui
},
9382 { "AddPort", xcvtcp_addport
},
9386 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
9387 NT_USER_TOKEN
*token
, const char *command
,
9394 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9396 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9397 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9398 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9401 return WERR_BADFUNC
;
9404 /*******************************************************************
9405 *******************************************************************/
9406 #if 0 /* don't support management using the "Local Port" monitor */
9408 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
9409 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9410 DATA_BLOB
*out
, uint32_t *needed
)
9412 const char *dllname
= "localui.dll";
9414 *needed
= (strlen(dllname
)+1) * 2;
9416 if (out
->length
< *needed
) {
9417 return WERR_INSUFFICIENT_BUFFER
;
9420 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9427 /*******************************************************************
9428 *******************************************************************/
9430 struct xcv_api_table xcvlocal_cmds
[] = {
9431 { "MonitorUI", xcvlocal_monitorui
},
9435 struct xcv_api_table xcvlocal_cmds
[] = {
9442 /*******************************************************************
9443 *******************************************************************/
9445 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
9446 NT_USER_TOKEN
*token
, const char *command
,
9447 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
9452 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9454 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9455 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9456 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9458 return WERR_BADFUNC
;
9461 /****************************************************************
9463 ****************************************************************/
9465 WERROR
_spoolss_XcvData(pipes_struct
*p
,
9466 struct spoolss_XcvData
*r
)
9468 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9469 DATA_BLOB out_data
= data_blob_null
;
9473 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9474 OUR_HANDLE(r
->in
.handle
)));
9478 /* Has to be a handle to the TCP/IP port monitor */
9480 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9481 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9485 /* requires administrative access to the server */
9487 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9488 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9489 return WERR_ACCESS_DENIED
;
9492 /* Allocate the outgoing buffer */
9494 if (r
->in
.out_data_size
) {
9495 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
9496 if (out_data
.data
== NULL
) {
9501 switch ( Printer
->printer_type
) {
9502 case SPLHND_PORTMON_TCP
:
9503 werror
= process_xcvtcp_command(p
->mem_ctx
,
9504 p
->server_info
->ptok
,
9505 r
->in
.function_name
,
9506 &r
->in
.in_data
, &out_data
,
9509 case SPLHND_PORTMON_LOCAL
:
9510 werror
= process_xcvlocal_command(p
->mem_ctx
,
9511 p
->server_info
->ptok
,
9512 r
->in
.function_name
,
9513 &r
->in
.in_data
, &out_data
,
9517 werror
= WERR_INVALID_PRINT_MONITOR
;
9520 if (!W_ERROR_IS_OK(werror
)) {
9524 *r
->out
.status_code
= 0;
9526 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
9527 memcpy(r
->out
.out_data
, out_data
.data
,
9528 MIN(r
->in
.out_data_size
, out_data
.length
));
9534 /****************************************************************
9535 _spoolss_AddPrintProcessor
9536 ****************************************************************/
9538 WERROR
_spoolss_AddPrintProcessor(pipes_struct
*p
,
9539 struct spoolss_AddPrintProcessor
*r
)
9541 /* for now, just indicate success and ignore the add. We'll
9542 automatically set the winprint processor for printer
9543 entries later. Used to debug the LexMark Optra S 1855 PCL
9549 /****************************************************************
9551 ****************************************************************/
9553 WERROR
_spoolss_AddPort(pipes_struct
*p
,
9554 struct spoolss_AddPort
*r
)
9556 /* do what w2k3 does */
9558 return WERR_NOT_SUPPORTED
;
9561 /****************************************************************
9562 _spoolss_GetPrinterDriver
9563 ****************************************************************/
9565 WERROR
_spoolss_GetPrinterDriver(pipes_struct
*p
,
9566 struct spoolss_GetPrinterDriver
*r
)
9568 p
->rng_fault_state
= true;
9569 return WERR_NOT_SUPPORTED
;
9572 /****************************************************************
9573 _spoolss_ReadPrinter
9574 ****************************************************************/
9576 WERROR
_spoolss_ReadPrinter(pipes_struct
*p
,
9577 struct spoolss_ReadPrinter
*r
)
9579 p
->rng_fault_state
= true;
9580 return WERR_NOT_SUPPORTED
;
9583 /****************************************************************
9584 _spoolss_WaitForPrinterChange
9585 ****************************************************************/
9587 WERROR
_spoolss_WaitForPrinterChange(pipes_struct
*p
,
9588 struct spoolss_WaitForPrinterChange
*r
)
9590 p
->rng_fault_state
= true;
9591 return WERR_NOT_SUPPORTED
;
9594 /****************************************************************
9595 _spoolss_ConfigurePort
9596 ****************************************************************/
9598 WERROR
_spoolss_ConfigurePort(pipes_struct
*p
,
9599 struct spoolss_ConfigurePort
*r
)
9601 p
->rng_fault_state
= true;
9602 return WERR_NOT_SUPPORTED
;
9605 /****************************************************************
9607 ****************************************************************/
9609 WERROR
_spoolss_DeletePort(pipes_struct
*p
,
9610 struct spoolss_DeletePort
*r
)
9612 p
->rng_fault_state
= true;
9613 return WERR_NOT_SUPPORTED
;
9616 /****************************************************************
9617 _spoolss_CreatePrinterIC
9618 ****************************************************************/
9620 WERROR
_spoolss_CreatePrinterIC(pipes_struct
*p
,
9621 struct spoolss_CreatePrinterIC
*r
)
9623 p
->rng_fault_state
= true;
9624 return WERR_NOT_SUPPORTED
;
9627 /****************************************************************
9628 _spoolss_PlayGDIScriptOnPrinterIC
9629 ****************************************************************/
9631 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(pipes_struct
*p
,
9632 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
9634 p
->rng_fault_state
= true;
9635 return WERR_NOT_SUPPORTED
;
9638 /****************************************************************
9639 _spoolss_DeletePrinterIC
9640 ****************************************************************/
9642 WERROR
_spoolss_DeletePrinterIC(pipes_struct
*p
,
9643 struct spoolss_DeletePrinterIC
*r
)
9645 p
->rng_fault_state
= true;
9646 return WERR_NOT_SUPPORTED
;
9649 /****************************************************************
9650 _spoolss_AddPrinterConnection
9651 ****************************************************************/
9653 WERROR
_spoolss_AddPrinterConnection(pipes_struct
*p
,
9654 struct spoolss_AddPrinterConnection
*r
)
9656 p
->rng_fault_state
= true;
9657 return WERR_NOT_SUPPORTED
;
9660 /****************************************************************
9661 _spoolss_DeletePrinterConnection
9662 ****************************************************************/
9664 WERROR
_spoolss_DeletePrinterConnection(pipes_struct
*p
,
9665 struct spoolss_DeletePrinterConnection
*r
)
9667 p
->rng_fault_state
= true;
9668 return WERR_NOT_SUPPORTED
;
9671 /****************************************************************
9672 _spoolss_PrinterMessageBox
9673 ****************************************************************/
9675 WERROR
_spoolss_PrinterMessageBox(pipes_struct
*p
,
9676 struct spoolss_PrinterMessageBox
*r
)
9678 p
->rng_fault_state
= true;
9679 return WERR_NOT_SUPPORTED
;
9682 /****************************************************************
9684 ****************************************************************/
9686 WERROR
_spoolss_AddMonitor(pipes_struct
*p
,
9687 struct spoolss_AddMonitor
*r
)
9689 p
->rng_fault_state
= true;
9690 return WERR_NOT_SUPPORTED
;
9693 /****************************************************************
9694 _spoolss_DeleteMonitor
9695 ****************************************************************/
9697 WERROR
_spoolss_DeleteMonitor(pipes_struct
*p
,
9698 struct spoolss_DeleteMonitor
*r
)
9700 p
->rng_fault_state
= true;
9701 return WERR_NOT_SUPPORTED
;
9704 /****************************************************************
9705 _spoolss_DeletePrintProcessor
9706 ****************************************************************/
9708 WERROR
_spoolss_DeletePrintProcessor(pipes_struct
*p
,
9709 struct spoolss_DeletePrintProcessor
*r
)
9711 p
->rng_fault_state
= true;
9712 return WERR_NOT_SUPPORTED
;
9715 /****************************************************************
9716 _spoolss_AddPrintProvidor
9717 ****************************************************************/
9719 WERROR
_spoolss_AddPrintProvidor(pipes_struct
*p
,
9720 struct spoolss_AddPrintProvidor
*r
)
9722 p
->rng_fault_state
= true;
9723 return WERR_NOT_SUPPORTED
;
9726 /****************************************************************
9727 _spoolss_DeletePrintProvidor
9728 ****************************************************************/
9730 WERROR
_spoolss_DeletePrintProvidor(pipes_struct
*p
,
9731 struct spoolss_DeletePrintProvidor
*r
)
9733 p
->rng_fault_state
= true;
9734 return WERR_NOT_SUPPORTED
;
9737 /****************************************************************
9738 _spoolss_FindFirstPrinterChangeNotification
9739 ****************************************************************/
9741 WERROR
_spoolss_FindFirstPrinterChangeNotification(pipes_struct
*p
,
9742 struct spoolss_FindFirstPrinterChangeNotification
*r
)
9744 p
->rng_fault_state
= true;
9745 return WERR_NOT_SUPPORTED
;
9748 /****************************************************************
9749 _spoolss_FindNextPrinterChangeNotification
9750 ****************************************************************/
9752 WERROR
_spoolss_FindNextPrinterChangeNotification(pipes_struct
*p
,
9753 struct spoolss_FindNextPrinterChangeNotification
*r
)
9755 p
->rng_fault_state
= true;
9756 return WERR_NOT_SUPPORTED
;
9759 /****************************************************************
9760 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9761 ****************************************************************/
9763 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct
*p
,
9764 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
9766 p
->rng_fault_state
= true;
9767 return WERR_NOT_SUPPORTED
;
9770 /****************************************************************
9771 _spoolss_ReplyOpenPrinter
9772 ****************************************************************/
9774 WERROR
_spoolss_ReplyOpenPrinter(pipes_struct
*p
,
9775 struct spoolss_ReplyOpenPrinter
*r
)
9777 p
->rng_fault_state
= true;
9778 return WERR_NOT_SUPPORTED
;
9781 /****************************************************************
9782 _spoolss_RouterReplyPrinter
9783 ****************************************************************/
9785 WERROR
_spoolss_RouterReplyPrinter(pipes_struct
*p
,
9786 struct spoolss_RouterReplyPrinter
*r
)
9788 p
->rng_fault_state
= true;
9789 return WERR_NOT_SUPPORTED
;
9792 /****************************************************************
9793 _spoolss_ReplyClosePrinter
9794 ****************************************************************/
9796 WERROR
_spoolss_ReplyClosePrinter(pipes_struct
*p
,
9797 struct spoolss_ReplyClosePrinter
*r
)
9799 p
->rng_fault_state
= true;
9800 return WERR_NOT_SUPPORTED
;
9803 /****************************************************************
9805 ****************************************************************/
9807 WERROR
_spoolss_AddPortEx(pipes_struct
*p
,
9808 struct spoolss_AddPortEx
*r
)
9810 p
->rng_fault_state
= true;
9811 return WERR_NOT_SUPPORTED
;
9814 /****************************************************************
9815 _spoolss_RouterFindFirstPrinterChangeNotification
9816 ****************************************************************/
9818 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct
*p
,
9819 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
9821 p
->rng_fault_state
= true;
9822 return WERR_NOT_SUPPORTED
;
9825 /****************************************************************
9826 _spoolss_SpoolerInit
9827 ****************************************************************/
9829 WERROR
_spoolss_SpoolerInit(pipes_struct
*p
,
9830 struct spoolss_SpoolerInit
*r
)
9832 p
->rng_fault_state
= true;
9833 return WERR_NOT_SUPPORTED
;
9836 /****************************************************************
9837 _spoolss_ResetPrinterEx
9838 ****************************************************************/
9840 WERROR
_spoolss_ResetPrinterEx(pipes_struct
*p
,
9841 struct spoolss_ResetPrinterEx
*r
)
9843 p
->rng_fault_state
= true;
9844 return WERR_NOT_SUPPORTED
;
9847 /****************************************************************
9848 _spoolss_RouterReplyPrinterEx
9849 ****************************************************************/
9851 WERROR
_spoolss_RouterReplyPrinterEx(pipes_struct
*p
,
9852 struct spoolss_RouterReplyPrinterEx
*r
)
9854 p
->rng_fault_state
= true;
9855 return WERR_NOT_SUPPORTED
;
9858 /****************************************************************
9860 ****************************************************************/
9862 WERROR
_spoolss_44(pipes_struct
*p
,
9863 struct spoolss_44
*r
)
9865 p
->rng_fault_state
= true;
9866 return WERR_NOT_SUPPORTED
;
9869 /****************************************************************
9871 ****************************************************************/
9873 WERROR
_spoolss_47(pipes_struct
*p
,
9874 struct spoolss_47
*r
)
9876 p
->rng_fault_state
= true;
9877 return WERR_NOT_SUPPORTED
;
9880 /****************************************************************
9882 ****************************************************************/
9884 WERROR
_spoolss_4a(pipes_struct
*p
,
9885 struct spoolss_4a
*r
)
9887 p
->rng_fault_state
= true;
9888 return WERR_NOT_SUPPORTED
;
9891 /****************************************************************
9893 ****************************************************************/
9895 WERROR
_spoolss_4b(pipes_struct
*p
,
9896 struct spoolss_4b
*r
)
9898 p
->rng_fault_state
= true;
9899 return WERR_NOT_SUPPORTED
;
9902 /****************************************************************
9904 ****************************************************************/
9906 WERROR
_spoolss_4c(pipes_struct
*p
,
9907 struct spoolss_4c
*r
)
9909 p
->rng_fault_state
= true;
9910 return WERR_NOT_SUPPORTED
;
9913 /****************************************************************
9915 ****************************************************************/
9917 WERROR
_spoolss_53(pipes_struct
*p
,
9918 struct spoolss_53
*r
)
9920 p
->rng_fault_state
= true;
9921 return WERR_NOT_SUPPORTED
;
9924 /****************************************************************
9926 ****************************************************************/
9928 WERROR
_spoolss_55(pipes_struct
*p
,
9929 struct spoolss_55
*r
)
9931 p
->rng_fault_state
= true;
9932 return WERR_NOT_SUPPORTED
;
9935 /****************************************************************
9937 ****************************************************************/
9939 WERROR
_spoolss_56(pipes_struct
*p
,
9940 struct spoolss_56
*r
)
9942 p
->rng_fault_state
= true;
9943 return WERR_NOT_SUPPORTED
;
9946 /****************************************************************
9948 ****************************************************************/
9950 WERROR
_spoolss_57(pipes_struct
*p
,
9951 struct spoolss_57
*r
)
9953 p
->rng_fault_state
= true;
9954 return WERR_NOT_SUPPORTED
;
9957 /****************************************************************
9959 ****************************************************************/
9961 WERROR
_spoolss_5a(pipes_struct
*p
,
9962 struct spoolss_5a
*r
)
9964 p
->rng_fault_state
= true;
9965 return WERR_NOT_SUPPORTED
;
9968 /****************************************************************
9970 ****************************************************************/
9972 WERROR
_spoolss_5b(pipes_struct
*p
,
9973 struct spoolss_5b
*r
)
9975 p
->rng_fault_state
= true;
9976 return WERR_NOT_SUPPORTED
;
9979 /****************************************************************
9981 ****************************************************************/
9983 WERROR
_spoolss_5c(pipes_struct
*p
,
9984 struct spoolss_5c
*r
)
9986 p
->rng_fault_state
= true;
9987 return WERR_NOT_SUPPORTED
;
9990 /****************************************************************
9992 ****************************************************************/
9994 WERROR
_spoolss_5d(pipes_struct
*p
,
9995 struct spoolss_5d
*r
)
9997 p
->rng_fault_state
= true;
9998 return WERR_NOT_SUPPORTED
;
10001 /****************************************************************
10003 ****************************************************************/
10005 WERROR
_spoolss_5e(pipes_struct
*p
,
10006 struct spoolss_5e
*r
)
10008 p
->rng_fault_state
= true;
10009 return WERR_NOT_SUPPORTED
;
10012 /****************************************************************
10014 ****************************************************************/
10016 WERROR
_spoolss_5f(pipes_struct
*p
,
10017 struct spoolss_5f
*r
)
10019 p
->rng_fault_state
= true;
10020 return WERR_NOT_SUPPORTED
;
10023 /****************************************************************
10025 ****************************************************************/
10027 WERROR
_spoolss_60(pipes_struct
*p
,
10028 struct spoolss_60
*r
)
10030 p
->rng_fault_state
= true;
10031 return WERR_NOT_SUPPORTED
;
10034 /****************************************************************
10036 ****************************************************************/
10038 WERROR
_spoolss_61(pipes_struct
*p
,
10039 struct spoolss_61
*r
)
10041 p
->rng_fault_state
= true;
10042 return WERR_NOT_SUPPORTED
;
10045 /****************************************************************
10047 ****************************************************************/
10049 WERROR
_spoolss_62(pipes_struct
*p
,
10050 struct spoolss_62
*r
)
10052 p
->rng_fault_state
= true;
10053 return WERR_NOT_SUPPORTED
;
10056 /****************************************************************
10058 ****************************************************************/
10060 WERROR
_spoolss_63(pipes_struct
*p
,
10061 struct spoolss_63
*r
)
10063 p
->rng_fault_state
= true;
10064 return WERR_NOT_SUPPORTED
;
10067 /****************************************************************
10069 ****************************************************************/
10071 WERROR
_spoolss_64(pipes_struct
*p
,
10072 struct spoolss_64
*r
)
10074 p
->rng_fault_state
= true;
10075 return WERR_NOT_SUPPORTED
;
10078 /****************************************************************
10080 ****************************************************************/
10082 WERROR
_spoolss_65(pipes_struct
*p
,
10083 struct spoolss_65
*r
)
10085 p
->rng_fault_state
= true;
10086 return WERR_NOT_SUPPORTED
;
10089 /****************************************************************
10090 _spoolss_GetCorePrinterDrivers
10091 ****************************************************************/
10093 WERROR
_spoolss_GetCorePrinterDrivers(pipes_struct
*p
,
10094 struct spoolss_GetCorePrinterDrivers
*r
)
10096 p
->rng_fault_state
= true;
10097 return WERR_NOT_SUPPORTED
;
10100 /****************************************************************
10102 ****************************************************************/
10104 WERROR
_spoolss_67(pipes_struct
*p
,
10105 struct spoolss_67
*r
)
10107 p
->rng_fault_state
= true;
10108 return WERR_NOT_SUPPORTED
;
10111 /****************************************************************
10112 _spoolss_GetPrinterDriverPackagePath
10113 ****************************************************************/
10115 WERROR
_spoolss_GetPrinterDriverPackagePath(pipes_struct
*p
,
10116 struct spoolss_GetPrinterDriverPackagePath
*r
)
10118 p
->rng_fault_state
= true;
10119 return WERR_NOT_SUPPORTED
;
10122 /****************************************************************
10124 ****************************************************************/
10126 WERROR
_spoolss_69(pipes_struct
*p
,
10127 struct spoolss_69
*r
)
10129 p
->rng_fault_state
= true;
10130 return WERR_NOT_SUPPORTED
;
10133 /****************************************************************
10135 ****************************************************************/
10137 WERROR
_spoolss_6a(pipes_struct
*p
,
10138 struct spoolss_6a
*r
)
10140 p
->rng_fault_state
= true;
10141 return WERR_NOT_SUPPORTED
;
10144 /****************************************************************
10146 ****************************************************************/
10148 WERROR
_spoolss_6b(pipes_struct
*p
,
10149 struct spoolss_6b
*r
)
10151 p
->rng_fault_state
= true;
10152 return WERR_NOT_SUPPORTED
;
10155 /****************************************************************
10157 ****************************************************************/
10159 WERROR
_spoolss_6c(pipes_struct
*p
,
10160 struct spoolss_6c
*r
)
10162 p
->rng_fault_state
= true;
10163 return WERR_NOT_SUPPORTED
;
10166 /****************************************************************
10168 ****************************************************************/
10170 WERROR
_spoolss_6d(pipes_struct
*p
,
10171 struct spoolss_6d
*r
)
10173 p
->rng_fault_state
= true;
10174 return WERR_NOT_SUPPORTED
;