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"
35 #include "registry/reg_objects.h"
37 /* macros stolen from s4 spoolss server */
38 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
39 ((info)?ndr_size_##fn(info, level, 0):0)
41 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
42 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
44 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
45 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
47 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
50 extern userdom_struct current_user_info
;
53 #define DBGC_CLASS DBGC_RPC_SRV
55 #ifndef MAX_OPEN_PRINTER_EXS
56 #define MAX_OPEN_PRINTER_EXS 50
59 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
61 static Printer_entry
*printers_list
;
63 typedef struct _counter_printer_0
{
64 struct _counter_printer_0
*next
;
65 struct _counter_printer_0
*prev
;
71 static counter_printer_0
*counter_list
;
73 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
74 static uint32_t smb_connections
= 0;
77 /* in printing/nt_printing.c */
79 extern struct standard_mapping printer_std_mapping
, printserver_std_mapping
;
81 /* API table for Xcv Monitor functions */
83 struct xcv_api_table
{
85 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, NT_USER_TOKEN
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
88 /********************************************************************
89 * Canonicalize servername.
90 ********************************************************************/
92 static const char *canon_servername(const char *servername
)
94 const char *pservername
= servername
;
95 while (*pservername
== '\\') {
101 /* translate between internal status numbers and NT status numbers */
102 static int nt_printj_status(int v
)
108 return JOB_STATUS_PAUSED
;
110 return JOB_STATUS_SPOOLING
;
112 return JOB_STATUS_PRINTING
;
114 return JOB_STATUS_ERROR
;
116 return JOB_STATUS_DELETING
;
118 return JOB_STATUS_OFFLINE
;
120 return JOB_STATUS_PAPEROUT
;
122 return JOB_STATUS_PRINTED
;
124 return JOB_STATUS_DELETED
;
126 return JOB_STATUS_BLOCKED_DEVQ
;
127 case LPQ_USER_INTERVENTION
:
128 return JOB_STATUS_USER_INTERVENTION
;
133 static int nt_printq_status(int v
)
137 return PRINTER_STATUS_PAUSED
;
146 /***************************************************************************
147 Disconnect from the client
148 ****************************************************************************/
150 static void srv_spoolss_replycloseprinter(int snum
, struct policy_handle
*handle
)
156 * Tell the specific printing tdb we no longer want messages for this printer
157 * by deregistering our PID.
160 if (!print_notify_deregister_pid(snum
))
161 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
163 /* weird if the test succeds !!! */
164 if (smb_connections
==0) {
165 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
169 status
= rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe
, talloc_tos(),
172 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
173 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
174 win_errstr(result
)));
176 /* if it's the last connection, deconnect the IPC$ share */
177 if (smb_connections
==1) {
179 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe
) );
180 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
182 messaging_deregister(smbd_messaging_context(),
183 MSG_PRINTER_NOTIFY2
, NULL
);
185 /* Tell the connections db we're no longer interested in
186 * printer notify messages. */
188 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY
);
194 /****************************************************************************
195 Functions to free a printer entry datastruct.
196 ****************************************************************************/
198 static int printer_entry_destructor(Printer_entry
*Printer
)
200 if (Printer
->notify
.client_connected
== true) {
203 if ( Printer
->printer_type
== SPLHND_SERVER
) {
205 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
206 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
207 snum
= print_queue_snum(Printer
->sharename
);
209 srv_spoolss_replycloseprinter(snum
,
210 &Printer
->notify
.client_hnd
);
214 Printer
->notify
.flags
=0;
215 Printer
->notify
.options
=0;
216 Printer
->notify
.localmachine
[0]='\0';
217 Printer
->notify
.printerlocal
=0;
218 TALLOC_FREE(Printer
->notify
.option
);
219 Printer
->notify
.client_connected
= false;
221 free_nt_devicemode( &Printer
->nt_devmode
);
222 free_a_printer( &Printer
->printer_info
, 2 );
224 /* Remove from the internal list. */
225 DLIST_REMOVE(printers_list
, Printer
);
229 /****************************************************************************
230 find printer index by handle
231 ****************************************************************************/
233 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
,
234 struct policy_handle
*hnd
)
236 Printer_entry
*find_printer
= NULL
;
238 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
239 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
246 /****************************************************************************
247 Close printer index by handle.
248 ****************************************************************************/
250 static bool close_printer_handle(pipes_struct
*p
, struct policy_handle
*hnd
)
252 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
255 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
260 close_policy_hnd(p
, hnd
);
265 /****************************************************************************
266 Delete a printer given a handle.
267 ****************************************************************************/
269 static WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *sharename
)
271 char *cmd
= lp_deleteprinter_cmd();
272 char *command
= NULL
;
274 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
275 bool is_print_op
= false;
277 /* can't fail if we don't try */
282 command
= talloc_asprintf(ctx
,
289 is_print_op
= user_has_privileges( token
, &se_printop
);
291 DEBUG(10,("Running [%s]\n", command
));
293 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
298 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
299 /* Tell everyone we updated smb.conf. */
300 message_send_all(smbd_messaging_context(),
301 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
307 /********** END SePrintOperatorPrivlege BLOCK **********/
309 DEBUGADD(10,("returned [%d]\n", ret
));
311 TALLOC_FREE(command
);
314 return WERR_BADFID
; /* What to return here? */
316 /* go ahead and re-read the services immediately */
318 reload_services(false);
321 if ( lp_servicenumber( sharename
) > 0 )
322 return WERR_ACCESS_DENIED
;
327 /****************************************************************************
328 Delete a printer given a handle.
329 ****************************************************************************/
331 static WERROR
delete_printer_handle(pipes_struct
*p
, struct policy_handle
*hnd
)
333 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
336 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
342 * It turns out that Windows allows delete printer on a handle
343 * opened by an admin user, then used on a pipe handle created
344 * by an anonymous user..... but they're working on security.... riiight !
348 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
349 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
350 return WERR_ACCESS_DENIED
;
353 /* this does not need a become root since the access check has been
354 done on the handle already */
356 if (del_a_printer( Printer
->sharename
) != 0) {
357 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
361 return delete_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
362 Printer
->sharename
);
365 /****************************************************************************
366 Return the snum of a printer corresponding to an handle.
367 ****************************************************************************/
369 static bool get_printer_snum(pipes_struct
*p
, struct policy_handle
*hnd
,
370 int *number
, struct share_params
**params
)
372 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
375 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
380 switch (Printer
->printer_type
) {
382 DEBUG(4,("short name:%s\n", Printer
->sharename
));
383 *number
= print_queue_snum(Printer
->sharename
);
384 return (*number
!= -1);
392 /****************************************************************************
393 Set printer handle type.
394 Check if it's \\server or \\server\printer
395 ****************************************************************************/
397 static bool set_printer_hnd_printertype(Printer_entry
*Printer
, const char *handlename
)
399 DEBUG(3,("Setting printer type=%s\n", handlename
));
401 if ( strlen(handlename
) < 3 ) {
402 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
406 /* it's a print server */
407 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
408 DEBUGADD(4,("Printer is a print server\n"));
409 Printer
->printer_type
= SPLHND_SERVER
;
411 /* it's a printer (set_printer_hnd_name() will handle port monitors */
413 DEBUGADD(4,("Printer is a printer\n"));
414 Printer
->printer_type
= SPLHND_PRINTER
;
420 /****************************************************************************
421 Set printer handle name.. Accept names like \\server, \\server\printer,
422 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
423 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
424 XcvDataPort() interface.
425 ****************************************************************************/
427 static bool set_printer_hnd_name(Printer_entry
*Printer
, const char *handlename
)
430 int n_services
=lp_numservices();
431 char *aprinter
, *printername
;
432 const char *servername
;
435 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
438 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
,
439 (unsigned long)strlen(handlename
)));
441 aprinter
= CONST_DISCARD(char *, handlename
);
442 if ( *handlename
== '\\' ) {
443 servername
= canon_servername(handlename
);
444 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
449 servername
= global_myname();
452 /* save the servername to fill in replies on this handle */
454 if ( !is_myname_or_ipaddr( servername
) )
457 fstrcpy( Printer
->servername
, servername
);
459 if ( Printer
->printer_type
== SPLHND_SERVER
)
462 if ( Printer
->printer_type
!= SPLHND_PRINTER
)
465 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
467 /* check for the Port Monitor Interface */
469 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
470 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
471 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
474 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
475 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
476 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
480 /* Search all sharenames first as this is easier than pulling
481 the printer_info_2 off of disk. Don't use find_service() since
482 that calls out to map_username() */
484 /* do another loop to look for printernames */
486 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
488 /* no point going on if this is not a printer */
490 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
493 fstrcpy(sname
, lp_servicename(snum
));
494 if ( strequal( aprinter
, sname
) ) {
499 /* no point looking up the printer object if
500 we aren't allowing printername != sharename */
502 if ( lp_force_printername(snum
) )
505 fstrcpy(sname
, lp_servicename(snum
));
509 /* This call doesn't fill in the location or comment from
510 * a CUPS server for efficiency with large numbers of printers.
514 result
= get_a_printer_search( NULL
, &printer
, 2, sname
);
515 if ( !W_ERROR_IS_OK(result
) ) {
516 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
517 sname
, win_errstr(result
)));
521 /* printername is always returned as \\server\printername */
522 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
523 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
524 printer
->info_2
->printername
));
525 free_a_printer( &printer
, 2);
531 if ( strequal(printername
, aprinter
) ) {
532 free_a_printer( &printer
, 2);
537 DEBUGADD(10, ("printername: %s\n", printername
));
539 free_a_printer( &printer
, 2);
542 free_a_printer( &printer
, 2);
545 DEBUGADD(4,("Printer not found\n"));
549 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
551 fstrcpy(Printer
->sharename
, sname
);
556 /****************************************************************************
557 Find first available printer slot. creates a printer handle for you.
558 ****************************************************************************/
560 static bool open_printer_hnd(pipes_struct
*p
, struct policy_handle
*hnd
,
561 const char *name
, uint32_t access_granted
)
563 Printer_entry
*new_printer
;
565 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
567 new_printer
= TALLOC_ZERO_P(NULL
, Printer_entry
);
568 if (new_printer
== NULL
) {
571 talloc_set_destructor(new_printer
, printer_entry_destructor
);
573 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
574 TALLOC_FREE(new_printer
);
578 /* Add to the internal list. */
579 DLIST_ADD(printers_list
, new_printer
);
581 new_printer
->notify
.option
=NULL
;
583 if (!set_printer_hnd_printertype(new_printer
, name
)) {
584 close_printer_handle(p
, hnd
);
588 if (!set_printer_hnd_name(new_printer
, name
)) {
589 close_printer_handle(p
, hnd
);
593 new_printer
->access_granted
= access_granted
;
595 DEBUG(5, ("%d printer handles active\n",
596 (int)num_pipe_handles(p
->pipe_handles
)));
601 /***************************************************************************
602 check to see if the client motify handle is monitoring the notification
603 given by (notify_type, notify_field).
604 **************************************************************************/
606 static bool is_monitoring_event_flags(uint32_t flags
, uint16_t notify_type
,
607 uint16_t notify_field
)
612 static bool is_monitoring_event(Printer_entry
*p
, uint16_t notify_type
,
613 uint16_t notify_field
)
615 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
619 * Flags should always be zero when the change notify
620 * is registered by the client's spooler. A user Win32 app
621 * might use the flags though instead of the NOTIFY_OPTION_INFO
630 return is_monitoring_event_flags(
631 p
->notify
.flags
, notify_type
, notify_field
);
633 for (i
= 0; i
< option
->count
; i
++) {
635 /* Check match for notify_type */
637 if (option
->types
[i
].type
!= notify_type
)
640 /* Check match for field */
642 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
643 if (option
->types
[i
].fields
[j
].field
== notify_field
) {
649 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
650 p
->servername
, p
->sharename
, notify_type
, notify_field
));
655 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
656 _data->data.integer[0] = _integer; \
657 _data->data.integer[1] = 0;
660 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
661 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
662 if (!_data->data.string.string) {\
663 _data->data.string.size = 0; \
665 _data->data.string.size = strlen_m_term(_p) * 2;
667 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
668 _data->data.devmode.devmode = _devmode;
670 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
671 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
672 if (!_data->data.sd.sd) { \
673 _data->data.sd.sd_size = 0; \
675 _data->data.sd.sd_size = _size;
677 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
682 struct spoolss_Time st
;
686 if (!init_systemtime(&st
, t
)) {
690 p
= talloc_array(mem_ctx
, char, len
);
696 * Systemtime must be linearized as a set of UINT16's.
697 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
700 SSVAL(p
, 0, st
.year
);
701 SSVAL(p
, 2, st
.month
);
702 SSVAL(p
, 4, st
.day_of_week
);
704 SSVAL(p
, 8, st
.hour
);
705 SSVAL(p
, 10, st
.minute
);
706 SSVAL(p
, 12, st
.second
);
707 SSVAL(p
, 14, st
.millisecond
);
713 /* Convert a notification message to a struct spoolss_Notify */
715 static void notify_one_value(struct spoolss_notify_msg
*msg
,
716 struct spoolss_Notify
*data
,
719 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
722 static void notify_string(struct spoolss_notify_msg
*msg
,
723 struct spoolss_Notify
*data
,
726 /* The length of the message includes the trailing \0 */
728 data
->data
.string
.size
= msg
->len
* 2;
729 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
730 if (!data
->data
.string
.string
) {
731 data
->data
.string
.size
= 0;
736 static void notify_system_time(struct spoolss_notify_msg
*msg
,
737 struct spoolss_Notify
*data
,
740 data
->data
.string
.string
= NULL
;
741 data
->data
.string
.size
= 0;
743 if (msg
->len
!= sizeof(time_t)) {
744 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
749 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
750 &data
->data
.string
.string
,
751 &data
->data
.string
.size
);
754 struct notify2_message_table
{
756 void (*fn
)(struct spoolss_notify_msg
*msg
,
757 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
760 static struct notify2_message_table printer_notify_table
[] = {
761 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string
},
762 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string
},
763 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string
},
764 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string
},
765 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string
},
766 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string
},
767 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string
},
768 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL
},
769 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string
},
770 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string
},
771 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL
},
772 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string
},
773 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
774 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value
},
775 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value
},
776 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL
},
777 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL
},
778 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL
},
779 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value
},
782 static struct notify2_message_table job_notify_table
[] = {
783 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL
},
784 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL
},
785 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL
},
786 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string
},
787 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL
},
788 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL
},
789 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL
},
790 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL
},
791 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL
},
792 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL
},
793 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value
},
794 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL
},
795 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
796 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string
},
797 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL
},
798 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL
},
799 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time
},
800 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL
},
801 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL
},
802 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL
},
803 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value
},
804 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL
},
805 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value
},
806 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL
},
810 /***********************************************************************
811 Allocate talloc context for container object
812 **********************************************************************/
814 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
819 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
824 /***********************************************************************
825 release all allocated memory and zero out structure
826 **********************************************************************/
828 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
834 talloc_destroy(ctr
->ctx
);
841 /***********************************************************************
842 **********************************************************************/
844 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
852 /***********************************************************************
853 **********************************************************************/
855 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
857 if ( !ctr
|| !ctr
->msg_groups
)
860 if ( idx
>= ctr
->num_groups
)
863 return &ctr
->msg_groups
[idx
];
867 /***********************************************************************
868 How many groups of change messages do we have ?
869 **********************************************************************/
871 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
876 return ctr
->num_groups
;
879 /***********************************************************************
880 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
881 **********************************************************************/
883 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
885 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
886 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
887 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
893 /* loop over all groups looking for a matching printer name */
895 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
896 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
900 /* add a new group? */
902 if ( i
== ctr
->num_groups
) {
905 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
906 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
909 ctr
->msg_groups
= groups
;
911 /* clear the new entry and set the printer name */
913 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
914 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
917 /* add the change messages; 'i' is the correct index now regardless */
919 msg_grp
= &ctr
->msg_groups
[i
];
923 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
924 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
927 msg_grp
->msgs
= msg_list
;
929 new_slot
= msg_grp
->num_msgs
-1;
930 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
932 /* need to allocate own copy of data */
935 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
936 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
938 return ctr
->num_groups
;
941 void construct_info_data(struct spoolss_Notify
*info_data
,
942 enum spoolss_NotifyType type
,
946 /***********************************************************************
947 Send a change notication message on all handles which have a call
949 **********************************************************************/
951 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
954 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
955 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
956 SPOOLSS_NOTIFY_MSG
*messages
;
957 int sending_msg_count
;
960 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
964 messages
= msg_group
->msgs
;
967 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
971 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
973 /* loop over all printers */
975 for (p
= printers_list
; p
; p
= p
->next
) {
976 struct spoolss_Notify
*notifies
;
981 /* Is there notification on this handle? */
983 if ( !p
->notify
.client_connected
)
986 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
988 /* For this printer? Print servers always receive
991 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
992 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
995 DEBUG(10,("Our printer\n"));
997 /* allocate the max entries possible */
999 notifies
= TALLOC_ZERO_ARRAY(mem_ctx
, struct spoolss_Notify
, msg_group
->num_msgs
);
1004 /* build the array of change notifications */
1006 sending_msg_count
= 0;
1008 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
1009 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
1011 /* Are we monitoring this event? */
1013 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1016 sending_msg_count
++;
1019 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1020 msg
->type
, msg
->field
, p
->sharename
));
1023 * if the is a printer notification handle and not a job notification
1024 * type, then set the id to 0. Other wise just use what was specified
1027 * When registering change notification on a print server handle
1028 * we always need to send back the id (snum) matching the printer
1029 * for which the change took place. For change notify registered
1030 * on a printer handle, this does not matter and the id should be 0.
1035 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1041 /* Convert unix jobid to smb jobid */
1043 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1044 id
= sysjob_to_jobid(msg
->id
);
1047 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1052 construct_info_data( ¬ifies
[count
], msg
->type
, msg
->field
, id
);
1055 case PRINTER_NOTIFY_TYPE
:
1056 if ( printer_notify_table
[msg
->field
].fn
)
1057 printer_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1060 case JOB_NOTIFY_TYPE
:
1061 if ( job_notify_table
[msg
->field
].fn
)
1062 job_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1066 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1073 if ( sending_msg_count
) {
1076 union spoolss_ReplyPrinterInfo info
;
1077 struct spoolss_NotifyInfo info0
;
1078 uint32_t reply_result
;
1080 info0
.version
= 0x2;
1081 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1082 info0
.count
= count
;
1083 info0
.notifies
= notifies
;
1085 info
.info0
= &info0
;
1087 status
= rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe
, mem_ctx
,
1088 &p
->notify
.client_hnd
,
1089 p
->notify
.change
, /* color */
1092 0, /* reply_type, must be 0 */
1095 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(werr
)) {
1096 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1097 notify_cli_pipe
->srv_name_slash
,
1100 switch (reply_result
) {
1103 case PRINTER_NOTIFY_INFO_DISCARDED
:
1104 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1105 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1114 DEBUG(8,("send_notify2_changes: Exit...\n"));
1118 /***********************************************************************
1119 **********************************************************************/
1121 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1124 uint32_t tv_sec
, tv_usec
;
1127 /* Unpack message */
1129 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "f",
1132 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "ddddddd",
1134 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1137 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "dd",
1138 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1140 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "B",
1141 &msg
->len
, &msg
->notify
.data
);
1143 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1144 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1146 tv
->tv_sec
= tv_sec
;
1147 tv
->tv_usec
= tv_usec
;
1150 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1151 msg
->notify
.value
[1]));
1153 dump_data(3, (uint8_t *)msg
->notify
.data
, msg
->len
);
1158 /********************************************************************
1159 Receive a notify2 message list
1160 ********************************************************************/
1162 static void receive_notify2_message_list(struct messaging_context
*msg
,
1165 struct server_id server_id
,
1168 size_t msg_count
, i
;
1169 char *buf
= (char *)data
->data
;
1172 SPOOLSS_NOTIFY_MSG notify
;
1173 SPOOLSS_NOTIFY_MSG_CTR messages
;
1176 if (data
->length
< 4) {
1177 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1181 msg_count
= IVAL(buf
, 0);
1184 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1186 if (msg_count
== 0) {
1187 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1191 /* initialize the container */
1193 ZERO_STRUCT( messages
);
1194 notify_msg_ctr_init( &messages
);
1197 * build message groups for each printer identified
1198 * in a change_notify msg. Remember that a PCN message
1199 * includes the handle returned for the srv_spoolss_replyopenprinter()
1200 * call. Therefore messages are grouped according to printer handle.
1203 for ( i
=0; i
<msg_count
; i
++ ) {
1204 struct timeval msg_tv
;
1206 if (msg_ptr
+ 4 - buf
> data
->length
) {
1207 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1211 msg_len
= IVAL(msg_ptr
,0);
1214 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1215 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1219 /* unpack messages */
1221 ZERO_STRUCT( notify
);
1222 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1225 /* add to correct list in container */
1227 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1229 /* free memory that might have been allocated by notify2_unpack_msg() */
1231 if ( notify
.len
!= 0 )
1232 SAFE_FREE( notify
.notify
.data
);
1235 /* process each group of messages */
1237 num_groups
= notify_msg_ctr_numgroups( &messages
);
1238 for ( i
=0; i
<num_groups
; i
++ )
1239 send_notify2_changes( &messages
, i
);
1244 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1245 (uint32_t)msg_count
));
1247 notify_msg_ctr_destroy( &messages
);
1252 /********************************************************************
1253 Send a message to ourself about new driver being installed
1254 so we can upgrade the information for each printer bound to this
1256 ********************************************************************/
1258 static bool srv_spoolss_drv_upgrade_printer(const char *drivername
)
1260 int len
= strlen(drivername
);
1265 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1268 messaging_send_buf(smbd_messaging_context(), procid_self(),
1269 MSG_PRINTER_DRVUPGRADE
,
1270 (uint8_t *)drivername
, len
+1);
1275 /**********************************************************************
1276 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1277 over all printers, upgrading ones as necessary
1278 **********************************************************************/
1280 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1283 struct server_id server_id
,
1288 int n_services
= lp_numservices();
1291 len
= MIN(data
->length
,sizeof(drivername
)-1);
1292 strncpy(drivername
, (const char *)data
->data
, len
);
1294 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1296 /* Iterate the printer list */
1298 for (snum
=0; snum
<n_services
; snum
++)
1300 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1303 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1305 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1306 if (!W_ERROR_IS_OK(result
))
1309 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1311 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1313 /* all we care about currently is the change_id */
1315 result
= mod_a_printer(printer
, 2);
1316 if (!W_ERROR_IS_OK(result
)) {
1317 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1318 win_errstr(result
)));
1322 free_a_printer(&printer
, 2);
1329 /********************************************************************
1330 Update the cache for all printq's with a registered client
1332 ********************************************************************/
1334 void update_monitored_printq_cache( void )
1336 Printer_entry
*printer
= printers_list
;
1339 /* loop through all printers and update the cache where
1340 client_connected == true */
1343 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1344 && printer
->notify
.client_connected
)
1346 snum
= print_queue_snum(printer
->sharename
);
1347 print_queue_status( snum
, NULL
, NULL
);
1350 printer
= printer
->next
;
1356 /****************************************************************
1357 _spoolss_OpenPrinter
1358 ****************************************************************/
1360 WERROR
_spoolss_OpenPrinter(pipes_struct
*p
,
1361 struct spoolss_OpenPrinter
*r
)
1363 struct spoolss_OpenPrinterEx e
;
1366 ZERO_STRUCT(e
.in
.userlevel
);
1368 e
.in
.printername
= r
->in
.printername
;
1369 e
.in
.datatype
= r
->in
.datatype
;
1370 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1371 e
.in
.access_mask
= r
->in
.access_mask
;
1374 e
.out
.handle
= r
->out
.handle
;
1376 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1378 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1379 /* OpenPrinterEx returns this for a bad
1380 * printer name. We must return WERR_INVALID_PRINTER_NAME
1383 werr
= WERR_INVALID_PRINTER_NAME
;
1389 /********************************************************************
1390 ********************************************************************/
1392 bool convert_devicemode(const char *printername
,
1393 const struct spoolss_DeviceMode
*devmode
,
1394 NT_DEVICEMODE
**pp_nt_devmode
)
1396 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1399 * Ensure nt_devmode is a valid pointer
1400 * as we will be overwriting it.
1403 if (nt_devmode
== NULL
) {
1404 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1405 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1409 fstrcpy(nt_devmode
->devicename
, devmode
->devicename
);
1410 fstrcpy(nt_devmode
->formname
, devmode
->formname
);
1412 nt_devmode
->devicename
[31] = '\0';
1413 nt_devmode
->formname
[31] = '\0';
1415 nt_devmode
->specversion
= devmode
->specversion
;
1416 nt_devmode
->driverversion
= devmode
->driverversion
;
1417 nt_devmode
->size
= devmode
->size
;
1418 nt_devmode
->fields
= devmode
->fields
;
1419 nt_devmode
->orientation
= devmode
->orientation
;
1420 nt_devmode
->papersize
= devmode
->papersize
;
1421 nt_devmode
->paperlength
= devmode
->paperlength
;
1422 nt_devmode
->paperwidth
= devmode
->paperwidth
;
1423 nt_devmode
->scale
= devmode
->scale
;
1424 nt_devmode
->copies
= devmode
->copies
;
1425 nt_devmode
->defaultsource
= devmode
->defaultsource
;
1426 nt_devmode
->printquality
= devmode
->printquality
;
1427 nt_devmode
->color
= devmode
->color
;
1428 nt_devmode
->duplex
= devmode
->duplex
;
1429 nt_devmode
->yresolution
= devmode
->yresolution
;
1430 nt_devmode
->ttoption
= devmode
->ttoption
;
1431 nt_devmode
->collate
= devmode
->collate
;
1433 nt_devmode
->logpixels
= devmode
->logpixels
;
1434 nt_devmode
->bitsperpel
= devmode
->bitsperpel
;
1435 nt_devmode
->pelswidth
= devmode
->pelswidth
;
1436 nt_devmode
->pelsheight
= devmode
->pelsheight
;
1437 nt_devmode
->displayflags
= devmode
->displayflags
;
1438 nt_devmode
->displayfrequency
= devmode
->displayfrequency
;
1439 nt_devmode
->icmmethod
= devmode
->icmmethod
;
1440 nt_devmode
->icmintent
= devmode
->icmintent
;
1441 nt_devmode
->mediatype
= devmode
->mediatype
;
1442 nt_devmode
->dithertype
= devmode
->dithertype
;
1443 nt_devmode
->reserved1
= devmode
->reserved1
;
1444 nt_devmode
->reserved2
= devmode
->reserved2
;
1445 nt_devmode
->panningwidth
= devmode
->panningwidth
;
1446 nt_devmode
->panningheight
= devmode
->panningheight
;
1449 * Only change private and driverextra if the incoming devmode
1450 * has a new one. JRA.
1453 if ((devmode
->__driverextra_length
!= 0) && (devmode
->driverextra_data
.data
!= NULL
)) {
1454 SAFE_FREE(nt_devmode
->nt_dev_private
);
1455 nt_devmode
->driverextra
= devmode
->__driverextra_length
;
1456 if((nt_devmode
->nt_dev_private
= SMB_MALLOC_ARRAY(uint8_t, nt_devmode
->driverextra
)) == NULL
)
1458 memcpy(nt_devmode
->nt_dev_private
, devmode
->driverextra_data
.data
, nt_devmode
->driverextra
);
1461 *pp_nt_devmode
= nt_devmode
;
1466 /****************************************************************
1467 _spoolss_OpenPrinterEx
1468 ****************************************************************/
1470 WERROR
_spoolss_OpenPrinterEx(pipes_struct
*p
,
1471 struct spoolss_OpenPrinterEx
*r
)
1474 Printer_entry
*Printer
=NULL
;
1476 if (!r
->in
.printername
) {
1477 return WERR_INVALID_PARAM
;
1480 /* some sanity check because you can open a printer or a print server */
1481 /* aka: \\server\printer or \\server */
1483 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1485 if (!open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0)) {
1486 ZERO_STRUCTP(r
->out
.handle
);
1487 return WERR_INVALID_PARAM
;
1490 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1492 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1493 "handle we created for printer %s\n", r
->in
.printername
));
1494 close_printer_handle(p
, r
->out
.handle
);
1495 ZERO_STRUCTP(r
->out
.handle
);
1496 return WERR_INVALID_PARAM
;
1500 * First case: the user is opening the print server:
1502 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1503 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1505 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1506 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1507 * or if the user is listed in the smb.conf printer admin parameter.
1509 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1510 * client view printer folder, but does not show the MSAPW.
1512 * Note: this test needs code to check access rights here too. Jeremy
1513 * could you look at this?
1515 * Second case: the user is opening a printer:
1516 * NT doesn't let us connect to a printer if the connecting user
1517 * doesn't have print permission.
1519 * Third case: user is opening a Port Monitor
1520 * access checks same as opening a handle to the print server.
1523 switch (Printer
->printer_type
)
1526 case SPLHND_PORTMON_TCP
:
1527 case SPLHND_PORTMON_LOCAL
:
1528 /* Printserver handles use global struct... */
1532 /* Map standard access rights to object specific access rights */
1534 se_map_standard(&r
->in
.access_mask
,
1535 &printserver_std_mapping
);
1537 /* Deny any object specific bits that don't apply to print
1538 servers (i.e printer and job specific bits) */
1540 r
->in
.access_mask
&= SPECIFIC_RIGHTS_MASK
;
1542 if (r
->in
.access_mask
&
1543 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1544 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1545 close_printer_handle(p
, r
->out
.handle
);
1546 ZERO_STRUCTP(r
->out
.handle
);
1547 return WERR_ACCESS_DENIED
;
1550 /* Allow admin access */
1552 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1554 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1556 if (!lp_ms_add_printer_wizard()) {
1557 close_printer_handle(p
, r
->out
.handle
);
1558 ZERO_STRUCTP(r
->out
.handle
);
1559 return WERR_ACCESS_DENIED
;
1562 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1563 and not a printer admin, then fail */
1565 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
1566 !user_has_privileges(p
->server_info
->ptok
,
1568 !token_contains_name_in_list(
1569 uidtoname(p
->server_info
->utok
.uid
),
1571 p
->server_info
->ptok
,
1572 lp_printer_admin(snum
))) {
1573 close_printer_handle(p
, r
->out
.handle
);
1574 ZERO_STRUCTP(r
->out
.handle
);
1575 return WERR_ACCESS_DENIED
;
1578 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1582 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1585 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1586 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1588 /* We fall through to return WERR_OK */
1591 case SPLHND_PRINTER
:
1592 /* NT doesn't let us connect to a printer if the connecting user
1593 doesn't have print permission. */
1595 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1596 close_printer_handle(p
, r
->out
.handle
);
1597 ZERO_STRUCTP(r
->out
.handle
);
1601 if (r
->in
.access_mask
== SEC_FLAG_MAXIMUM_ALLOWED
) {
1602 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1605 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1607 /* map an empty access mask to the minimum access mask */
1608 if (r
->in
.access_mask
== 0x0)
1609 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1612 * If we are not serving the printer driver for this printer,
1613 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1614 * will keep NT clients happy --jerry
1617 if (lp_use_client_driver(snum
)
1618 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1620 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1623 /* check smb.conf parameters and the the sec_desc */
1625 if ( !check_access(get_client_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1626 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1627 ZERO_STRUCTP(r
->out
.handle
);
1628 return WERR_ACCESS_DENIED
;
1631 if (!user_ok_token(uidtoname(p
->server_info
->utok
.uid
), NULL
,
1632 p
->server_info
->ptok
, snum
) ||
1633 !print_access_check(p
->server_info
, snum
,
1634 r
->in
.access_mask
)) {
1635 DEBUG(3, ("access DENIED for printer open\n"));
1636 close_printer_handle(p
, r
->out
.handle
);
1637 ZERO_STRUCTP(r
->out
.handle
);
1638 return WERR_ACCESS_DENIED
;
1641 if ((r
->in
.access_mask
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1642 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1643 close_printer_handle(p
, r
->out
.handle
);
1644 ZERO_STRUCTP(r
->out
.handle
);
1645 return WERR_ACCESS_DENIED
;
1648 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1649 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1651 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1653 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1654 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1659 /* sanity check to prevent programmer error */
1660 ZERO_STRUCTP(r
->out
.handle
);
1664 Printer
->access_granted
= r
->in
.access_mask
;
1667 * If the client sent a devmode in the OpenPrinter() call, then
1668 * save it here in case we get a job submission on this handle
1671 if ((Printer
->printer_type
!= SPLHND_SERVER
) &&
1672 r
->in
.devmode_ctr
.devmode
) {
1673 convert_devicemode(Printer
->sharename
,
1674 r
->in
.devmode_ctr
.devmode
,
1675 &Printer
->nt_devmode
);
1678 #if 0 /* JERRY -- I'm doubtful this is really effective */
1679 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1680 optimization in Windows 2000 clients --jerry */
1682 if ( (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1683 && (RA_WIN2K
== get_remote_arch()) )
1685 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1686 sys_usleep( 500000 );
1693 /****************************************************************************
1694 ****************************************************************************/
1696 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2
*r
,
1697 NT_PRINTER_INFO_LEVEL_2
*d
)
1699 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1705 d
->attributes
= r
->attributes
;
1706 d
->priority
= r
->priority
;
1707 d
->default_priority
= r
->defaultpriority
;
1708 d
->starttime
= r
->starttime
;
1709 d
->untiltime
= r
->untiltime
;
1710 d
->status
= r
->status
;
1711 d
->cjobs
= r
->cjobs
;
1713 fstrcpy(d
->servername
, r
->servername
);
1714 fstrcpy(d
->printername
, r
->printername
);
1715 fstrcpy(d
->sharename
, r
->sharename
);
1716 fstrcpy(d
->portname
, r
->portname
);
1717 fstrcpy(d
->drivername
, r
->drivername
);
1718 slprintf(d
->comment
, sizeof(d
->comment
)-1, "%s", r
->comment
);
1719 fstrcpy(d
->location
, r
->location
);
1720 fstrcpy(d
->sepfile
, r
->sepfile
);
1721 fstrcpy(d
->printprocessor
, r
->printprocessor
);
1722 fstrcpy(d
->datatype
, r
->datatype
);
1723 fstrcpy(d
->parameters
, r
->parameters
);
1728 /****************************************************************************
1729 ****************************************************************************/
1731 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1732 NT_PRINTER_INFO_LEVEL
*printer
)
1736 switch (info_ctr
->level
) {
1738 /* allocate memory if needed. Messy because
1739 convert_printer_info is used to update an existing
1740 printer or build a new one */
1742 if (!printer
->info_2
) {
1743 printer
->info_2
= TALLOC_ZERO_P(printer
, NT_PRINTER_INFO_LEVEL_2
);
1744 if (!printer
->info_2
) {
1745 DEBUG(0,("convert_printer_info: "
1746 "talloc() failed!\n"));
1751 ret
= printer_info2_to_nt_printer_info2(info_ctr
->info
.info2
,
1753 printer
->info_2
->setuptime
= time(NULL
);
1760 /****************************************************************
1761 _spoolss_ClosePrinter
1762 ****************************************************************/
1764 WERROR
_spoolss_ClosePrinter(pipes_struct
*p
,
1765 struct spoolss_ClosePrinter
*r
)
1767 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1769 if (Printer
&& Printer
->document_started
) {
1770 struct spoolss_EndDocPrinter e
;
1772 e
.in
.handle
= r
->in
.handle
;
1774 _spoolss_EndDocPrinter(p
, &e
);
1777 if (!close_printer_handle(p
, r
->in
.handle
))
1780 /* clear the returned printer handle. Observed behavior
1781 from Win2k server. Don't think this really matters.
1782 Previous code just copied the value of the closed
1785 ZERO_STRUCTP(r
->out
.handle
);
1790 /****************************************************************
1791 _spoolss_DeletePrinter
1792 ****************************************************************/
1794 WERROR
_spoolss_DeletePrinter(pipes_struct
*p
,
1795 struct spoolss_DeletePrinter
*r
)
1797 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1800 if (Printer
&& Printer
->document_started
) {
1801 struct spoolss_EndDocPrinter e
;
1803 e
.in
.handle
= r
->in
.handle
;
1805 _spoolss_EndDocPrinter(p
, &e
);
1808 result
= delete_printer_handle(p
, r
->in
.handle
);
1810 update_c_setprinter(false);
1815 /*******************************************************************
1816 * static function to lookup the version id corresponding to an
1817 * long architecture string
1818 ******************************************************************/
1820 static const struct print_architecture_table_node archi_table
[]= {
1822 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
1823 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
1824 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
1825 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
1826 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
1827 {"Windows IA64", SPL_ARCH_IA64
, 3 },
1828 {"Windows x64", SPL_ARCH_X64
, 3 },
1832 static int get_version_id(const char *arch
)
1836 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1838 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1839 return (archi_table
[i
].version
);
1845 /****************************************************************
1846 _spoolss_DeletePrinterDriver
1847 ****************************************************************/
1849 WERROR
_spoolss_DeletePrinterDriver(pipes_struct
*p
,
1850 struct spoolss_DeletePrinterDriver
*r
)
1853 struct spoolss_DriverInfo8
*info
= NULL
;
1854 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
1857 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1858 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1860 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1861 and not a printer admin, then fail */
1863 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
1864 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
1865 && !token_contains_name_in_list(
1866 uidtoname(p
->server_info
->utok
.uid
), NULL
,
1867 NULL
, p
->server_info
->ptok
,
1868 lp_printer_admin(-1)) )
1870 return WERR_ACCESS_DENIED
;
1873 /* check that we have a valid driver name first */
1875 if ((version
= get_version_id(r
->in
.architecture
)) == -1)
1876 return WERR_INVALID_ENVIRONMENT
;
1878 if (!W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
, &info
, r
->in
.driver
,
1882 /* try for Win2k driver if "Windows NT x86" */
1884 if ( version
== 2 ) {
1886 if (!W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
,
1891 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1895 /* otherwise it was a failure */
1897 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1903 if (printer_driver_in_use(info
)) {
1904 status
= WERR_PRINTER_DRIVER_IN_USE
;
1910 if (W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
,
1913 r
->in
.architecture
, 3)))
1915 /* if we get to here, we now have 2 driver info structures to remove */
1916 /* remove the Win2k driver first*/
1918 status_win2k
= delete_printer_driver(
1919 p
, info_win2k
, 3, false);
1920 free_a_printer_driver(info_win2k
);
1922 /* this should not have failed---if it did, report to client */
1923 if ( !W_ERROR_IS_OK(status_win2k
) )
1925 status
= status_win2k
;
1931 status
= delete_printer_driver(p
, info
, version
, false);
1933 /* if at least one of the deletes succeeded return OK */
1935 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
1939 free_a_printer_driver(info
);
1944 /****************************************************************
1945 _spoolss_DeletePrinterDriverEx
1946 ****************************************************************/
1948 WERROR
_spoolss_DeletePrinterDriverEx(pipes_struct
*p
,
1949 struct spoolss_DeletePrinterDriverEx
*r
)
1951 struct spoolss_DriverInfo8
*info
= NULL
;
1952 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
1956 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1957 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1959 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1960 and not a printer admin, then fail */
1962 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
1963 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
1964 && !token_contains_name_in_list(
1965 uidtoname(p
->server_info
->utok
.uid
), NULL
, NULL
,
1966 p
->server_info
->ptok
, lp_printer_admin(-1)) )
1968 return WERR_ACCESS_DENIED
;
1971 /* check that we have a valid driver name first */
1972 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
1973 /* this is what NT returns */
1974 return WERR_INVALID_ENVIRONMENT
;
1977 if (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
1978 version
= r
->in
.version
;
1980 status
= get_a_printer_driver(p
->mem_ctx
, &info
, r
->in
.driver
,
1981 r
->in
.architecture
, version
);
1983 if ( !W_ERROR_IS_OK(status
) )
1986 * if the client asked for a specific version,
1987 * or this is something other than Windows NT x86,
1991 if ( (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
1994 /* try for Win2k driver if "Windows NT x86" */
1997 if (!W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
, &info
, r
->in
.driver
,
2000 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2005 if (printer_driver_in_use(info
)) {
2006 status
= WERR_PRINTER_DRIVER_IN_USE
;
2011 * we have a couple of cases to consider.
2012 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2013 * then the delete should fail if **any** files overlap with
2015 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2016 * non-overlapping files
2017 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2018 * is set, the do not delete any files
2019 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2022 delete_files
= r
->in
.delete_flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2024 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2026 if (delete_files
&& printer_driver_files_in_use(info
, info
) & (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
)) {
2027 /* no idea of the correct error here */
2028 status
= WERR_ACCESS_DENIED
;
2033 /* also check for W32X86/3 if necessary; maybe we already have? */
2035 if ( (version
== 2) && ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2036 if (W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
, &info_win2k
,
2038 r
->in
.architecture
, 3)))
2041 if (delete_files
&& printer_driver_files_in_use(info
, info_win2k
) & (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) ) {
2042 /* no idea of the correct error here */
2043 free_a_printer_driver(info_win2k
);
2044 status
= WERR_ACCESS_DENIED
;
2048 /* if we get to here, we now have 2 driver info structures to remove */
2049 /* remove the Win2k driver first*/
2051 status_win2k
= delete_printer_driver(
2052 p
, info_win2k
, 3, delete_files
);
2053 free_a_printer_driver(info_win2k
);
2055 /* this should not have failed---if it did, report to client */
2057 if ( !W_ERROR_IS_OK(status_win2k
) )
2062 status
= delete_printer_driver(p
, info
, version
, delete_files
);
2064 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2067 free_a_printer_driver(info
);
2073 /****************************************************************************
2074 Internal routine for removing printerdata
2075 ***************************************************************************/
2077 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2079 return delete_printer_data( printer
->info_2
, key
, value
);
2082 /****************************************************************************
2083 Internal routine for storing printerdata
2084 ***************************************************************************/
2086 WERROR
set_printer_dataex(NT_PRINTER_INFO_LEVEL
*printer
,
2087 const char *key
, const char *value
,
2088 uint32_t type
, uint8_t *data
, int real_len
)
2090 /* the registry objects enforce uniqueness based on value name */
2092 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2095 /********************************************************************
2096 GetPrinterData on a printer server Handle.
2097 ********************************************************************/
2099 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2101 enum winreg_Type
*type
,
2102 union spoolss_PrinterData
*data
)
2104 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2106 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2112 if (!StrCaseCmp(value
, "BeepEnabled")) {
2118 if (!StrCaseCmp(value
, "EventLog")) {
2120 /* formally was 0x1b */
2125 if (!StrCaseCmp(value
, "NetPopup")) {
2131 if (!StrCaseCmp(value
, "MajorVersion")) {
2134 /* Windows NT 4.0 seems to not allow uploading of drivers
2135 to a server that reports 0x3 as the MajorVersion.
2136 need to investigate more how Win2k gets around this .
2139 if (RA_WINNT
== get_remote_arch()) {
2148 if (!StrCaseCmp(value
, "MinorVersion")) {
2155 * uint32_t size = 0x114
2156 * uint32_t major = 5
2157 * uint32_t minor = [0|1]
2158 * uint32_t build = [2195|2600]
2159 * extra unicode string = e.g. "Service Pack 3"
2161 if (!StrCaseCmp(value
, "OSVersion")) {
2163 enum ndr_err_code ndr_err
;
2164 struct spoolss_OSVersion os
;
2166 os
.major
= 5; /* Windows 2000 == 5.0 */
2168 os
.build
= 2195; /* build */
2169 os
.extra_string
= ""; /* leave extra string empty */
2171 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &os
,
2172 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2173 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2174 return WERR_GENERAL_FAILURE
;
2178 data
->binary
= blob
;
2184 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2187 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2188 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2193 if (!StrCaseCmp(value
, "Architecture")) {
2195 data
->string
= talloc_strdup(mem_ctx
,
2196 lp_parm_const_string(GLOBAL_SECTION_SNUM
, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86
));
2197 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2202 if (!StrCaseCmp(value
, "DsPresent")) {
2205 /* only show the publish check box if we are a
2206 member of a AD domain */
2208 if (lp_security() == SEC_ADS
) {
2216 if (!StrCaseCmp(value
, "DNSMachineName")) {
2217 const char *hostname
= get_mydnsfullname();
2220 return WERR_BADFILE
;
2224 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2225 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2232 return WERR_INVALID_PARAM
;
2235 /****************************************************************
2236 _spoolss_GetPrinterData
2237 ****************************************************************/
2239 WERROR
_spoolss_GetPrinterData(pipes_struct
*p
,
2240 struct spoolss_GetPrinterData
*r
)
2242 struct spoolss_GetPrinterDataEx r2
;
2244 r2
.in
.handle
= r
->in
.handle
;
2245 r2
.in
.key_name
= "PrinterDriverData";
2246 r2
.in
.value_name
= r
->in
.value_name
;
2247 r2
.in
.offered
= r
->in
.offered
;
2248 r2
.out
.type
= r
->out
.type
;
2249 r2
.out
.data
= r
->out
.data
;
2250 r2
.out
.needed
= r
->out
.needed
;
2252 return _spoolss_GetPrinterDataEx(p
, &r2
);
2255 /*********************************************************
2256 Connect to the client machine.
2257 **********************************************************/
2259 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2260 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2263 struct cli_state
*the_cli
;
2264 struct sockaddr_storage rm_addr
;
2265 char addr
[INET6_ADDRSTRLEN
];
2267 if ( is_zero_addr((struct sockaddr
*)client_ss
) ) {
2268 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2270 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20, false) ) {
2271 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2274 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2276 rm_addr
= *client_ss
;
2277 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2278 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2282 if (ismyaddr((struct sockaddr
*)&rm_addr
)) {
2283 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2288 /* setup the connection */
2289 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2290 &rm_addr
, 0, "IPC$", "IPC",
2294 0, lp_client_signing(), NULL
);
2296 if ( !NT_STATUS_IS_OK( ret
) ) {
2297 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2302 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2303 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2304 cli_shutdown(the_cli
);
2309 * Ok - we have an anonymous connection to the IPC$ share.
2310 * Now start the NT Domain stuff :-).
2313 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2314 if (!NT_STATUS_IS_OK(ret
)) {
2315 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2316 remote_machine
, nt_errstr(ret
)));
2317 cli_shutdown(the_cli
);
2324 /***************************************************************************
2325 Connect to the client.
2326 ****************************************************************************/
2328 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2329 uint32_t localprinter
, uint32_t type
,
2330 struct policy_handle
*handle
,
2331 struct sockaddr_storage
*client_ss
)
2337 * If it's the first connection, contact the client
2338 * and connect to the IPC$ share anonymously
2340 if (smb_connections
==0) {
2341 fstring unix_printer
;
2343 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2345 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ss
, unix_printer
))
2348 messaging_register(smbd_messaging_context(), NULL
,
2349 MSG_PRINTER_NOTIFY2
,
2350 receive_notify2_message_list
);
2351 /* Tell the connections db we're now interested in printer
2352 * notify messages. */
2353 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY
);
2357 * Tell the specific printing tdb we want messages for this printer
2358 * by registering our PID.
2361 if (!print_notify_register_pid(snum
))
2362 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2366 status
= rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe
, talloc_tos(),
2374 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
2375 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2376 win_errstr(result
)));
2378 return (W_ERROR_IS_OK(result
));
2381 /****************************************************************
2382 ****************************************************************/
2384 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2385 const struct spoolss_NotifyOption
*r
)
2387 struct spoolss_NotifyOption
*option
;
2394 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2401 if (!option
->count
) {
2405 option
->types
= talloc_zero_array(option
,
2406 struct spoolss_NotifyOptionType
, option
->count
);
2407 if (!option
->types
) {
2408 talloc_free(option
);
2412 for (i
=0; i
< option
->count
; i
++) {
2413 option
->types
[i
] = r
->types
[i
];
2415 if (option
->types
[i
].count
) {
2416 option
->types
[i
].fields
= talloc_zero_array(option
,
2417 union spoolss_Field
, option
->types
[i
].count
);
2418 if (!option
->types
[i
].fields
) {
2419 talloc_free(option
);
2422 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2423 option
->types
[i
].fields
[k
] =
2424 r
->types
[i
].fields
[k
];
2432 /****************************************************************
2433 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2435 * before replying OK: status=0 a rpc call is made to the workstation
2436 * asking ReplyOpenPrinter
2438 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2439 * called from api_spoolss_rffpcnex
2440 ****************************************************************/
2442 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct
*p
,
2443 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2446 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2447 struct sockaddr_storage client_ss
;
2449 /* store the notify value in the printer struct */
2451 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2454 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2455 "Invalid handle (%s:%u:%u).\n",
2456 OUR_HANDLE(r
->in
.handle
)));
2460 Printer
->notify
.flags
= r
->in
.flags
;
2461 Printer
->notify
.options
= r
->in
.options
;
2462 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2464 TALLOC_FREE(Printer
->notify
.option
);
2465 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2467 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2469 /* Connect to the client machine and send a ReplyOpenPrinter */
2471 if ( Printer
->printer_type
== SPLHND_SERVER
)
2473 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2474 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2477 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2478 "client_address is %s\n", p
->client_address
));
2480 if (!interpret_string_addr(&client_ss
, p
->client_address
,
2482 return WERR_SERVER_UNAVAILABLE
;
2485 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2486 Printer
->notify
.printerlocal
, 1,
2487 &Printer
->notify
.client_hnd
, &client_ss
))
2488 return WERR_SERVER_UNAVAILABLE
;
2490 Printer
->notify
.client_connected
= true;
2495 /*******************************************************************
2496 * fill a notify_info_data with the servername
2497 ********************************************************************/
2499 static void spoolss_notify_server_name(int snum
,
2500 struct spoolss_Notify
*data
,
2501 print_queue_struct
*queue
,
2502 NT_PRINTER_INFO_LEVEL
*printer
,
2503 TALLOC_CTX
*mem_ctx
)
2505 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->servername
);
2508 /*******************************************************************
2509 * fill a notify_info_data with the printername (not including the servername).
2510 ********************************************************************/
2512 static void spoolss_notify_printer_name(int snum
,
2513 struct spoolss_Notify
*data
,
2514 print_queue_struct
*queue
,
2515 NT_PRINTER_INFO_LEVEL
*printer
,
2516 TALLOC_CTX
*mem_ctx
)
2518 /* the notify name should not contain the \\server\ part */
2519 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2522 p
= printer
->info_2
->printername
;
2527 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2530 /*******************************************************************
2531 * fill a notify_info_data with the servicename
2532 ********************************************************************/
2534 static void spoolss_notify_share_name(int snum
,
2535 struct spoolss_Notify
*data
,
2536 print_queue_struct
*queue
,
2537 NT_PRINTER_INFO_LEVEL
*printer
,
2538 TALLOC_CTX
*mem_ctx
)
2540 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2543 /*******************************************************************
2544 * fill a notify_info_data with the port name
2545 ********************************************************************/
2547 static void spoolss_notify_port_name(int snum
,
2548 struct spoolss_Notify
*data
,
2549 print_queue_struct
*queue
,
2550 NT_PRINTER_INFO_LEVEL
*printer
,
2551 TALLOC_CTX
*mem_ctx
)
2553 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->portname
);
2556 /*******************************************************************
2557 * fill a notify_info_data with the printername
2558 * but it doesn't exist, have to see what to do
2559 ********************************************************************/
2561 static void spoolss_notify_driver_name(int snum
,
2562 struct spoolss_Notify
*data
,
2563 print_queue_struct
*queue
,
2564 NT_PRINTER_INFO_LEVEL
*printer
,
2565 TALLOC_CTX
*mem_ctx
)
2567 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->drivername
);
2570 /*******************************************************************
2571 * fill a notify_info_data with the comment
2572 ********************************************************************/
2574 static void spoolss_notify_comment(int snum
,
2575 struct spoolss_Notify
*data
,
2576 print_queue_struct
*queue
,
2577 NT_PRINTER_INFO_LEVEL
*printer
,
2578 TALLOC_CTX
*mem_ctx
)
2582 if (*printer
->info_2
->comment
== '\0') {
2583 p
= lp_comment(snum
);
2585 p
= printer
->info_2
->comment
;
2588 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->comment
);
2591 /*******************************************************************
2592 * fill a notify_info_data with the comment
2593 * location = "Room 1, floor 2, building 3"
2594 ********************************************************************/
2596 static void spoolss_notify_location(int snum
,
2597 struct spoolss_Notify
*data
,
2598 print_queue_struct
*queue
,
2599 NT_PRINTER_INFO_LEVEL
*printer
,
2600 TALLOC_CTX
*mem_ctx
)
2602 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->location
);
2605 /*******************************************************************
2606 * fill a notify_info_data with the device mode
2607 * jfm:xxxx don't to it for know but that's a real problem !!!
2608 ********************************************************************/
2610 static void spoolss_notify_devmode(int snum
,
2611 struct spoolss_Notify
*data
,
2612 print_queue_struct
*queue
,
2613 NT_PRINTER_INFO_LEVEL
*printer
,
2614 TALLOC_CTX
*mem_ctx
)
2616 /* for a dummy implementation we have to zero the fields */
2617 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2620 /*******************************************************************
2621 * fill a notify_info_data with the separator file name
2622 ********************************************************************/
2624 static void spoolss_notify_sepfile(int snum
,
2625 struct spoolss_Notify
*data
,
2626 print_queue_struct
*queue
,
2627 NT_PRINTER_INFO_LEVEL
*printer
,
2628 TALLOC_CTX
*mem_ctx
)
2630 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->sepfile
);
2633 /*******************************************************************
2634 * fill a notify_info_data with the print processor
2635 * jfm:xxxx return always winprint to indicate we don't do anything to it
2636 ********************************************************************/
2638 static void spoolss_notify_print_processor(int snum
,
2639 struct spoolss_Notify
*data
,
2640 print_queue_struct
*queue
,
2641 NT_PRINTER_INFO_LEVEL
*printer
,
2642 TALLOC_CTX
*mem_ctx
)
2644 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->printprocessor
);
2647 /*******************************************************************
2648 * fill a notify_info_data with the print processor options
2649 * jfm:xxxx send an empty string
2650 ********************************************************************/
2652 static void spoolss_notify_parameters(int snum
,
2653 struct spoolss_Notify
*data
,
2654 print_queue_struct
*queue
,
2655 NT_PRINTER_INFO_LEVEL
*printer
,
2656 TALLOC_CTX
*mem_ctx
)
2658 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->parameters
);
2661 /*******************************************************************
2662 * fill a notify_info_data with the data type
2663 * jfm:xxxx always send RAW as data type
2664 ********************************************************************/
2666 static void spoolss_notify_datatype(int snum
,
2667 struct spoolss_Notify
*data
,
2668 print_queue_struct
*queue
,
2669 NT_PRINTER_INFO_LEVEL
*printer
,
2670 TALLOC_CTX
*mem_ctx
)
2672 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->datatype
);
2675 /*******************************************************************
2676 * fill a notify_info_data with the security descriptor
2677 * jfm:xxxx send an null pointer to say no security desc
2678 * have to implement security before !
2679 ********************************************************************/
2681 static void spoolss_notify_security_desc(int snum
,
2682 struct spoolss_Notify
*data
,
2683 print_queue_struct
*queue
,
2684 NT_PRINTER_INFO_LEVEL
*printer
,
2685 TALLOC_CTX
*mem_ctx
)
2687 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
,
2688 printer
->info_2
->secdesc_buf
->sd_size
,
2689 printer
->info_2
->secdesc_buf
->sd
);
2692 /*******************************************************************
2693 * fill a notify_info_data with the attributes
2694 * jfm:xxxx a samba printer is always shared
2695 ********************************************************************/
2697 static void spoolss_notify_attributes(int snum
,
2698 struct spoolss_Notify
*data
,
2699 print_queue_struct
*queue
,
2700 NT_PRINTER_INFO_LEVEL
*printer
,
2701 TALLOC_CTX
*mem_ctx
)
2703 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->attributes
);
2706 /*******************************************************************
2707 * fill a notify_info_data with the priority
2708 ********************************************************************/
2710 static void spoolss_notify_priority(int snum
,
2711 struct spoolss_Notify
*data
,
2712 print_queue_struct
*queue
,
2713 NT_PRINTER_INFO_LEVEL
*printer
,
2714 TALLOC_CTX
*mem_ctx
)
2716 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->priority
);
2719 /*******************************************************************
2720 * fill a notify_info_data with the default priority
2721 ********************************************************************/
2723 static void spoolss_notify_default_priority(int snum
,
2724 struct spoolss_Notify
*data
,
2725 print_queue_struct
*queue
,
2726 NT_PRINTER_INFO_LEVEL
*printer
,
2727 TALLOC_CTX
*mem_ctx
)
2729 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->default_priority
);
2732 /*******************************************************************
2733 * fill a notify_info_data with the start time
2734 ********************************************************************/
2736 static void spoolss_notify_start_time(int snum
,
2737 struct spoolss_Notify
*data
,
2738 print_queue_struct
*queue
,
2739 NT_PRINTER_INFO_LEVEL
*printer
,
2740 TALLOC_CTX
*mem_ctx
)
2742 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->starttime
);
2745 /*******************************************************************
2746 * fill a notify_info_data with the until time
2747 ********************************************************************/
2749 static void spoolss_notify_until_time(int snum
,
2750 struct spoolss_Notify
*data
,
2751 print_queue_struct
*queue
,
2752 NT_PRINTER_INFO_LEVEL
*printer
,
2753 TALLOC_CTX
*mem_ctx
)
2755 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->untiltime
);
2758 /*******************************************************************
2759 * fill a notify_info_data with the status
2760 ********************************************************************/
2762 static void spoolss_notify_status(int snum
,
2763 struct spoolss_Notify
*data
,
2764 print_queue_struct
*queue
,
2765 NT_PRINTER_INFO_LEVEL
*printer
,
2766 TALLOC_CTX
*mem_ctx
)
2768 print_status_struct status
;
2770 print_queue_length(snum
, &status
);
2771 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
2774 /*******************************************************************
2775 * fill a notify_info_data with the number of jobs queued
2776 ********************************************************************/
2778 static void spoolss_notify_cjobs(int snum
,
2779 struct spoolss_Notify
*data
,
2780 print_queue_struct
*queue
,
2781 NT_PRINTER_INFO_LEVEL
*printer
,
2782 TALLOC_CTX
*mem_ctx
)
2784 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, print_queue_length(snum
, NULL
));
2787 /*******************************************************************
2788 * fill a notify_info_data with the average ppm
2789 ********************************************************************/
2791 static void spoolss_notify_average_ppm(int snum
,
2792 struct spoolss_Notify
*data
,
2793 print_queue_struct
*queue
,
2794 NT_PRINTER_INFO_LEVEL
*printer
,
2795 TALLOC_CTX
*mem_ctx
)
2797 /* always respond 8 pages per minutes */
2798 /* a little hard ! */
2799 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->averageppm
);
2802 /*******************************************************************
2803 * fill a notify_info_data with username
2804 ********************************************************************/
2806 static void spoolss_notify_username(int snum
,
2807 struct spoolss_Notify
*data
,
2808 print_queue_struct
*queue
,
2809 NT_PRINTER_INFO_LEVEL
*printer
,
2810 TALLOC_CTX
*mem_ctx
)
2812 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
2815 /*******************************************************************
2816 * fill a notify_info_data with job status
2817 ********************************************************************/
2819 static void spoolss_notify_job_status(int snum
,
2820 struct spoolss_Notify
*data
,
2821 print_queue_struct
*queue
,
2822 NT_PRINTER_INFO_LEVEL
*printer
,
2823 TALLOC_CTX
*mem_ctx
)
2825 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
2828 /*******************************************************************
2829 * fill a notify_info_data with job name
2830 ********************************************************************/
2832 static void spoolss_notify_job_name(int snum
,
2833 struct spoolss_Notify
*data
,
2834 print_queue_struct
*queue
,
2835 NT_PRINTER_INFO_LEVEL
*printer
,
2836 TALLOC_CTX
*mem_ctx
)
2838 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
2841 /*******************************************************************
2842 * fill a notify_info_data with job status
2843 ********************************************************************/
2845 static void spoolss_notify_job_status_string(int snum
,
2846 struct spoolss_Notify
*data
,
2847 print_queue_struct
*queue
,
2848 NT_PRINTER_INFO_LEVEL
*printer
,
2849 TALLOC_CTX
*mem_ctx
)
2852 * Now we're returning job status codes we just return a "" here. JRA.
2857 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2860 switch (queue
->status
) {
2865 p
= ""; /* NT provides the paused string */
2874 #endif /* NO LONGER NEEDED. */
2876 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2879 /*******************************************************************
2880 * fill a notify_info_data with job time
2881 ********************************************************************/
2883 static void spoolss_notify_job_time(int snum
,
2884 struct spoolss_Notify
*data
,
2885 print_queue_struct
*queue
,
2886 NT_PRINTER_INFO_LEVEL
*printer
,
2887 TALLOC_CTX
*mem_ctx
)
2889 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
2892 /*******************************************************************
2893 * fill a notify_info_data with job size
2894 ********************************************************************/
2896 static void spoolss_notify_job_size(int snum
,
2897 struct spoolss_Notify
*data
,
2898 print_queue_struct
*queue
,
2899 NT_PRINTER_INFO_LEVEL
*printer
,
2900 TALLOC_CTX
*mem_ctx
)
2902 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
2905 /*******************************************************************
2906 * fill a notify_info_data with page info
2907 ********************************************************************/
2908 static void spoolss_notify_total_pages(int snum
,
2909 struct spoolss_Notify
*data
,
2910 print_queue_struct
*queue
,
2911 NT_PRINTER_INFO_LEVEL
*printer
,
2912 TALLOC_CTX
*mem_ctx
)
2914 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
2917 /*******************************************************************
2918 * fill a notify_info_data with pages printed info.
2919 ********************************************************************/
2920 static void spoolss_notify_pages_printed(int snum
,
2921 struct spoolss_Notify
*data
,
2922 print_queue_struct
*queue
,
2923 NT_PRINTER_INFO_LEVEL
*printer
,
2924 TALLOC_CTX
*mem_ctx
)
2926 /* Add code when back-end tracks this */
2927 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
2930 /*******************************************************************
2931 Fill a notify_info_data with job position.
2932 ********************************************************************/
2934 static void spoolss_notify_job_position(int snum
,
2935 struct spoolss_Notify
*data
,
2936 print_queue_struct
*queue
,
2937 NT_PRINTER_INFO_LEVEL
*printer
,
2938 TALLOC_CTX
*mem_ctx
)
2940 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->job
);
2943 /*******************************************************************
2944 Fill a notify_info_data with submitted time.
2945 ********************************************************************/
2947 static void spoolss_notify_submitted_time(int snum
,
2948 struct spoolss_Notify
*data
,
2949 print_queue_struct
*queue
,
2950 NT_PRINTER_INFO_LEVEL
*printer
,
2951 TALLOC_CTX
*mem_ctx
)
2953 data
->data
.string
.string
= NULL
;
2954 data
->data
.string
.size
= 0;
2956 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
2957 &data
->data
.string
.string
,
2958 &data
->data
.string
.size
);
2962 struct s_notify_info_data_table
2964 enum spoolss_NotifyType type
;
2967 enum spoolss_NotifyTable variable_type
;
2968 void (*fn
) (int snum
, struct spoolss_Notify
*data
,
2969 print_queue_struct
*queue
,
2970 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
2973 /* A table describing the various print notification constants and
2974 whether the notification data is a pointer to a variable sized
2975 buffer, a one value uint32_t or a two value uint32_t. */
2977 static const struct s_notify_info_data_table notify_info_data_table
[] =
2979 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
2980 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
2981 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
2982 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
2983 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
2984 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
2985 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
2986 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
2987 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
2988 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
2989 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
2990 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
2991 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
2992 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
2993 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
2994 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
2995 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
2996 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
2997 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
2998 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
2999 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
3000 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3001 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3002 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3003 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3004 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3005 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3006 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3007 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3008 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3009 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3010 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3011 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3012 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3013 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3014 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3015 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3016 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3017 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3018 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3019 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3020 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3021 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3022 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3023 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3024 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3025 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3026 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3027 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3030 /*******************************************************************
3031 Return the variable_type of info_data structure.
3032 ********************************************************************/
3034 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3039 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3040 if ( (notify_info_data_table
[i
].type
== type
) &&
3041 (notify_info_data_table
[i
].field
== field
) ) {
3042 return notify_info_data_table
[i
].variable_type
;
3046 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3051 /****************************************************************************
3052 ****************************************************************************/
3054 static bool search_notify(enum spoolss_NotifyType type
,
3060 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3061 if (notify_info_data_table
[i
].type
== type
&&
3062 notify_info_data_table
[i
].field
== field
&&
3063 notify_info_data_table
[i
].fn
!= NULL
) {
3072 /****************************************************************************
3073 ****************************************************************************/
3075 void construct_info_data(struct spoolss_Notify
*info_data
,
3076 enum spoolss_NotifyType type
,
3080 info_data
->type
= type
;
3081 info_data
->field
.field
= field
;
3082 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3083 info_data
->job_id
= id
;
3086 /*******************************************************************
3088 * fill a notify_info struct with info asked
3090 ********************************************************************/
3092 static bool construct_notify_printer_info(Printer_entry
*print_hnd
,
3093 struct spoolss_NotifyInfo
*info
,
3095 const struct spoolss_NotifyOptionType
*option_type
,
3097 TALLOC_CTX
*mem_ctx
)
3100 enum spoolss_NotifyType type
;
3103 struct spoolss_Notify
*current_data
;
3104 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3105 print_queue_struct
*queue
=NULL
;
3107 type
= option_type
->type
;
3109 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3110 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3111 option_type
->count
, lp_servicename(snum
)));
3113 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3116 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3117 field
= option_type
->fields
[field_num
].field
;
3119 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3121 if (!search_notify(type
, field
, &j
) )
3124 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3125 struct spoolss_Notify
,
3127 if (info
->notifies
== NULL
) {
3128 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3129 free_a_printer(&printer
, 2);
3133 current_data
= &info
->notifies
[info
->count
];
3135 construct_info_data(current_data
, type
, field
, id
);
3137 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3138 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3140 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3146 free_a_printer(&printer
, 2);
3150 /*******************************************************************
3152 * fill a notify_info struct with info asked
3154 ********************************************************************/
3156 static bool construct_notify_jobs_info(print_queue_struct
*queue
,
3157 struct spoolss_NotifyInfo
*info
,
3158 NT_PRINTER_INFO_LEVEL
*printer
,
3160 const struct spoolss_NotifyOptionType
*option_type
,
3162 TALLOC_CTX
*mem_ctx
)
3165 enum spoolss_NotifyType type
;
3167 struct spoolss_Notify
*current_data
;
3169 DEBUG(4,("construct_notify_jobs_info\n"));
3171 type
= option_type
->type
;
3173 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3174 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3175 option_type
->count
));
3177 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3178 field
= option_type
->fields
[field_num
].field
;
3180 if (!search_notify(type
, field
, &j
) )
3183 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3184 struct spoolss_Notify
,
3186 if (info
->notifies
== NULL
) {
3187 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3191 current_data
=&(info
->notifies
[info
->count
]);
3193 construct_info_data(current_data
, type
, field
, id
);
3194 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3203 * JFM: The enumeration is not that simple, it's even non obvious.
3205 * let's take an example: I want to monitor the PRINTER SERVER for
3206 * the printer's name and the number of jobs currently queued.
3207 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3208 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3210 * I have 3 printers on the back of my server.
3212 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3215 * 1 printer 1 name 1
3216 * 2 printer 1 cjob 1
3217 * 3 printer 2 name 2
3218 * 4 printer 2 cjob 2
3219 * 5 printer 3 name 3
3220 * 6 printer 3 name 3
3222 * that's the print server case, the printer case is even worse.
3225 /*******************************************************************
3227 * enumerate all printers on the printserver
3228 * fill a notify_info struct with info asked
3230 ********************************************************************/
3232 static WERROR
printserver_notify_info(pipes_struct
*p
,
3233 struct policy_handle
*hnd
,
3234 struct spoolss_NotifyInfo
*info
,
3235 TALLOC_CTX
*mem_ctx
)
3238 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3239 int n_services
=lp_numservices();
3241 struct spoolss_NotifyOption
*option
;
3242 struct spoolss_NotifyOptionType option_type
;
3244 DEBUG(4,("printserver_notify_info\n"));
3249 option
= Printer
->notify
.option
;
3252 info
->notifies
= NULL
;
3255 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3256 sending a ffpcn() request first */
3261 for (i
=0; i
<option
->count
; i
++) {
3262 option_type
= option
->types
[i
];
3264 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3267 for (snum
=0; snum
<n_services
; snum
++)
3269 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3270 construct_notify_printer_info ( Printer
, info
, snum
, &option_type
, snum
, mem_ctx
);
3276 * Debugging information, don't delete.
3279 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3280 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3281 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3283 for (i
=0; i
<info
->count
; i
++) {
3284 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3285 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3286 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3293 /*******************************************************************
3295 * fill a notify_info struct with info asked
3297 ********************************************************************/
3299 static WERROR
printer_notify_info(pipes_struct
*p
, struct policy_handle
*hnd
,
3300 struct spoolss_NotifyInfo
*info
,
3301 TALLOC_CTX
*mem_ctx
)
3304 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3307 struct spoolss_NotifyOption
*option
;
3308 struct spoolss_NotifyOptionType option_type
;
3310 print_queue_struct
*queue
=NULL
;
3311 print_status_struct status
;
3313 DEBUG(4,("printer_notify_info\n"));
3318 option
= Printer
->notify
.option
;
3322 info
->notifies
= NULL
;
3325 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3326 sending a ffpcn() request first */
3331 get_printer_snum(p
, hnd
, &snum
, NULL
);
3333 for (i
=0; i
<option
->count
; i
++) {
3334 option_type
= option
->types
[i
];
3336 switch (option_type
.type
) {
3337 case PRINTER_NOTIFY_TYPE
:
3338 if(construct_notify_printer_info(Printer
, info
, snum
,
3344 case JOB_NOTIFY_TYPE
: {
3345 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3347 count
= print_queue_status(snum
, &queue
, &status
);
3349 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3352 for (j
=0; j
<count
; j
++) {
3353 construct_notify_jobs_info(&queue
[j
], info
,
3360 free_a_printer(&printer
, 2);
3370 * Debugging information, don't delete.
3373 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3374 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3375 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3377 for (i=0; i<info->count; i++) {
3378 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3379 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3380 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3386 /****************************************************************
3387 _spoolss_RouterRefreshPrinterChangeNotify
3388 ****************************************************************/
3390 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(pipes_struct
*p
,
3391 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3393 struct spoolss_NotifyInfo
*info
;
3395 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3396 WERROR result
= WERR_BADFID
;
3398 /* we always have a spoolss_NotifyInfo struct */
3399 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3401 result
= WERR_NOMEM
;
3405 *r
->out
.info
= info
;
3408 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3409 "Invalid handle (%s:%u:%u).\n",
3410 OUR_HANDLE(r
->in
.handle
)));
3414 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3417 * We are now using the change value, and
3418 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3419 * I don't have a global notification system, I'm sending back all the
3420 * informations even when _NOTHING_ has changed.
3423 /* We need to keep track of the change value to send back in
3424 RRPCN replies otherwise our updates are ignored. */
3426 Printer
->notify
.fnpcn
= true;
3428 if (Printer
->notify
.client_connected
) {
3429 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3430 "Saving change value in request [%x]\n",
3432 Printer
->notify
.change
= r
->in
.change_low
;
3435 /* just ignore the spoolss_NotifyOption */
3437 switch (Printer
->printer_type
) {
3439 result
= printserver_notify_info(p
, r
->in
.handle
,
3443 case SPLHND_PRINTER
:
3444 result
= printer_notify_info(p
, r
->in
.handle
,
3449 Printer
->notify
.fnpcn
= false;
3455 /********************************************************************
3456 * construct_printer_info_0
3457 * fill a printer_info_0 struct
3458 ********************************************************************/
3460 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3461 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3462 struct spoolss_PrinterInfo0
*r
,
3466 counter_printer_0
*session_counter
;
3468 print_status_struct status
;
3470 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3471 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3473 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3474 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3476 count
= print_queue_length(snum
, &status
);
3478 /* check if we already have a counter for this printer */
3479 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3480 if (session_counter
->snum
== snum
)
3484 /* it's the first time, add it to the list */
3485 if (session_counter
== NULL
) {
3486 session_counter
= SMB_MALLOC_P(counter_printer_0
);
3487 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3488 ZERO_STRUCTP(session_counter
);
3489 session_counter
->snum
= snum
;
3490 session_counter
->counter
= 0;
3491 DLIST_ADD(counter_list
, session_counter
);
3495 session_counter
->counter
++;
3501 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3503 init_systemtime(&r
->time
, gmtime(&setuptime
));
3506 * the global_counter should be stored in a TDB as it's common to all the clients
3507 * and should be zeroed on samba startup
3509 r
->global_counter
= session_counter
->counter
;
3511 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3512 SSVAL(&r
->version
, 0, 0x0005); /* NT 5 */
3513 SSVAL(&r
->version
, 2, 0x0893); /* build 2195 */
3514 r
->free_build
= SPOOLSS_RELEASE_BUILD
;
3516 r
->max_spooling
= 0;
3517 r
->session_counter
= session_counter
->counter
;
3518 r
->num_error_out_of_paper
= 0x0;
3519 r
->num_error_not_ready
= 0x0; /* number of print failure */
3521 r
->number_of_processors
= 0x1;
3522 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3523 r
->high_part_total_bytes
= 0x0;
3524 r
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3525 r
->last_error
= WERR_OK
;
3526 r
->status
= nt_printq_status(status
.status
);
3527 r
->enumerate_network_printers
= 0x0;
3528 r
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3529 r
->processor_architecture
= 0x0;
3530 r
->processor_level
= 0x6; /* 6 ???*/
3538 /****************************************************************************
3539 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3540 should be valid upon entry
3541 ****************************************************************************/
3543 static WERROR
convert_nt_devicemode(TALLOC_CTX
*mem_ctx
,
3544 struct spoolss_DeviceMode
*r
,
3545 const NT_DEVICEMODE
*ntdevmode
)
3547 if (!r
|| !ntdevmode
) {
3548 return WERR_INVALID_PARAM
;
3551 r
->devicename
= talloc_strdup(mem_ctx
, ntdevmode
->devicename
);
3552 W_ERROR_HAVE_NO_MEMORY(r
->devicename
);
3554 r
->specversion
= ntdevmode
->specversion
;
3555 r
->driverversion
= ntdevmode
->driverversion
;
3556 r
->size
= ntdevmode
->size
;
3557 r
->__driverextra_length
= ntdevmode
->driverextra
;
3558 r
->fields
= ntdevmode
->fields
;
3560 r
->orientation
= ntdevmode
->orientation
;
3561 r
->papersize
= ntdevmode
->papersize
;
3562 r
->paperlength
= ntdevmode
->paperlength
;
3563 r
->paperwidth
= ntdevmode
->paperwidth
;
3564 r
->scale
= ntdevmode
->scale
;
3565 r
->copies
= ntdevmode
->copies
;
3566 r
->defaultsource
= ntdevmode
->defaultsource
;
3567 r
->printquality
= ntdevmode
->printquality
;
3568 r
->color
= ntdevmode
->color
;
3569 r
->duplex
= ntdevmode
->duplex
;
3570 r
->yresolution
= ntdevmode
->yresolution
;
3571 r
->ttoption
= ntdevmode
->ttoption
;
3572 r
->collate
= ntdevmode
->collate
;
3574 r
->formname
= talloc_strdup(mem_ctx
, ntdevmode
->formname
);
3575 W_ERROR_HAVE_NO_MEMORY(r
->formname
);
3577 r
->logpixels
= ntdevmode
->logpixels
;
3578 r
->bitsperpel
= ntdevmode
->bitsperpel
;
3579 r
->pelswidth
= ntdevmode
->pelswidth
;
3580 r
->pelsheight
= ntdevmode
->pelsheight
;
3581 r
->displayflags
= ntdevmode
->displayflags
;
3582 r
->displayfrequency
= ntdevmode
->displayfrequency
;
3583 r
->icmmethod
= ntdevmode
->icmmethod
;
3584 r
->icmintent
= ntdevmode
->icmintent
;
3585 r
->mediatype
= ntdevmode
->mediatype
;
3586 r
->dithertype
= ntdevmode
->dithertype
;
3587 r
->reserved1
= ntdevmode
->reserved1
;
3588 r
->reserved2
= ntdevmode
->reserved2
;
3589 r
->panningwidth
= ntdevmode
->panningwidth
;
3590 r
->panningheight
= ntdevmode
->panningheight
;
3592 if (ntdevmode
->nt_dev_private
!= NULL
) {
3593 r
->driverextra_data
= data_blob_talloc(mem_ctx
,
3594 ntdevmode
->nt_dev_private
,
3595 ntdevmode
->driverextra
);
3596 W_ERROR_HAVE_NO_MEMORY(r
->driverextra_data
.data
);
3603 /****************************************************************************
3604 Create a spoolss_DeviceMode struct. Returns talloced memory.
3605 ****************************************************************************/
3607 struct spoolss_DeviceMode
*construct_dev_mode(TALLOC_CTX
*mem_ctx
,
3608 const char *servicename
)
3611 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3612 struct spoolss_DeviceMode
*devmode
= NULL
;
3614 DEBUG(7,("construct_dev_mode\n"));
3616 DEBUGADD(8,("getting printer characteristics\n"));
3618 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
3621 if (!printer
->info_2
->devmode
) {
3622 DEBUG(5, ("BONG! There was no device mode!\n"));
3626 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
3628 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3632 DEBUGADD(8,("loading DEVICEMODE\n"));
3634 result
= convert_nt_devicemode(mem_ctx
, devmode
, printer
->info_2
->devmode
);
3635 if (!W_ERROR_IS_OK(result
)) {
3636 TALLOC_FREE(devmode
);
3640 free_a_printer(&printer
,2);
3645 /********************************************************************
3646 * construct_printer_info1
3647 * fill a spoolss_PrinterInfo1 struct
3648 ********************************************************************/
3650 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
3651 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3653 struct spoolss_PrinterInfo1
*r
,
3658 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
3659 ntprinter
->info_2
->printername
,
3660 ntprinter
->info_2
->drivername
,
3661 ntprinter
->info_2
->location
);
3662 W_ERROR_HAVE_NO_MEMORY(r
->description
);
3664 if (*ntprinter
->info_2
->comment
== '\0') {
3665 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3667 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
); /* saved comment */
3669 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3671 r
->name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3672 W_ERROR_HAVE_NO_MEMORY(r
->name
);
3677 /********************************************************************
3678 * construct_printer_info2
3679 * fill a spoolss_PrinterInfo2 struct
3680 ********************************************************************/
3682 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
3683 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3684 struct spoolss_PrinterInfo2
*r
,
3689 print_status_struct status
;
3691 count
= print_queue_length(snum
, &status
);
3693 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3694 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3695 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3696 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3697 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
3698 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
3699 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
3700 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3701 r
->drivername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
3702 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
3704 if (*ntprinter
->info_2
->comment
== '\0') {
3705 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3707 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
);
3709 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3711 r
->location
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->location
);
3712 W_ERROR_HAVE_NO_MEMORY(r
->location
);
3713 r
->sepfile
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->sepfile
);
3714 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
3715 r
->printprocessor
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printprocessor
);
3716 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
3717 r
->datatype
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->datatype
);
3718 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
3719 r
->parameters
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->parameters
);
3720 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
3722 r
->attributes
= ntprinter
->info_2
->attributes
;
3724 r
->priority
= ntprinter
->info_2
->priority
;
3725 r
->defaultpriority
= ntprinter
->info_2
->default_priority
;
3726 r
->starttime
= ntprinter
->info_2
->starttime
;
3727 r
->untiltime
= ntprinter
->info_2
->untiltime
;
3728 r
->status
= nt_printq_status(status
.status
);
3730 r
->averageppm
= ntprinter
->info_2
->averageppm
;
3732 r
->devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
3734 DEBUG(8,("Returning NULL Devicemode!\n"));
3739 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
3740 /* don't use talloc_steal() here unless you do a deep steal of all
3741 the SEC_DESC members */
3743 r
->secdesc
= dup_sec_desc(mem_ctx
, ntprinter
->info_2
->secdesc_buf
->sd
);
3749 /********************************************************************
3750 * construct_printer_info3
3751 * fill a spoolss_PrinterInfo3 struct
3752 ********************************************************************/
3754 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
3755 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3756 struct spoolss_PrinterInfo3
*r
,
3759 /* These are the components of the SD we are returning. */
3761 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
3762 /* don't use talloc_steal() here unless you do a deep steal of all
3763 the SEC_DESC members */
3765 r
->secdesc
= dup_sec_desc(mem_ctx
,
3766 ntprinter
->info_2
->secdesc_buf
->sd
);
3767 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
3773 /********************************************************************
3774 * construct_printer_info4
3775 * fill a spoolss_PrinterInfo4 struct
3776 ********************************************************************/
3778 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
3779 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3780 struct spoolss_PrinterInfo4
*r
,
3783 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3784 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3785 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3786 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3788 r
->attributes
= ntprinter
->info_2
->attributes
;
3793 /********************************************************************
3794 * construct_printer_info5
3795 * fill a spoolss_PrinterInfo5 struct
3796 ********************************************************************/
3798 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
3799 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3800 struct spoolss_PrinterInfo5
*r
,
3803 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3804 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3805 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
3806 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3808 r
->attributes
= ntprinter
->info_2
->attributes
;
3810 /* these two are not used by NT+ according to MSDN */
3812 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
3813 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
3818 /********************************************************************
3819 * construct_printer_info_6
3820 * fill a spoolss_PrinterInfo6 struct
3821 ********************************************************************/
3823 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
3824 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3825 struct spoolss_PrinterInfo6
*r
,
3829 print_status_struct status
;
3831 count
= print_queue_length(snum
, &status
);
3833 r
->status
= nt_printq_status(status
.status
);
3838 /********************************************************************
3839 * construct_printer_info7
3840 * fill a spoolss_PrinterInfo7 struct
3841 ********************************************************************/
3843 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
3844 Printer_entry
*print_hnd
,
3845 struct spoolss_PrinterInfo7
*r
,
3850 if (is_printer_published(print_hnd
, snum
, &guid
)) {
3851 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
3852 r
->action
= DSPRINT_PUBLISH
;
3854 r
->guid
= talloc_strdup(mem_ctx
, "");
3855 r
->action
= DSPRINT_UNPUBLISH
;
3857 W_ERROR_HAVE_NO_MEMORY(r
->guid
);
3862 /********************************************************************
3863 * construct_printer_info8
3864 * fill a spoolss_PrinterInfo8 struct
3865 ********************************************************************/
3867 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
3868 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3869 struct spoolss_DeviceModeInfo
*r
,
3872 r
->devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
3874 DEBUG(8,("Returning NULL Devicemode!\n"));
3881 /********************************************************************
3882 ********************************************************************/
3884 static bool snum_is_shared_printer(int snum
)
3886 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
3889 /********************************************************************
3890 Spoolss_enumprinters.
3891 ********************************************************************/
3893 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
3896 union spoolss_PrinterInfo
**info_p
,
3900 int n_services
= lp_numservices();
3901 union spoolss_PrinterInfo
*info
= NULL
;
3903 WERROR result
= WERR_OK
;
3908 for (snum
= 0; snum
< n_services
; snum
++) {
3910 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3912 if (!snum_is_shared_printer(snum
)) {
3916 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3917 lp_servicename(snum
), snum
));
3919 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
3920 union spoolss_PrinterInfo
,
3923 result
= WERR_NOMEM
;
3927 result
= get_a_printer(NULL
, &ntprinter
, 2,
3928 lp_const_servicename(snum
));
3929 if (!W_ERROR_IS_OK(result
)) {
3935 result
= construct_printer_info0(info
, ntprinter
,
3936 &info
[count
].info0
, snum
);
3939 result
= construct_printer_info1(info
, ntprinter
, flags
,
3940 &info
[count
].info1
, snum
);
3943 result
= construct_printer_info2(info
, ntprinter
,
3944 &info
[count
].info2
, snum
);
3947 result
= construct_printer_info4(info
, ntprinter
,
3948 &info
[count
].info4
, snum
);
3951 result
= construct_printer_info5(info
, ntprinter
,
3952 &info
[count
].info5
, snum
);
3956 result
= WERR_UNKNOWN_LEVEL
;
3957 free_a_printer(&ntprinter
, 2);
3961 free_a_printer(&ntprinter
, 2);
3962 if (!W_ERROR_IS_OK(result
)) {
3973 if (!W_ERROR_IS_OK(result
)) {
3983 /********************************************************************
3984 * handle enumeration of printers at level 0
3985 ********************************************************************/
3987 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
3989 const char *servername
,
3990 union spoolss_PrinterInfo
**info
,
3993 DEBUG(4,("enum_all_printers_info_0\n"));
3995 return enum_all_printers_info_level(mem_ctx
, 0, flags
, info
, count
);
3999 /********************************************************************
4000 ********************************************************************/
4002 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4004 union spoolss_PrinterInfo
**info
,
4007 DEBUG(4,("enum_all_printers_info_1\n"));
4009 return enum_all_printers_info_level(mem_ctx
, 1, flags
, info
, count
);
4012 /********************************************************************
4013 enum_all_printers_info_1_local.
4014 *********************************************************************/
4016 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4017 union spoolss_PrinterInfo
**info
,
4020 DEBUG(4,("enum_all_printers_info_1_local\n"));
4022 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4025 /********************************************************************
4026 enum_all_printers_info_1_name.
4027 *********************************************************************/
4029 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4031 union spoolss_PrinterInfo
**info
,
4034 const char *s
= name
;
4036 DEBUG(4,("enum_all_printers_info_1_name\n"));
4038 if ((name
[0] == '\\') && (name
[1] == '\\')) {
4042 if (!is_myname_or_ipaddr(s
)) {
4043 return WERR_INVALID_NAME
;
4046 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4049 /********************************************************************
4050 enum_all_printers_info_1_network.
4051 *********************************************************************/
4053 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4055 union spoolss_PrinterInfo
**info
,
4058 const char *s
= name
;
4060 DEBUG(4,("enum_all_printers_info_1_network\n"));
4062 /* If we respond to a enum_printers level 1 on our name with flags
4063 set to PRINTER_ENUM_REMOTE with a list of printers then these
4064 printers incorrectly appear in the APW browse list.
4065 Specifically the printers for the server appear at the workgroup
4066 level where all the other servers in the domain are
4067 listed. Windows responds to this call with a
4068 WERR_CAN_NOT_COMPLETE so we should do the same. */
4070 if (name
[0] == '\\' && name
[1] == '\\') {
4074 if (is_myname_or_ipaddr(s
)) {
4075 return WERR_CAN_NOT_COMPLETE
;
4078 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_NAME
, info
, count
);
4081 /********************************************************************
4082 * api_spoolss_enumprinters
4084 * called from api_spoolss_enumprinters (see this to understand)
4085 ********************************************************************/
4087 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4088 union spoolss_PrinterInfo
**info
,
4091 DEBUG(4,("enum_all_printers_info_2\n"));
4093 return enum_all_printers_info_level(mem_ctx
, 2, 0, info
, count
);
4096 /********************************************************************
4097 * handle enumeration of printers at level 1
4098 ********************************************************************/
4100 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4103 union spoolss_PrinterInfo
**info
,
4106 /* Not all the flags are equals */
4108 if (flags
& PRINTER_ENUM_LOCAL
) {
4109 return enum_all_printers_info_1_local(mem_ctx
, info
, count
);
4112 if (flags
& PRINTER_ENUM_NAME
) {
4113 return enum_all_printers_info_1_name(mem_ctx
, name
, info
, count
);
4116 if (flags
& PRINTER_ENUM_NETWORK
) {
4117 return enum_all_printers_info_1_network(mem_ctx
, name
, info
, count
);
4120 return WERR_OK
; /* NT4sp5 does that */
4123 /********************************************************************
4124 * handle enumeration of printers at level 2
4125 ********************************************************************/
4127 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4129 const char *servername
,
4130 union spoolss_PrinterInfo
**info
,
4133 if (flags
& PRINTER_ENUM_LOCAL
) {
4134 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4137 if (flags
& PRINTER_ENUM_NAME
) {
4138 if (!is_myname_or_ipaddr(canon_servername(servername
))) {
4139 return WERR_INVALID_NAME
;
4142 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4145 if (flags
& PRINTER_ENUM_REMOTE
) {
4146 return WERR_UNKNOWN_LEVEL
;
4152 /********************************************************************
4153 * handle enumeration of printers at level 4
4154 ********************************************************************/
4156 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4158 const char *servername
,
4159 union spoolss_PrinterInfo
**info
,
4162 DEBUG(4,("enum_all_printers_info_4\n"));
4164 return enum_all_printers_info_level(mem_ctx
, 4, flags
, info
, count
);
4168 /********************************************************************
4169 * handle enumeration of printers at level 5
4170 ********************************************************************/
4172 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4174 const char *servername
,
4175 union spoolss_PrinterInfo
**info
,
4178 DEBUG(4,("enum_all_printers_info_5\n"));
4180 return enum_all_printers_info_level(mem_ctx
, 5, flags
, info
, count
);
4183 /****************************************************************
4184 _spoolss_EnumPrinters
4185 ****************************************************************/
4187 WERROR
_spoolss_EnumPrinters(pipes_struct
*p
,
4188 struct spoolss_EnumPrinters
*r
)
4190 const char *name
= NULL
;
4193 /* that's an [in out] buffer */
4195 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4196 return WERR_INVALID_PARAM
;
4199 DEBUG(4,("_spoolss_EnumPrinters\n"));
4203 *r
->out
.info
= NULL
;
4207 * flags==PRINTER_ENUM_NAME
4208 * if name=="" then enumerates all printers
4209 * if name!="" then enumerate the printer
4210 * flags==PRINTER_ENUM_REMOTE
4211 * name is NULL, enumerate printers
4212 * Level 2: name!="" enumerates printers, name can't be NULL
4213 * Level 3: doesn't exist
4214 * Level 4: does a local registry lookup
4215 * Level 5: same as Level 2
4219 name
= talloc_strdup_upper(p
->mem_ctx
, r
->in
.server
);
4220 W_ERROR_HAVE_NO_MEMORY(name
);
4223 switch (r
->in
.level
) {
4225 result
= enumprinters_level0(p
->mem_ctx
, r
->in
.flags
, name
,
4226 r
->out
.info
, r
->out
.count
);
4229 result
= enumprinters_level1(p
->mem_ctx
, r
->in
.flags
, name
,
4230 r
->out
.info
, r
->out
.count
);
4233 result
= enumprinters_level2(p
->mem_ctx
, r
->in
.flags
, name
,
4234 r
->out
.info
, r
->out
.count
);
4237 result
= enumprinters_level4(p
->mem_ctx
, r
->in
.flags
, name
,
4238 r
->out
.info
, r
->out
.count
);
4241 result
= enumprinters_level5(p
->mem_ctx
, r
->in
.flags
, name
,
4242 r
->out
.info
, r
->out
.count
);
4245 return WERR_UNKNOWN_LEVEL
;
4248 if (!W_ERROR_IS_OK(result
)) {
4252 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4253 spoolss_EnumPrinters
,
4254 *r
->out
.info
, r
->in
.level
,
4256 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4257 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4259 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4262 /****************************************************************
4264 ****************************************************************/
4266 WERROR
_spoolss_GetPrinter(pipes_struct
*p
,
4267 struct spoolss_GetPrinter
*r
)
4269 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4270 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4271 WERROR result
= WERR_OK
;
4275 /* that's an [in out] buffer */
4277 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4278 return WERR_INVALID_PARAM
;
4283 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4287 result
= get_a_printer(Printer
, &ntprinter
, 2,
4288 lp_const_servicename(snum
));
4289 if (!W_ERROR_IS_OK(result
)) {
4293 switch (r
->in
.level
) {
4295 result
= construct_printer_info0(p
->mem_ctx
, ntprinter
,
4296 &r
->out
.info
->info0
, snum
);
4299 result
= construct_printer_info1(p
->mem_ctx
, ntprinter
,
4301 &r
->out
.info
->info1
, snum
);
4304 result
= construct_printer_info2(p
->mem_ctx
, ntprinter
,
4305 &r
->out
.info
->info2
, snum
);
4308 result
= construct_printer_info3(p
->mem_ctx
, ntprinter
,
4309 &r
->out
.info
->info3
, snum
);
4312 result
= construct_printer_info4(p
->mem_ctx
, ntprinter
,
4313 &r
->out
.info
->info4
, snum
);
4316 result
= construct_printer_info5(p
->mem_ctx
, ntprinter
,
4317 &r
->out
.info
->info5
, snum
);
4320 result
= construct_printer_info6(p
->mem_ctx
, ntprinter
,
4321 &r
->out
.info
->info6
, snum
);
4324 result
= construct_printer_info7(p
->mem_ctx
, Printer
,
4325 &r
->out
.info
->info7
, snum
);
4328 result
= construct_printer_info8(p
->mem_ctx
, ntprinter
,
4329 &r
->out
.info
->info8
, snum
);
4332 result
= WERR_UNKNOWN_LEVEL
;
4336 free_a_printer(&ntprinter
, 2);
4338 if (!W_ERROR_IS_OK(result
)) {
4339 TALLOC_FREE(r
->out
.info
);
4343 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
,
4344 r
->out
.info
, r
->in
.level
);
4345 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4347 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4350 /********************************************************************
4351 ********************************************************************/
4353 static const char **string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4354 const char **string_array
,
4355 const char *cservername
)
4357 int i
, num_strings
= 0;
4358 const char **array
= NULL
;
4360 if (!string_array
) {
4364 for (i
=0; string_array
[i
] && string_array
[i
][0] != '\0'; i
++) {
4366 const char *str
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4367 cservername
, string_array
[i
]);
4374 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4381 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4382 &array
, &num_strings
);
4388 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4390 if (in && strlen(in)) { \
4391 out = talloc_strdup(mem_ctx, in); \
4392 W_ERROR_HAVE_NO_MEMORY(out); \
4398 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4400 if (in && strlen(in)) { \
4401 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4403 out = talloc_strdup(mem_ctx, ""); \
4405 W_ERROR_HAVE_NO_MEMORY(out); \
4408 /********************************************************************
4409 * fill a spoolss_DriverInfo1 struct
4410 ********************************************************************/
4412 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4413 struct spoolss_DriverInfo1
*r
,
4414 const struct spoolss_DriverInfo8
*driver
,
4415 const char *servername
)
4417 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4418 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4423 /********************************************************************
4424 * fill a spoolss_DriverInfo2 struct
4425 ********************************************************************/
4427 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4428 struct spoolss_DriverInfo2
*r
,
4429 const struct spoolss_DriverInfo8
*driver
,
4430 const char *servername
)
4433 const char *cservername
= canon_servername(servername
);
4435 r
->version
= driver
->version
;
4437 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4438 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4439 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4440 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4442 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4443 driver
->driver_path
,
4446 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4450 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4451 driver
->config_file
,
4457 /********************************************************************
4458 * fill a spoolss_DriverInfo3 struct
4459 ********************************************************************/
4461 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4462 struct spoolss_DriverInfo3
*r
,
4463 const struct spoolss_DriverInfo8
*driver
,
4464 const char *servername
)
4466 const char *cservername
= canon_servername(servername
);
4468 r
->version
= driver
->version
;
4470 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4471 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4472 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4473 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4475 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4476 driver
->driver_path
,
4479 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4483 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4484 driver
->config_file
,
4487 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4491 FILL_DRIVER_STRING(mem_ctx
,
4492 driver
->monitor_name
,
4495 FILL_DRIVER_STRING(mem_ctx
,
4496 driver
->default_datatype
,
4497 r
->default_datatype
);
4499 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4500 driver
->dependent_files
,
4505 /********************************************************************
4506 * fill a spoolss_DriverInfo4 struct
4507 ********************************************************************/
4509 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
4510 struct spoolss_DriverInfo4
*r
,
4511 const struct spoolss_DriverInfo8
*driver
,
4512 const char *servername
)
4514 const char *cservername
= canon_servername(servername
);
4516 r
->version
= driver
->version
;
4518 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4519 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4520 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4521 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4523 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4524 driver
->driver_path
,
4527 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4531 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4532 driver
->config_file
,
4535 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4539 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4540 driver
->dependent_files
,
4543 FILL_DRIVER_STRING(mem_ctx
,
4544 driver
->monitor_name
,
4547 FILL_DRIVER_STRING(mem_ctx
,
4548 driver
->default_datatype
,
4549 r
->default_datatype
);
4551 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4552 driver
->previous_names
,
4558 /********************************************************************
4559 * fill a spoolss_DriverInfo5 struct
4560 ********************************************************************/
4562 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
4563 struct spoolss_DriverInfo5
*r
,
4564 const struct spoolss_DriverInfo8
*driver
,
4565 const char *servername
)
4567 const char *cservername
= canon_servername(servername
);
4569 r
->version
= driver
->version
;
4571 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4572 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4573 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4574 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4576 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4577 driver
->driver_path
,
4580 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4584 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4585 driver
->config_file
,
4588 r
->driver_attributes
= 0;
4589 r
->config_version
= 0;
4590 r
->driver_version
= 0;
4594 /********************************************************************
4595 * fill a spoolss_DriverInfo6 struct
4596 ********************************************************************/
4598 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
4599 struct spoolss_DriverInfo6
*r
,
4600 const struct spoolss_DriverInfo8
*driver
,
4601 const char *servername
)
4603 const char *cservername
= canon_servername(servername
);
4605 r
->version
= driver
->version
;
4607 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4608 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4609 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4610 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4612 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4613 driver
->driver_path
,
4616 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4620 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4621 driver
->config_file
,
4624 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4628 FILL_DRIVER_STRING(mem_ctx
,
4629 driver
->monitor_name
,
4632 FILL_DRIVER_STRING(mem_ctx
,
4633 driver
->default_datatype
,
4634 r
->default_datatype
);
4636 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4637 driver
->dependent_files
,
4639 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4640 driver
->previous_names
,
4643 r
->driver_date
= driver
->driver_date
;
4644 r
->driver_version
= driver
->driver_version
;
4646 FILL_DRIVER_STRING(mem_ctx
,
4647 driver
->manufacturer_name
,
4648 r
->manufacturer_name
);
4649 FILL_DRIVER_STRING(mem_ctx
,
4650 driver
->manufacturer_url
,
4651 r
->manufacturer_url
);
4652 FILL_DRIVER_STRING(mem_ctx
,
4653 driver
->hardware_id
,
4655 FILL_DRIVER_STRING(mem_ctx
,
4662 /********************************************************************
4663 * fill a spoolss_DriverInfo8 struct
4664 ********************************************************************/
4666 static WERROR
fill_printer_driver_info8(TALLOC_CTX
*mem_ctx
,
4667 struct spoolss_DriverInfo8
*r
,
4668 const struct spoolss_DriverInfo8
*driver
,
4669 const char *servername
)
4671 const char *cservername
= canon_servername(servername
);
4673 r
->version
= driver
->version
;
4675 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4676 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4677 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4678 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4680 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4681 driver
->driver_path
,
4684 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4688 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4689 driver
->config_file
,
4692 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4696 FILL_DRIVER_STRING(mem_ctx
,
4697 driver
->monitor_name
,
4700 FILL_DRIVER_STRING(mem_ctx
,
4701 driver
->default_datatype
,
4702 r
->default_datatype
);
4704 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4705 driver
->dependent_files
,
4707 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4708 driver
->previous_names
,
4711 r
->driver_date
= driver
->driver_date
;
4712 r
->driver_version
= driver
->driver_version
;
4714 FILL_DRIVER_STRING(mem_ctx
,
4715 driver
->manufacturer_name
,
4716 r
->manufacturer_name
);
4717 FILL_DRIVER_STRING(mem_ctx
,
4718 driver
->manufacturer_url
,
4719 r
->manufacturer_url
);
4720 FILL_DRIVER_STRING(mem_ctx
,
4721 driver
->hardware_id
,
4723 FILL_DRIVER_STRING(mem_ctx
,
4727 FILL_DRIVER_STRING(mem_ctx
,
4728 driver
->print_processor
,
4729 r
->print_processor
);
4730 FILL_DRIVER_STRING(mem_ctx
,
4731 driver
->vendor_setup
,
4734 r
->color_profiles
= string_array_from_driver_info(mem_ctx
,
4735 driver
->color_profiles
,
4738 FILL_DRIVER_STRING(mem_ctx
,
4742 r
->printer_driver_attributes
= driver
->printer_driver_attributes
;
4744 r
->core_driver_dependencies
= string_array_from_driver_info(mem_ctx
,
4745 driver
->core_driver_dependencies
,
4748 r
->min_inbox_driver_ver_date
= driver
->min_inbox_driver_ver_date
;
4749 r
->min_inbox_driver_ver_version
= driver
->min_inbox_driver_ver_version
;
4754 #if 0 /* disabled until marshalling issues are resolved - gd */
4755 /********************************************************************
4756 ********************************************************************/
4758 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
4759 struct spoolss_DriverFileInfo
*r
,
4760 const char *cservername
,
4761 const char *file_name
,
4762 enum spoolss_DriverFileType file_type
,
4763 uint32_t file_version
)
4765 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4766 cservername
, file_name
);
4767 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
4768 r
->file_type
= file_type
;
4769 r
->file_version
= file_version
;
4774 /********************************************************************
4775 ********************************************************************/
4777 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
4778 const struct spoolss_DriverInfo8
*driver
,
4779 const char *cservername
,
4780 struct spoolss_DriverFileInfo
**info_p
,
4783 struct spoolss_DriverFileInfo
*info
= NULL
;
4791 if (strlen(driver
->driver_path
)) {
4792 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4793 struct spoolss_DriverFileInfo
,
4795 W_ERROR_HAVE_NO_MEMORY(info
);
4796 result
= fill_spoolss_DriverFileInfo(info
,
4799 driver
->driver_path
,
4800 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
4802 W_ERROR_NOT_OK_RETURN(result
);
4806 if (strlen(driver
->config_file
)) {
4807 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4808 struct spoolss_DriverFileInfo
,
4810 W_ERROR_HAVE_NO_MEMORY(info
);
4811 result
= fill_spoolss_DriverFileInfo(info
,
4814 driver
->config_file
,
4815 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
4817 W_ERROR_NOT_OK_RETURN(result
);
4821 if (strlen(driver
->data_file
)) {
4822 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4823 struct spoolss_DriverFileInfo
,
4825 W_ERROR_HAVE_NO_MEMORY(info
);
4826 result
= fill_spoolss_DriverFileInfo(info
,
4830 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
4832 W_ERROR_NOT_OK_RETURN(result
);
4836 if (strlen(driver
->help_file
)) {
4837 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4838 struct spoolss_DriverFileInfo
,
4840 W_ERROR_HAVE_NO_MEMORY(info
);
4841 result
= fill_spoolss_DriverFileInfo(info
,
4845 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
4847 W_ERROR_NOT_OK_RETURN(result
);
4851 for (i
=0; driver
->dependent_files
[i
] && driver
->dependent_files
[i
][0] != '\0'; i
++) {
4852 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4853 struct spoolss_DriverFileInfo
,
4855 W_ERROR_HAVE_NO_MEMORY(info
);
4856 result
= fill_spoolss_DriverFileInfo(info
,
4859 driver
->dependent_files
[i
],
4860 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
4862 W_ERROR_NOT_OK_RETURN(result
);
4872 /********************************************************************
4873 * fill a spoolss_DriverInfo101 struct
4874 ********************************************************************/
4876 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
4877 struct spoolss_DriverInfo101
*r
,
4878 const struct spoolss_DriverInfo8
*driver
,
4879 const char *servername
)
4881 const char *cservername
= canon_servername(servername
);
4884 r
->version
= driver
->version
;
4886 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4887 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4888 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4889 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4891 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
4895 if (!W_ERROR_IS_OK(result
)) {
4899 FILL_DRIVER_STRING(mem_ctx
,
4900 driver
->monitor_name
,
4903 FILL_DRIVER_STRING(mem_ctx
,
4904 driver
->default_datatype
,
4905 r
->default_datatype
);
4907 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4908 driver
->previous_names
,
4910 r
->driver_date
= driver
->driver_date
;
4911 r
->driver_version
= driver
->driver_version
;
4913 FILL_DRIVER_STRING(mem_ctx
,
4914 driver
->manufacturer_name
,
4915 r
->manufacturer_name
);
4916 FILL_DRIVER_STRING(mem_ctx
,
4917 driver
->manufacturer_url
,
4918 r
->manufacturer_url
);
4919 FILL_DRIVER_STRING(mem_ctx
,
4920 driver
->hardware_id
,
4922 FILL_DRIVER_STRING(mem_ctx
,
4929 /********************************************************************
4930 ********************************************************************/
4932 static WERROR
construct_printer_driver_info_level(TALLOC_CTX
*mem_ctx
,
4934 union spoolss_DriverInfo
*r
,
4936 const char *servername
,
4937 const char *architecture
,
4940 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4941 struct spoolss_DriverInfo8
*driver
;
4944 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
4946 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4947 win_errstr(result
)));
4949 if (!W_ERROR_IS_OK(result
)) {
4950 return WERR_INVALID_PRINTER_NAME
;
4953 result
= get_a_printer_driver(mem_ctx
, &driver
, printer
->info_2
->drivername
,
4954 architecture
, version
);
4956 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4957 win_errstr(result
)));
4959 if (!W_ERROR_IS_OK(result
)) {
4961 * Is this a W2k client ?
4965 free_a_printer(&printer
, 2);
4966 return WERR_UNKNOWN_PRINTER_DRIVER
;
4969 /* Yes - try again with a WinNT driver. */
4971 result
= get_a_printer_driver(mem_ctx
, &driver
, printer
->info_2
->drivername
,
4972 architecture
, version
);
4973 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4974 win_errstr(result
)));
4975 if (!W_ERROR_IS_OK(result
)) {
4976 free_a_printer(&printer
, 2);
4977 return WERR_UNKNOWN_PRINTER_DRIVER
;
4983 result
= fill_printer_driver_info1(mem_ctx
, &r
->info1
, driver
, servername
);
4986 result
= fill_printer_driver_info2(mem_ctx
, &r
->info2
, driver
, servername
);
4989 result
= fill_printer_driver_info3(mem_ctx
, &r
->info3
, driver
, servername
);
4992 result
= fill_printer_driver_info4(mem_ctx
, &r
->info4
, driver
, servername
);
4995 result
= fill_printer_driver_info5(mem_ctx
, &r
->info5
, driver
, servername
);
4998 result
= fill_printer_driver_info6(mem_ctx
, &r
->info6
, driver
, servername
);
5001 result
= fill_printer_driver_info8(mem_ctx
, &r
->info8
, driver
, servername
);
5003 #if 0 /* disabled until marshalling issues are resolved - gd */
5005 result
= fill_printer_driver_info101(mem_ctx
, &r
->info101
, driver
, servername
);
5009 result
= WERR_UNKNOWN_LEVEL
;
5013 free_a_printer(&printer
, 2);
5014 free_a_printer_driver(driver
);
5019 /****************************************************************
5020 _spoolss_GetPrinterDriver2
5021 ****************************************************************/
5023 WERROR
_spoolss_GetPrinterDriver2(pipes_struct
*p
,
5024 struct spoolss_GetPrinterDriver2
*r
)
5026 Printer_entry
*printer
;
5029 const char *servername
;
5032 /* that's an [in out] buffer */
5034 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5035 return WERR_INVALID_PARAM
;
5038 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5040 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5041 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5042 return WERR_INVALID_PRINTER_NAME
;
5046 *r
->out
.server_major_version
= 0;
5047 *r
->out
.server_minor_version
= 0;
5049 servername
= get_server_name(printer
);
5051 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5055 result
= construct_printer_driver_info_level(p
->mem_ctx
, r
->in
.level
,
5059 r
->in
.client_major_version
);
5060 if (!W_ERROR_IS_OK(result
)) {
5061 TALLOC_FREE(r
->out
.info
);
5065 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
,
5066 r
->out
.info
, r
->in
.level
);
5067 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5069 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5073 /****************************************************************
5074 _spoolss_StartPagePrinter
5075 ****************************************************************/
5077 WERROR
_spoolss_StartPagePrinter(pipes_struct
*p
,
5078 struct spoolss_StartPagePrinter
*r
)
5080 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5083 DEBUG(3,("_spoolss_StartPagePrinter: "
5084 "Error in startpageprinter printer handle\n"));
5088 Printer
->page_started
= true;
5092 /****************************************************************
5093 _spoolss_EndPagePrinter
5094 ****************************************************************/
5096 WERROR
_spoolss_EndPagePrinter(pipes_struct
*p
,
5097 struct spoolss_EndPagePrinter
*r
)
5101 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5104 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5105 OUR_HANDLE(r
->in
.handle
)));
5109 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5112 Printer
->page_started
= false;
5113 print_job_endpage(snum
, Printer
->jobid
);
5118 /****************************************************************
5119 _spoolss_StartDocPrinter
5120 ****************************************************************/
5122 WERROR
_spoolss_StartDocPrinter(pipes_struct
*p
,
5123 struct spoolss_StartDocPrinter
*r
)
5125 struct spoolss_DocumentInfo1
*info_1
;
5127 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5130 DEBUG(2,("_spoolss_StartDocPrinter: "
5131 "Invalid handle (%s:%u:%u)\n",
5132 OUR_HANDLE(r
->in
.handle
)));
5136 if (r
->in
.level
!= 1) {
5137 return WERR_UNKNOWN_LEVEL
;
5140 info_1
= r
->in
.info
.info1
;
5143 * a nice thing with NT is it doesn't listen to what you tell it.
5144 * when asked to send _only_ RAW datas, it tries to send datas
5147 * So I add checks like in NT Server ...
5150 if (info_1
->datatype
) {
5151 if (strcmp(info_1
->datatype
, "RAW") != 0) {
5153 return WERR_INVALID_DATATYPE
;
5157 /* get the share number of the printer */
5158 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5162 Printer
->jobid
= print_job_start(p
->server_info
, snum
,
5163 info_1
->document_name
,
5164 Printer
->nt_devmode
);
5166 /* An error occured in print_job_start() so return an appropriate
5169 if (Printer
->jobid
== -1) {
5170 return map_werror_from_unix(errno
);
5173 Printer
->document_started
= true;
5174 *r
->out
.job_id
= Printer
->jobid
;
5179 /****************************************************************
5180 _spoolss_EndDocPrinter
5181 ****************************************************************/
5183 WERROR
_spoolss_EndDocPrinter(pipes_struct
*p
,
5184 struct spoolss_EndDocPrinter
*r
)
5186 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5190 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5191 OUR_HANDLE(r
->in
.handle
)));
5195 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5199 Printer
->document_started
= false;
5200 print_job_end(snum
, Printer
->jobid
, NORMAL_CLOSE
);
5201 /* error codes unhandled so far ... */
5206 /****************************************************************
5207 _spoolss_WritePrinter
5208 ****************************************************************/
5210 WERROR
_spoolss_WritePrinter(pipes_struct
*p
,
5211 struct spoolss_WritePrinter
*r
)
5213 ssize_t buffer_written
;
5215 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5218 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5219 OUR_HANDLE(r
->in
.handle
)));
5220 *r
->out
.num_written
= r
->in
._data_size
;
5224 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5227 buffer_written
= print_job_write(snum
, Printer
->jobid
,
5228 (const char *)r
->in
.data
.data
,
5230 (size_t)r
->in
._data_size
);
5231 if (buffer_written
== (ssize_t
)-1) {
5232 *r
->out
.num_written
= 0;
5233 if (errno
== ENOSPC
)
5234 return WERR_NO_SPOOL_SPACE
;
5236 return WERR_ACCESS_DENIED
;
5239 *r
->out
.num_written
= r
->in
._data_size
;
5244 /********************************************************************
5245 * api_spoolss_getprinter
5246 * called from the spoolss dispatcher
5248 ********************************************************************/
5250 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5254 WERROR errcode
= WERR_BADFUNC
;
5255 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5258 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5259 OUR_HANDLE(handle
)));
5263 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5267 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5268 errcode
= print_queue_pause(p
->server_info
, snum
);
5270 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5271 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5272 errcode
= print_queue_resume(p
->server_info
, snum
);
5274 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5275 errcode
= print_queue_purge(p
->server_info
, snum
);
5278 return WERR_UNKNOWN_LEVEL
;
5285 /****************************************************************
5286 _spoolss_AbortPrinter
5287 * From MSDN: "Deletes printer's spool file if printer is configured
5289 ****************************************************************/
5291 WERROR
_spoolss_AbortPrinter(pipes_struct
*p
,
5292 struct spoolss_AbortPrinter
*r
)
5294 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5296 WERROR errcode
= WERR_OK
;
5299 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5300 OUR_HANDLE(r
->in
.handle
)));
5304 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5307 print_job_delete(p
->server_info
, snum
, Printer
->jobid
, &errcode
);
5312 /********************************************************************
5313 * called by spoolss_api_setprinter
5314 * when updating a printer description
5315 ********************************************************************/
5317 static WERROR
update_printer_sec(struct policy_handle
*handle
,
5318 pipes_struct
*p
, struct sec_desc_buf
*secdesc_ctr
)
5320 struct sec_desc_buf
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5324 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5326 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5327 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5328 OUR_HANDLE(handle
)));
5330 result
= WERR_BADFID
;
5335 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5336 result
= WERR_INVALID_PARAM
;
5340 /* Check the user has permissions to change the security
5341 descriptor. By experimentation with two NT machines, the user
5342 requires Full Access to the printer to change security
5345 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5346 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5347 result
= WERR_ACCESS_DENIED
;
5351 /* NT seems to like setting the security descriptor even though
5352 nothing may have actually changed. */
5354 if ( !nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
)) {
5355 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5356 result
= WERR_BADFID
;
5360 if (DEBUGLEVEL
>= 10) {
5361 struct security_acl
*the_acl
;
5364 the_acl
= old_secdesc_ctr
->sd
->dacl
;
5365 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5366 PRINTERNAME(snum
), the_acl
->num_aces
));
5368 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5369 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5370 &the_acl
->aces
[i
].trustee
),
5371 the_acl
->aces
[i
].access_mask
));
5374 the_acl
= secdesc_ctr
->sd
->dacl
;
5377 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5378 PRINTERNAME(snum
), the_acl
->num_aces
));
5380 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5381 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5382 &the_acl
->aces
[i
].trustee
),
5383 the_acl
->aces
[i
].access_mask
));
5386 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5390 new_secdesc_ctr
= sec_desc_merge_buf(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5391 if (!new_secdesc_ctr
) {
5392 result
= WERR_NOMEM
;
5396 if (security_descriptor_equal(new_secdesc_ctr
->sd
, old_secdesc_ctr
->sd
)) {
5401 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5408 /********************************************************************
5409 Canonicalize printer info from a client
5411 ATTN: It does not matter what we set the servername to hear
5412 since we do the necessary work in get_a_printer() to set it to
5413 the correct value based on what the client sent in the
5414 _spoolss_open_printer_ex().
5415 ********************************************************************/
5417 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5419 fstring printername
;
5422 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5423 "portname=%s drivername=%s comment=%s location=%s\n",
5424 info
->servername
, info
->printername
, info
->sharename
,
5425 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5427 /* we force some elements to "correct" values */
5428 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5429 fstrcpy(info
->sharename
, lp_servicename(snum
));
5431 /* check to see if we allow printername != sharename */
5433 if ( lp_force_printername(snum
) ) {
5434 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5435 global_myname(), info
->sharename
);
5438 /* make sure printername is in \\server\printername format */
5440 fstrcpy( printername
, info
->printername
);
5442 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5443 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5447 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5448 global_myname(), p
);
5451 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5452 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5459 /****************************************************************************
5460 ****************************************************************************/
5462 static WERROR
add_port_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
5464 char *cmd
= lp_addport_cmd();
5465 char *command
= NULL
;
5467 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5468 bool is_print_op
= false;
5471 return WERR_ACCESS_DENIED
;
5474 command
= talloc_asprintf(ctx
,
5475 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
5481 is_print_op
= user_has_privileges( token
, &se_printop
);
5483 DEBUG(10,("Running [%s]\n", command
));
5485 /********* BEGIN SePrintOperatorPrivilege **********/
5490 ret
= smbrun(command
, NULL
);
5495 /********* END SePrintOperatorPrivilege **********/
5497 DEBUGADD(10,("returned [%d]\n", ret
));
5499 TALLOC_FREE(command
);
5502 return WERR_ACCESS_DENIED
;
5508 /****************************************************************************
5509 ****************************************************************************/
5511 bool add_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
5513 char *cmd
= lp_addprinter_cmd();
5515 char *command
= NULL
;
5519 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5520 bool is_print_op
= false;
5521 char *remote_machine
= talloc_strdup(ctx
, "%m");
5523 if (!remote_machine
) {
5526 remote_machine
= talloc_sub_basic(ctx
,
5527 current_user_info
.smb_name
,
5528 current_user_info
.domain
,
5530 if (!remote_machine
) {
5534 command
= talloc_asprintf(ctx
,
5535 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5536 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5537 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5538 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5544 is_print_op
= user_has_privileges( token
, &se_printop
);
5546 DEBUG(10,("Running [%s]\n", command
));
5548 /********* BEGIN SePrintOperatorPrivilege **********/
5553 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
5554 /* Tell everyone we updated smb.conf. */
5555 message_send_all(smbd_messaging_context(),
5556 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
5562 /********* END SePrintOperatorPrivilege **********/
5564 DEBUGADD(10,("returned [%d]\n", ret
));
5566 TALLOC_FREE(command
);
5567 TALLOC_FREE(remote_machine
);
5575 /* reload our services immediately */
5577 reload_services(false);
5581 /* Get lines and convert them back to dos-codepage */
5582 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
5583 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5586 /* Set the portname to what the script says the portname should be. */
5587 /* but don't require anything to be return from the script exit a good error code */
5590 /* Set the portname to what the script says the portname should be. */
5591 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5592 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5595 TALLOC_FREE(qlines
);
5600 /********************************************************************
5601 * Called by spoolss_api_setprinter
5602 * when updating a printer description.
5603 ********************************************************************/
5605 static WERROR
update_printer(pipes_struct
*p
, struct policy_handle
*handle
,
5606 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
5607 struct spoolss_DeviceMode
*devmode
)
5610 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5611 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5616 DEBUG(8,("update_printer\n"));
5621 result
= WERR_BADFID
;
5625 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
5626 result
= WERR_BADFID
;
5630 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
5631 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
5632 result
= WERR_BADFID
;
5636 DEBUGADD(8,("Converting info_2 struct\n"));
5639 * convert_printer_info converts the incoming
5640 * info from the client and overwrites the info
5641 * just read from the tdb in the pointer 'printer'.
5644 if (!convert_printer_info(info_ctr
, printer
)) {
5645 result
= WERR_NOMEM
;
5650 /* we have a valid devmode
5651 convert it and link it*/
5653 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5654 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5655 &printer
->info_2
->devmode
)) {
5656 result
= WERR_NOMEM
;
5661 /* Do sanity check on the requested changes for Samba */
5663 if (!check_printer_ok(printer
->info_2
, snum
)) {
5664 result
= WERR_INVALID_PARAM
;
5668 /* FIXME!!! If the driver has changed we really should verify that
5669 it is installed before doing much else --jerry */
5671 /* Check calling user has permission to update printer description */
5673 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5674 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5675 result
= WERR_ACCESS_DENIED
;
5679 /* Call addprinter hook */
5680 /* Check changes to see if this is really needed */
5682 if ( *lp_addprinter_cmd()
5683 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
5684 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
5685 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
5686 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
5688 /* add_printer_hook() will call reload_services() */
5690 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
5692 result
= WERR_ACCESS_DENIED
;
5698 * When a *new* driver is bound to a printer, the drivername is used to
5699 * lookup previously saved driver initialization info, which is then
5700 * bound to the printer, simulating what happens in the Windows arch.
5702 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
5704 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5705 printer
->info_2
->drivername
));
5707 notify_printer_driver(snum
, printer
->info_2
->drivername
);
5711 * flag which changes actually occured. This is a small subset of
5712 * all the possible changes. We also have to update things in the
5716 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
5717 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->comment
);
5718 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
5719 REG_SZ
, buffer
.data
, buffer
.length
);
5721 notify_printer_comment(snum
, printer
->info_2
->comment
);
5724 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
5725 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->sharename
);
5726 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
5727 REG_SZ
, buffer
.data
, buffer
.length
);
5729 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
5732 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
5735 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
5738 pname
= printer
->info_2
->printername
;
5741 push_reg_sz(talloc_tos(), &buffer
, pname
);
5742 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
5743 REG_SZ
, buffer
.data
, buffer
.length
);
5745 notify_printer_printername( snum
, pname
);
5748 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
5749 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->portname
);
5750 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
5751 REG_SZ
, buffer
.data
, buffer
.length
);
5753 notify_printer_port(snum
, printer
->info_2
->portname
);
5756 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
5757 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->location
);
5758 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
5759 REG_SZ
, buffer
.data
, buffer
.length
);
5761 notify_printer_location(snum
, printer
->info_2
->location
);
5764 /* here we need to update some more DsSpooler keys */
5765 /* uNCName, serverName, shortServerName */
5767 push_reg_sz(talloc_tos(), &buffer
, global_myname());
5768 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
5769 REG_SZ
, buffer
.data
, buffer
.length
);
5770 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
5771 REG_SZ
, buffer
.data
, buffer
.length
);
5773 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
5774 global_myname(), printer
->info_2
->sharename
);
5775 push_reg_sz(talloc_tos(), &buffer
, asc_buffer
);
5776 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
5777 REG_SZ
, buffer
.data
, buffer
.length
);
5779 /* Update printer info */
5780 result
= mod_a_printer(printer
, 2);
5783 free_a_printer(&printer
, 2);
5784 free_a_printer(&old_printer
, 2);
5790 /****************************************************************************
5791 ****************************************************************************/
5792 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
,
5793 struct policy_handle
*handle
,
5794 struct spoolss_SetPrinterInfo7
*info7
)
5798 Printer_entry
*Printer
;
5800 if ( lp_security() != SEC_ADS
) {
5801 return WERR_UNKNOWN_LEVEL
;
5804 Printer
= find_printer_index_by_hnd(p
, handle
);
5806 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
5811 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5814 nt_printer_publish(Printer
, snum
, info7
->action
);
5818 return WERR_UNKNOWN_LEVEL
;
5822 /********************************************************************
5823 ********************************************************************/
5825 static WERROR
update_printer_devmode(pipes_struct
*p
, struct policy_handle
*handle
,
5826 struct spoolss_DeviceMode
*devmode
)
5829 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5830 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5833 DEBUG(8,("update_printer_devmode\n"));
5838 result
= WERR_BADFID
;
5842 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
5843 result
= WERR_BADFID
;
5847 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
)))) {
5848 result
= WERR_BADFID
;
5853 /* we have a valid devmode
5854 convert it and link it*/
5856 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5857 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5858 &printer
->info_2
->devmode
)) {
5859 result
= WERR_NOMEM
;
5864 /* Check calling user has permission to update printer description */
5866 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5867 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5868 result
= WERR_ACCESS_DENIED
;
5873 /* Update printer info */
5874 result
= mod_a_printer(printer
, 2);
5877 free_a_printer(&printer
, 2);
5883 /****************************************************************
5885 ****************************************************************/
5887 WERROR
_spoolss_SetPrinter(pipes_struct
*p
,
5888 struct spoolss_SetPrinter
*r
)
5892 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5895 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5896 OUR_HANDLE(r
->in
.handle
)));
5900 /* check the level */
5901 switch (r
->in
.info_ctr
->level
) {
5903 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
5905 result
= update_printer(p
, r
->in
.handle
,
5907 r
->in
.devmode_ctr
->devmode
);
5908 if (!W_ERROR_IS_OK(result
))
5910 if (r
->in
.secdesc_ctr
->sd
)
5911 result
= update_printer_sec(r
->in
.handle
, p
,
5915 return update_printer_sec(r
->in
.handle
, p
,
5918 return publish_or_unpublish_printer(p
, r
->in
.handle
,
5919 r
->in
.info_ctr
->info
.info7
);
5921 return update_printer_devmode(p
, r
->in
.handle
,
5922 r
->in
.devmode_ctr
->devmode
);
5924 return WERR_UNKNOWN_LEVEL
;
5928 /****************************************************************
5929 _spoolss_FindClosePrinterNotify
5930 ****************************************************************/
5932 WERROR
_spoolss_FindClosePrinterNotify(pipes_struct
*p
,
5933 struct spoolss_FindClosePrinterNotify
*r
)
5935 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5938 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5939 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
5943 if (Printer
->notify
.client_connected
== true) {
5946 if ( Printer
->printer_type
== SPLHND_SERVER
)
5948 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
5949 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
5952 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
5955 Printer
->notify
.flags
=0;
5956 Printer
->notify
.options
=0;
5957 Printer
->notify
.localmachine
[0]='\0';
5958 Printer
->notify
.printerlocal
=0;
5959 TALLOC_FREE(Printer
->notify
.option
);
5960 Printer
->notify
.client_connected
= false;
5965 /****************************************************************
5967 ****************************************************************/
5969 WERROR
_spoolss_AddJob(pipes_struct
*p
,
5970 struct spoolss_AddJob
*r
)
5972 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5973 return WERR_INVALID_PARAM
;
5976 /* this is what a NT server returns for AddJob. AddJob must fail on
5977 * non-local printers */
5979 if (r
->in
.level
!= 1) {
5980 return WERR_UNKNOWN_LEVEL
;
5983 return WERR_INVALID_PARAM
;
5986 /****************************************************************************
5988 ****************************************************************************/
5990 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
5991 struct spoolss_JobInfo1
*r
,
5992 const print_queue_struct
*queue
,
5993 int position
, int snum
,
5994 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
5998 t
= gmtime(&queue
->time
);
6000 r
->job_id
= queue
->job
;
6002 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6003 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6004 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6005 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6006 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6007 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6008 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6009 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6010 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6011 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6012 r
->text_status
= talloc_strdup(mem_ctx
, "");
6013 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6015 r
->status
= nt_printj_status(queue
->status
);
6016 r
->priority
= queue
->priority
;
6017 r
->position
= position
;
6018 r
->total_pages
= queue
->page_count
;
6019 r
->pages_printed
= 0; /* ??? */
6021 init_systemtime(&r
->submitted
, t
);
6026 /****************************************************************************
6028 ****************************************************************************/
6030 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6031 struct spoolss_JobInfo2
*r
,
6032 const print_queue_struct
*queue
,
6033 int position
, int snum
,
6034 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6035 struct spoolss_DeviceMode
*devmode
)
6039 t
= gmtime(&queue
->time
);
6041 r
->job_id
= queue
->job
;
6043 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6044 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6045 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6046 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6047 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6048 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6049 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6050 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6051 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6052 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6053 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6054 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6055 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6056 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6057 r
->parameters
= talloc_strdup(mem_ctx
, "");
6058 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6059 r
->driver_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
6060 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6062 r
->devmode
= devmode
;
6064 r
->text_status
= talloc_strdup(mem_ctx
, "");
6065 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6069 r
->status
= nt_printj_status(queue
->status
);
6070 r
->priority
= queue
->priority
;
6071 r
->position
= position
;
6074 r
->total_pages
= queue
->page_count
;
6075 r
->size
= queue
->size
;
6076 init_systemtime(&r
->submitted
, t
);
6078 r
->pages_printed
= 0; /* ??? */
6083 /****************************************************************************
6085 ****************************************************************************/
6087 static WERROR
fill_job_info3(TALLOC_CTX
*mem_ctx
,
6088 struct spoolss_JobInfo3
*r
,
6089 const print_queue_struct
*queue
,
6090 const print_queue_struct
*next_queue
,
6091 int position
, int snum
,
6092 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
6094 r
->job_id
= queue
->job
;
6097 r
->next_job_id
= next_queue
->job
;
6104 /****************************************************************************
6105 Enumjobs at level 1.
6106 ****************************************************************************/
6108 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6109 const print_queue_struct
*queue
,
6110 uint32_t num_queues
, int snum
,
6111 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6112 union spoolss_JobInfo
**info_p
,
6115 union spoolss_JobInfo
*info
;
6117 WERROR result
= WERR_OK
;
6119 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6120 W_ERROR_HAVE_NO_MEMORY(info
);
6122 *count
= num_queues
;
6124 for (i
=0; i
<*count
; i
++) {
6125 result
= fill_job_info1(info
,
6131 if (!W_ERROR_IS_OK(result
)) {
6137 if (!W_ERROR_IS_OK(result
)) {
6148 /****************************************************************************
6149 Enumjobs at level 2.
6150 ****************************************************************************/
6152 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6153 const print_queue_struct
*queue
,
6154 uint32_t num_queues
, int snum
,
6155 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6156 union spoolss_JobInfo
**info_p
,
6159 union spoolss_JobInfo
*info
;
6161 WERROR result
= WERR_OK
;
6163 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6164 W_ERROR_HAVE_NO_MEMORY(info
);
6166 *count
= num_queues
;
6168 for (i
=0; i
<*count
; i
++) {
6170 struct spoolss_DeviceMode
*devmode
;
6172 devmode
= construct_dev_mode(info
, lp_const_servicename(snum
));
6174 result
= WERR_NOMEM
;
6178 result
= fill_job_info2(info
,
6185 if (!W_ERROR_IS_OK(result
)) {
6191 if (!W_ERROR_IS_OK(result
)) {
6202 /****************************************************************************
6203 Enumjobs at level 3.
6204 ****************************************************************************/
6206 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
6207 const print_queue_struct
*queue
,
6208 uint32_t num_queues
, int snum
,
6209 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6210 union spoolss_JobInfo
**info_p
,
6213 union spoolss_JobInfo
*info
;
6215 WERROR result
= WERR_OK
;
6217 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6218 W_ERROR_HAVE_NO_MEMORY(info
);
6220 *count
= num_queues
;
6222 for (i
=0; i
<*count
; i
++) {
6223 const print_queue_struct
*next_queue
= NULL
;
6226 next_queue
= &queue
[i
+1];
6229 result
= fill_job_info3(info
,
6236 if (!W_ERROR_IS_OK(result
)) {
6242 if (!W_ERROR_IS_OK(result
)) {
6253 /****************************************************************
6255 ****************************************************************/
6257 WERROR
_spoolss_EnumJobs(pipes_struct
*p
,
6258 struct spoolss_EnumJobs
*r
)
6261 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6263 print_status_struct prt_status
;
6264 print_queue_struct
*queue
= NULL
;
6267 /* that's an [in out] buffer */
6269 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6270 return WERR_INVALID_PARAM
;
6273 DEBUG(4,("_spoolss_EnumJobs\n"));
6277 *r
->out
.info
= NULL
;
6279 /* lookup the printer snum and tdb entry */
6281 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6285 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6286 if (!W_ERROR_IS_OK(result
)) {
6290 count
= print_queue_status(snum
, &queue
, &prt_status
);
6291 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6292 count
, prt_status
.status
, prt_status
.message
));
6296 free_a_printer(&ntprinter
, 2);
6300 switch (r
->in
.level
) {
6302 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
6303 ntprinter
, r
->out
.info
, r
->out
.count
);
6306 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
6307 ntprinter
, r
->out
.info
, r
->out
.count
);
6310 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
6311 ntprinter
, r
->out
.info
, r
->out
.count
);
6314 result
= WERR_UNKNOWN_LEVEL
;
6319 free_a_printer(&ntprinter
, 2);
6321 if (!W_ERROR_IS_OK(result
)) {
6325 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6327 *r
->out
.info
, r
->in
.level
,
6329 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6330 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6332 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6335 /****************************************************************
6336 _spoolss_ScheduleJob
6337 ****************************************************************/
6339 WERROR
_spoolss_ScheduleJob(pipes_struct
*p
,
6340 struct spoolss_ScheduleJob
*r
)
6345 /****************************************************************
6346 ****************************************************************/
6348 static WERROR
spoolss_setjob_1(TALLOC_CTX
*mem_ctx
,
6349 const char *printer_name
,
6351 struct spoolss_SetJobInfo1
*r
)
6355 if (!print_job_get_name(mem_ctx
, printer_name
, job_id
, &old_doc_name
)) {
6359 if (strequal(old_doc_name
, r
->document_name
)) {
6363 if (!print_job_set_name(printer_name
, job_id
, r
->document_name
)) {
6370 /****************************************************************
6372 ****************************************************************/
6374 WERROR
_spoolss_SetJob(pipes_struct
*p
,
6375 struct spoolss_SetJob
*r
)
6378 WERROR errcode
= WERR_BADFUNC
;
6380 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6384 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
6385 return WERR_INVALID_PRINTER_NAME
;
6388 switch (r
->in
.command
) {
6389 case SPOOLSS_JOB_CONTROL_CANCEL
:
6390 case SPOOLSS_JOB_CONTROL_DELETE
:
6391 if (print_job_delete(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6395 case SPOOLSS_JOB_CONTROL_PAUSE
:
6396 if (print_job_pause(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6400 case SPOOLSS_JOB_CONTROL_RESTART
:
6401 case SPOOLSS_JOB_CONTROL_RESUME
:
6402 if (print_job_resume(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6410 return WERR_UNKNOWN_LEVEL
;
6413 if (!W_ERROR_IS_OK(errcode
)) {
6417 if (r
->in
.ctr
== NULL
) {
6421 switch (r
->in
.ctr
->level
) {
6423 errcode
= spoolss_setjob_1(p
->mem_ctx
, lp_const_servicename(snum
),
6425 r
->in
.ctr
->info
.info1
);
6431 return WERR_UNKNOWN_LEVEL
;
6437 /****************************************************************************
6438 Enumerates all printer drivers by level and architecture.
6439 ****************************************************************************/
6441 static WERROR
enumprinterdrivers_level_by_architecture(TALLOC_CTX
*mem_ctx
,
6442 const char *servername
,
6443 const char *architecture
,
6445 union spoolss_DriverInfo
**info_p
,
6451 fstring
*list
= NULL
;
6452 struct spoolss_DriverInfo8
*driver
;
6453 union spoolss_DriverInfo
*info
= NULL
;
6455 WERROR result
= WERR_OK
;
6460 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6462 ndrivers
= get_ntdrivers(&list
, architecture
, version
);
6463 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6464 ndrivers
, architecture
, version
));
6466 if (ndrivers
== -1) {
6467 result
= WERR_NOMEM
;
6471 if (ndrivers
!= 0) {
6472 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
6473 union spoolss_DriverInfo
,
6476 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6477 "failed to enlarge driver info buffer!\n"));
6478 result
= WERR_NOMEM
;
6483 for (i
=0; i
<ndrivers
; i
++) {
6484 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6485 ZERO_STRUCT(driver
);
6486 result
= get_a_printer_driver(mem_ctx
, &driver
, list
[i
],
6487 architecture
, version
);
6488 if (!W_ERROR_IS_OK(result
)) {
6494 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
6495 driver
, servername
);
6498 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
6499 driver
, servername
);
6502 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
6503 driver
, servername
);
6506 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
6507 driver
, servername
);
6510 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
6511 driver
, servername
);
6514 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
6515 driver
, servername
);
6518 result
= fill_printer_driver_info8(info
, &info
[count
+i
].info8
,
6519 driver
, servername
);
6522 result
= WERR_UNKNOWN_LEVEL
;
6526 free_a_printer_driver(driver
);
6528 if (!W_ERROR_IS_OK(result
)) {
6540 if (!W_ERROR_IS_OK(result
)) {
6551 /****************************************************************************
6552 Enumerates all printer drivers by level.
6553 ****************************************************************************/
6555 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
6556 const char *servername
,
6557 const char *architecture
,
6559 union spoolss_DriverInfo
**info_p
,
6563 WERROR result
= WERR_OK
;
6565 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_ALL
)) {
6567 for (a
=0; archi_table
[a
].long_archi
!= NULL
; a
++) {
6569 union spoolss_DriverInfo
*info
= NULL
;
6572 result
= enumprinterdrivers_level_by_architecture(mem_ctx
,
6574 archi_table
[a
].long_archi
,
6578 if (!W_ERROR_IS_OK(result
)) {
6582 for (i
=0; i
< count
; i
++) {
6583 ADD_TO_ARRAY(mem_ctx
, union spoolss_DriverInfo
,
6584 info
[i
], info_p
, count_p
);
6591 return enumprinterdrivers_level_by_architecture(mem_ctx
,
6599 /****************************************************************
6600 _spoolss_EnumPrinterDrivers
6601 ****************************************************************/
6603 WERROR
_spoolss_EnumPrinterDrivers(pipes_struct
*p
,
6604 struct spoolss_EnumPrinterDrivers
*r
)
6606 const char *cservername
;
6609 /* that's an [in out] buffer */
6611 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6612 return WERR_INVALID_PARAM
;
6615 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6619 *r
->out
.info
= NULL
;
6621 cservername
= canon_servername(r
->in
.server
);
6623 if (!is_myname_or_ipaddr(cservername
)) {
6624 return WERR_UNKNOWN_PRINTER_DRIVER
;
6627 result
= enumprinterdrivers_level(p
->mem_ctx
, cservername
,
6632 if (!W_ERROR_IS_OK(result
)) {
6636 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6637 spoolss_EnumPrinterDrivers
,
6638 *r
->out
.info
, r
->in
.level
,
6640 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6641 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6643 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6646 /****************************************************************************
6647 ****************************************************************************/
6649 static WERROR
fill_form_info_1(TALLOC_CTX
*mem_ctx
,
6650 struct spoolss_FormInfo1
*r
,
6651 const nt_forms_struct
*form
)
6653 r
->form_name
= talloc_strdup(mem_ctx
, form
->name
);
6654 W_ERROR_HAVE_NO_MEMORY(r
->form_name
);
6656 r
->flags
= form
->flag
;
6657 r
->size
.width
= form
->width
;
6658 r
->size
.height
= form
->length
;
6659 r
->area
.left
= form
->left
;
6660 r
->area
.top
= form
->top
;
6661 r
->area
.right
= form
->right
;
6662 r
->area
.bottom
= form
->bottom
;
6667 /****************************************************************
6668 spoolss_enumforms_level1
6669 ****************************************************************/
6671 static WERROR
spoolss_enumforms_level1(TALLOC_CTX
*mem_ctx
,
6672 const nt_forms_struct
*builtin_forms
,
6673 uint32_t num_builtin_forms
,
6674 const nt_forms_struct
*user_forms
,
6675 uint32_t num_user_forms
,
6676 union spoolss_FormInfo
**info_p
,
6679 union spoolss_FormInfo
*info
;
6680 WERROR result
= WERR_OK
;
6683 *count
= num_builtin_forms
+ num_user_forms
;
6685 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_FormInfo
, *count
);
6686 W_ERROR_HAVE_NO_MEMORY(info
);
6688 /* construct the list of form structures */
6689 for (i
=0; i
<num_builtin_forms
; i
++) {
6690 DEBUGADD(6,("Filling builtin form number [%d]\n",i
));
6691 result
= fill_form_info_1(info
, &info
[i
].info1
,
6693 if (!W_ERROR_IS_OK(result
)) {
6698 for (i
=0; i
<num_user_forms
; i
++) {
6699 DEBUGADD(6,("Filling user form number [%d]\n",i
));
6700 result
= fill_form_info_1(info
, &info
[i
+num_builtin_forms
].info1
,
6702 if (!W_ERROR_IS_OK(result
)) {
6708 if (!W_ERROR_IS_OK(result
)) {
6719 /****************************************************************
6721 ****************************************************************/
6723 WERROR
_spoolss_EnumForms(pipes_struct
*p
,
6724 struct spoolss_EnumForms
*r
)
6727 nt_forms_struct
*user_forms
= NULL
;
6728 nt_forms_struct
*builtin_forms
= NULL
;
6729 uint32_t num_user_forms
;
6730 uint32_t num_builtin_forms
;
6734 *r
->out
.info
= NULL
;
6736 /* that's an [in out] buffer */
6738 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
6739 return WERR_INVALID_PARAM
;
6742 DEBUG(4,("_spoolss_EnumForms\n"));
6743 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
6744 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
6746 num_builtin_forms
= get_builtin_ntforms(&builtin_forms
);
6747 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms
));
6748 num_user_forms
= get_ntforms(&user_forms
);
6749 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms
));
6751 if (num_user_forms
+ num_builtin_forms
== 0) {
6752 SAFE_FREE(builtin_forms
);
6753 SAFE_FREE(user_forms
);
6754 return WERR_NO_MORE_ITEMS
;
6757 switch (r
->in
.level
) {
6759 result
= spoolss_enumforms_level1(p
->mem_ctx
,
6768 result
= WERR_UNKNOWN_LEVEL
;
6772 SAFE_FREE(user_forms
);
6773 SAFE_FREE(builtin_forms
);
6775 if (!W_ERROR_IS_OK(result
)) {
6779 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6781 *r
->out
.info
, r
->in
.level
,
6783 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6784 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6786 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6789 /****************************************************************
6790 ****************************************************************/
6792 static WERROR
find_form_byname(const char *name
,
6793 nt_forms_struct
*form
)
6795 nt_forms_struct
*list
= NULL
;
6796 int num_forms
= 0, i
= 0;
6798 if (get_a_builtin_ntform_by_string(name
, form
)) {
6802 num_forms
= get_ntforms(&list
);
6803 DEBUGADD(5,("Number of forms [%d]\n", num_forms
));
6805 if (num_forms
== 0) {
6809 /* Check if the requested name is in the list of form structures */
6810 for (i
= 0; i
< num_forms
; i
++) {
6812 DEBUG(4,("checking form %s (want %s)\n", list
[i
].name
, name
));
6814 if (strequal(name
, list
[i
].name
)) {
6815 DEBUGADD(6,("Found form %s number [%d]\n", name
, i
));
6827 /****************************************************************
6829 ****************************************************************/
6831 WERROR
_spoolss_GetForm(pipes_struct
*p
,
6832 struct spoolss_GetForm
*r
)
6835 nt_forms_struct form
;
6837 /* that's an [in out] buffer */
6839 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6840 return WERR_INVALID_PARAM
;
6843 DEBUG(4,("_spoolss_GetForm\n"));
6844 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
6845 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
6847 result
= find_form_byname(r
->in
.form_name
, &form
);
6848 if (!W_ERROR_IS_OK(result
)) {
6849 TALLOC_FREE(r
->out
.info
);
6853 switch (r
->in
.level
) {
6855 result
= fill_form_info_1(p
->mem_ctx
,
6856 &r
->out
.info
->info1
,
6861 result
= WERR_UNKNOWN_LEVEL
;
6865 if (!W_ERROR_IS_OK(result
)) {
6866 TALLOC_FREE(r
->out
.info
);
6870 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
,
6871 r
->out
.info
, r
->in
.level
);
6872 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
6874 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6877 /****************************************************************************
6878 ****************************************************************************/
6880 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
6881 struct spoolss_PortInfo1
*r
,
6884 r
->port_name
= talloc_strdup(mem_ctx
, name
);
6885 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
6890 /****************************************************************************
6891 TODO: This probably needs distinguish between TCP/IP and Local ports
6893 ****************************************************************************/
6895 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
6896 struct spoolss_PortInfo2
*r
,
6899 r
->port_name
= talloc_strdup(mem_ctx
, name
);
6900 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
6902 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
6903 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
6905 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
6906 W_ERROR_HAVE_NO_MEMORY(r
->description
);
6908 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
6915 /****************************************************************************
6916 wrapper around the enumer ports command
6917 ****************************************************************************/
6919 static WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
6921 char *cmd
= lp_enumports_cmd();
6922 char **qlines
= NULL
;
6923 char *command
= NULL
;
6931 /* if no hook then just fill in the default port */
6934 if (!(qlines
= TALLOC_ARRAY( NULL
, char*, 2 ))) {
6937 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
6938 TALLOC_FREE(qlines
);
6945 /* we have a valid enumport command */
6947 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
6952 DEBUG(10,("Running [%s]\n", command
));
6953 ret
= smbrun(command
, &fd
);
6954 DEBUG(10,("Returned [%d]\n", ret
));
6955 TALLOC_FREE(command
);
6960 return WERR_ACCESS_DENIED
;
6964 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
6965 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6975 /****************************************************************************
6977 ****************************************************************************/
6979 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
6980 union spoolss_PortInfo
**info_p
,
6983 union spoolss_PortInfo
*info
= NULL
;
6985 WERROR result
= WERR_OK
;
6986 char **qlines
= NULL
;
6989 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
6990 if (!W_ERROR_IS_OK(result
)) {
6995 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
6997 DEBUG(10,("Returning WERR_NOMEM\n"));
6998 result
= WERR_NOMEM
;
7002 for (i
=0; i
<numlines
; i
++) {
7003 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7004 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7005 if (!W_ERROR_IS_OK(result
)) {
7010 TALLOC_FREE(qlines
);
7013 if (!W_ERROR_IS_OK(result
)) {
7015 TALLOC_FREE(qlines
);
7027 /****************************************************************************
7029 ****************************************************************************/
7031 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7032 union spoolss_PortInfo
**info_p
,
7035 union spoolss_PortInfo
*info
= NULL
;
7037 WERROR result
= WERR_OK
;
7038 char **qlines
= NULL
;
7041 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7042 if (!W_ERROR_IS_OK(result
)) {
7047 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7049 DEBUG(10,("Returning WERR_NOMEM\n"));
7050 result
= WERR_NOMEM
;
7054 for (i
=0; i
<numlines
; i
++) {
7055 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7056 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7057 if (!W_ERROR_IS_OK(result
)) {
7062 TALLOC_FREE(qlines
);
7065 if (!W_ERROR_IS_OK(result
)) {
7067 TALLOC_FREE(qlines
);
7079 /****************************************************************
7081 ****************************************************************/
7083 WERROR
_spoolss_EnumPorts(pipes_struct
*p
,
7084 struct spoolss_EnumPorts
*r
)
7088 /* that's an [in out] buffer */
7090 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7091 return WERR_INVALID_PARAM
;
7094 DEBUG(4,("_spoolss_EnumPorts\n"));
7098 *r
->out
.info
= NULL
;
7100 switch (r
->in
.level
) {
7102 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7106 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7110 return WERR_UNKNOWN_LEVEL
;
7113 if (!W_ERROR_IS_OK(result
)) {
7117 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7119 *r
->out
.info
, r
->in
.level
,
7121 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7122 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7124 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7127 /****************************************************************************
7128 ****************************************************************************/
7130 static WERROR
spoolss_addprinterex_level_2(pipes_struct
*p
,
7132 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7133 struct spoolss_DeviceMode
*devmode
,
7134 struct security_descriptor
*sec_desc
,
7135 struct spoolss_UserLevelCtr
*user_ctr
,
7136 struct policy_handle
*handle
)
7138 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7141 WERROR err
= WERR_OK
;
7143 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7144 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7148 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7149 if (!convert_printer_info(info_ctr
, printer
)) {
7150 free_a_printer(&printer
, 2);
7154 /* samba does not have a concept of local, non-shared printers yet, so
7155 * make sure we always setup sharename - gd */
7156 if ((printer
->info_2
->sharename
[0] == '\0') && (printer
->info_2
->printername
!= '\0')) {
7157 DEBUG(5, ("spoolss_addprinterex_level_2: "
7158 "no sharename has been set, setting printername %s as sharename\n",
7159 printer
->info_2
->printername
));
7160 fstrcpy(printer
->info_2
->sharename
, printer
->info_2
->printername
);
7163 /* check to see if the printer already exists */
7165 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7166 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7167 printer
->info_2
->sharename
));
7168 free_a_printer(&printer
, 2);
7169 return WERR_PRINTER_ALREADY_EXISTS
;
7172 if (!lp_force_printername(GLOBAL_SECTION_SNUM
)) {
7173 if ((snum
= print_queue_snum(printer
->info_2
->printername
)) != -1) {
7174 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7175 printer
->info_2
->printername
));
7176 free_a_printer(&printer
, 2);
7177 return WERR_PRINTER_ALREADY_EXISTS
;
7181 /* validate printer info struct */
7182 if (!info_ctr
->info
.info2
->printername
||
7183 strlen(info_ctr
->info
.info2
->printername
) == 0) {
7184 free_a_printer(&printer
,2);
7185 return WERR_INVALID_PRINTER_NAME
;
7187 if (!info_ctr
->info
.info2
->portname
||
7188 strlen(info_ctr
->info
.info2
->portname
) == 0) {
7189 free_a_printer(&printer
,2);
7190 return WERR_UNKNOWN_PORT
;
7192 if (!info_ctr
->info
.info2
->drivername
||
7193 strlen(info_ctr
->info
.info2
->drivername
) == 0) {
7194 free_a_printer(&printer
,2);
7195 return WERR_UNKNOWN_PRINTER_DRIVER
;
7197 if (!info_ctr
->info
.info2
->printprocessor
||
7198 strlen(info_ctr
->info
.info2
->printprocessor
) == 0) {
7199 free_a_printer(&printer
,2);
7200 return WERR_UNKNOWN_PRINTPROCESSOR
;
7203 /* FIXME!!! smbd should check to see if the driver is installed before
7204 trying to add a printer like this --jerry */
7206 if (*lp_addprinter_cmd() ) {
7207 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
7209 free_a_printer(&printer
,2);
7210 return WERR_ACCESS_DENIED
;
7213 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7214 "smb.conf parameter \"addprinter command\" is defined. This"
7215 "parameter must exist for this call to succeed\n",
7216 printer
->info_2
->sharename
));
7219 /* use our primary netbios name since get_a_printer() will convert
7220 it to what the client expects on a case by case basis */
7222 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7223 printer
->info_2
->sharename
);
7226 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7227 free_a_printer(&printer
,2);
7228 return WERR_ACCESS_DENIED
;
7231 /* you must be a printer admin to add a new printer */
7232 if (!print_access_check(p
->server_info
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7233 free_a_printer(&printer
,2);
7234 return WERR_ACCESS_DENIED
;
7238 * Do sanity check on the requested changes for Samba.
7241 if (!check_printer_ok(printer
->info_2
, snum
)) {
7242 free_a_printer(&printer
,2);
7243 return WERR_INVALID_PARAM
;
7247 * When a printer is created, the drivername bound to the printer is used
7248 * to lookup previously saved driver initialization info, which is then
7249 * bound to the new printer, simulating what happens in the Windows arch.
7254 /* A valid devmode was included, convert and link it
7256 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7258 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7259 &printer
->info_2
->devmode
)) {
7264 /* write the ASCII on disk */
7265 err
= mod_a_printer(printer
, 2);
7266 if (!W_ERROR_IS_OK(err
)) {
7267 free_a_printer(&printer
,2);
7271 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7272 /* Handle open failed - remove addition. */
7273 del_a_printer(printer
->info_2
->sharename
);
7274 free_a_printer(&printer
,2);
7275 ZERO_STRUCTP(handle
);
7276 return WERR_ACCESS_DENIED
;
7279 update_c_setprinter(false);
7280 free_a_printer(&printer
,2);
7285 /****************************************************************
7286 _spoolss_AddPrinterEx
7287 ****************************************************************/
7289 WERROR
_spoolss_AddPrinterEx(pipes_struct
*p
,
7290 struct spoolss_AddPrinterEx
*r
)
7292 switch (r
->in
.info_ctr
->level
) {
7294 /* we don't handle yet */
7295 /* but I know what to do ... */
7296 return WERR_UNKNOWN_LEVEL
;
7298 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
7300 r
->in
.devmode_ctr
->devmode
,
7301 r
->in
.secdesc_ctr
->sd
,
7302 r
->in
.userlevel_ctr
,
7305 return WERR_UNKNOWN_LEVEL
;
7309 /****************************************************************
7311 ****************************************************************/
7313 WERROR
_spoolss_AddPrinter(pipes_struct
*p
,
7314 struct spoolss_AddPrinter
*r
)
7316 struct spoolss_AddPrinterEx a
;
7317 struct spoolss_UserLevelCtr userlevel_ctr
;
7319 ZERO_STRUCT(userlevel_ctr
);
7321 userlevel_ctr
.level
= 1;
7323 a
.in
.server
= r
->in
.server
;
7324 a
.in
.info_ctr
= r
->in
.info_ctr
;
7325 a
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
7326 a
.in
.secdesc_ctr
= r
->in
.secdesc_ctr
;
7327 a
.in
.userlevel_ctr
= &userlevel_ctr
;
7328 a
.out
.handle
= r
->out
.handle
;
7330 return _spoolss_AddPrinterEx(p
, &a
);
7333 /****************************************************************
7334 _spoolss_AddPrinterDriverEx
7335 ****************************************************************/
7337 WERROR
_spoolss_AddPrinterDriverEx(pipes_struct
*p
,
7338 struct spoolss_AddPrinterDriverEx
*r
)
7340 WERROR err
= WERR_OK
;
7341 char *driver_name
= NULL
;
7345 switch (p
->hdr_req
.opnum
) {
7346 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
7347 fn
= "_spoolss_AddPrinterDriver";
7349 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
7350 fn
= "_spoolss_AddPrinterDriverEx";
7353 return WERR_INVALID_PARAM
;
7357 * we only support the semantics of AddPrinterDriver()
7358 * i.e. only copy files that are newer than existing ones
7361 if (r
->in
.flags
== 0) {
7362 return WERR_INVALID_PARAM
;
7365 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
7366 return WERR_ACCESS_DENIED
;
7370 if (r
->in
.info_ctr
->level
!= 3 && r
->in
.info_ctr
->level
!= 6) {
7371 /* Clever hack from Martin Zielinski <mz@seh.de>
7372 * to allow downgrade from level 8 (Vista).
7374 DEBUG(0,("%s: level %d not yet implemented\n", fn
,
7375 r
->in
.info_ctr
->level
));
7376 return WERR_UNKNOWN_LEVEL
;
7379 DEBUG(5,("Cleaning driver's information\n"));
7380 err
= clean_up_driver_struct(p
, r
->in
.info_ctr
);
7381 if (!W_ERROR_IS_OK(err
))
7384 DEBUG(5,("Moving driver to final destination\n"));
7385 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(p
, r
->in
.info_ctr
,
7390 if (add_a_printer_driver(p
->mem_ctx
, r
->in
.info_ctr
, &driver_name
, &version
)!=0) {
7391 err
= WERR_ACCESS_DENIED
;
7396 * I think this is where he DrvUpgradePrinter() hook would be
7397 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7398 * server. Right now, we just need to send ourselves a message
7399 * to update each printer bound to this driver. --jerry
7402 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7403 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7411 /****************************************************************
7412 _spoolss_AddPrinterDriver
7413 ****************************************************************/
7415 WERROR
_spoolss_AddPrinterDriver(pipes_struct
*p
,
7416 struct spoolss_AddPrinterDriver
*r
)
7418 struct spoolss_AddPrinterDriverEx a
;
7420 switch (r
->in
.info_ctr
->level
) {
7427 return WERR_UNKNOWN_LEVEL
;
7430 a
.in
.servername
= r
->in
.servername
;
7431 a
.in
.info_ctr
= r
->in
.info_ctr
;
7432 a
.in
.flags
= APD_COPY_NEW_FILES
;
7434 return _spoolss_AddPrinterDriverEx(p
, &a
);
7437 /****************************************************************************
7438 ****************************************************************************/
7440 struct _spoolss_paths
{
7446 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
7448 static const struct _spoolss_paths spoolss_paths
[]= {
7449 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
7450 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
7453 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
7454 const char *servername
,
7455 const char *environment
,
7459 const char *pservername
= NULL
;
7460 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
7461 const char *short_archi
;
7465 /* environment may be empty */
7466 if (environment
&& strlen(environment
)) {
7467 long_archi
= environment
;
7470 /* servername may be empty */
7471 if (servername
&& strlen(servername
)) {
7472 pservername
= canon_servername(servername
);
7474 if (!is_myname_or_ipaddr(pservername
)) {
7475 return WERR_INVALID_PARAM
;
7479 if (!(short_archi
= get_short_archi(long_archi
))) {
7480 return WERR_INVALID_ENVIRONMENT
;
7483 switch (component
) {
7484 case SPOOLSS_PRTPROCS_PATH
:
7485 case SPOOLSS_DRIVER_PATH
:
7487 *path
= talloc_asprintf(mem_ctx
,
7490 spoolss_paths
[component
].share
,
7493 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
7494 SPOOLSS_DEFAULT_SERVER_PATH
,
7495 spoolss_paths
[component
].dir
,
7500 return WERR_INVALID_PARAM
;
7510 /****************************************************************************
7511 ****************************************************************************/
7513 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
7514 const char *servername
,
7515 const char *environment
,
7516 struct spoolss_DriverDirectoryInfo1
*r
)
7521 werr
= compose_spoolss_server_path(mem_ctx
,
7524 SPOOLSS_DRIVER_PATH
,
7526 if (!W_ERROR_IS_OK(werr
)) {
7530 DEBUG(4,("printer driver directory: [%s]\n", path
));
7532 r
->directory_name
= path
;
7537 /****************************************************************
7538 _spoolss_GetPrinterDriverDirectory
7539 ****************************************************************/
7541 WERROR
_spoolss_GetPrinterDriverDirectory(pipes_struct
*p
,
7542 struct spoolss_GetPrinterDriverDirectory
*r
)
7546 /* that's an [in out] buffer */
7548 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7549 return WERR_INVALID_PARAM
;
7552 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7557 /* r->in.level is ignored */
7559 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
7562 &r
->out
.info
->info1
);
7563 if (!W_ERROR_IS_OK(werror
)) {
7564 TALLOC_FREE(r
->out
.info
);
7568 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
,
7569 r
->out
.info
, r
->in
.level
);
7570 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7572 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7575 /****************************************************************
7576 _spoolss_EnumPrinterData
7577 ****************************************************************/
7579 WERROR
_spoolss_EnumPrinterData(pipes_struct
*p
,
7580 struct spoolss_EnumPrinterData
*r
)
7583 struct spoolss_EnumPrinterDataEx r2
;
7585 struct spoolss_PrinterEnumValues
*info
, *val
= NULL
;
7588 r2
.in
.handle
= r
->in
.handle
;
7589 r2
.in
.key_name
= "PrinterDriverData";
7591 r2
.out
.count
= &count
;
7592 r2
.out
.info
= &info
;
7593 r2
.out
.needed
= &needed
;
7595 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
7596 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
7597 r2
.in
.offered
= needed
;
7598 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
7600 if (!W_ERROR_IS_OK(result
)) {
7605 * The NT machine wants to know the biggest size of value and data
7607 * cf: MSDN EnumPrinterData remark section
7610 if (!r
->in
.value_offered
&& !r
->in
.data_offered
) {
7611 uint32_t biggest_valuesize
= 0;
7612 uint32_t biggest_datasize
= 0;
7615 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7617 for (i
=0; i
<count
; i
++) {
7619 name_length
= strlen(info
[i
].value_name
);
7620 if (strlen(info
[i
].value_name
) > biggest_valuesize
) {
7621 biggest_valuesize
= name_length
;
7624 if (info
[i
].data_length
> biggest_datasize
) {
7625 biggest_datasize
= info
[i
].data_length
;
7628 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7632 /* the value is an UNICODE string but real_value_size is the length
7633 in bytes including the trailing 0 */
7635 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
7636 *r
->out
.data_needed
= biggest_datasize
;
7638 DEBUG(6,("final values: [%d], [%d]\n",
7639 *r
->out
.value_needed
, *r
->out
.data_needed
));
7644 if (r
->in
.enum_index
< count
) {
7645 val
= &info
[r
->in
.enum_index
];
7649 /* out_value should default to "" or else NT4 has
7650 problems unmarshalling the response */
7652 if (r
->in
.value_offered
) {
7653 *r
->out
.value_needed
= 1;
7654 r
->out
.value_name
= talloc_strdup(r
, "");
7655 if (!r
->out
.value_name
) {
7659 r
->out
.value_name
= NULL
;
7660 *r
->out
.value_needed
= 0;
7663 /* the data is counted in bytes */
7665 *r
->out
.data_needed
= r
->in
.data_offered
;
7667 result
= WERR_NO_MORE_ITEMS
;
7671 * - counted in bytes in the request
7672 * - counted in UNICODE chars in the max reply
7673 * - counted in bytes in the real size
7675 * take a pause *before* coding not *during* coding
7679 if (r
->in
.value_offered
) {
7680 r
->out
.value_name
= talloc_strdup(r
, val
->value_name
);
7681 if (!r
->out
.value_name
) {
7684 *r
->out
.value_needed
= val
->value_name_len
;
7686 r
->out
.value_name
= NULL
;
7687 *r
->out
.value_needed
= 0;
7692 *r
->out
.type
= val
->type
;
7694 /* data - counted in bytes */
7697 * See the section "Dynamically Typed Query Parameters"
7701 if (r
->out
.data
&& val
->data
&& val
->data
->data
&&
7702 val
->data_length
&& r
->in
.data_offered
) {
7703 memcpy(r
->out
.data
, val
->data
->data
,
7704 MIN(val
->data_length
,r
->in
.data_offered
));
7707 *r
->out
.data_needed
= val
->data_length
;
7715 /****************************************************************
7716 _spoolss_SetPrinterData
7717 ****************************************************************/
7719 WERROR
_spoolss_SetPrinterData(pipes_struct
*p
,
7720 struct spoolss_SetPrinterData
*r
)
7722 struct spoolss_SetPrinterDataEx r2
;
7724 r2
.in
.handle
= r
->in
.handle
;
7725 r2
.in
.key_name
= "PrinterDriverData";
7726 r2
.in
.value_name
= r
->in
.value_name
;
7727 r2
.in
.type
= r
->in
.type
;
7728 r2
.in
.data
= r
->in
.data
;
7729 r2
.in
.offered
= r
->in
.offered
;
7731 return _spoolss_SetPrinterDataEx(p
, &r2
);
7734 /****************************************************************
7735 _spoolss_ResetPrinter
7736 ****************************************************************/
7738 WERROR
_spoolss_ResetPrinter(pipes_struct
*p
,
7739 struct spoolss_ResetPrinter
*r
)
7741 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7744 DEBUG(5,("_spoolss_ResetPrinter\n"));
7747 * All we do is to check to see if the handle and queue is valid.
7748 * This call really doesn't mean anything to us because we only
7749 * support RAW printing. --jerry
7753 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7754 OUR_HANDLE(r
->in
.handle
)));
7758 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7762 /* blindly return success */
7766 /****************************************************************
7767 _spoolss_DeletePrinterData
7768 ****************************************************************/
7770 WERROR
_spoolss_DeletePrinterData(pipes_struct
*p
,
7771 struct spoolss_DeletePrinterData
*r
)
7773 struct spoolss_DeletePrinterDataEx r2
;
7775 r2
.in
.handle
= r
->in
.handle
;
7776 r2
.in
.key_name
= "PrinterDriverData";
7777 r2
.in
.value_name
= r
->in
.value_name
;
7779 return _spoolss_DeletePrinterDataEx(p
, &r2
);
7782 /****************************************************************
7784 ****************************************************************/
7786 WERROR
_spoolss_AddForm(pipes_struct
*p
,
7787 struct spoolss_AddForm
*r
)
7789 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
7790 nt_forms_struct tmpForm
;
7792 WERROR status
= WERR_OK
;
7793 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7794 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7797 nt_forms_struct
*list
=NULL
;
7798 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7801 DEBUG(5,("_spoolss_AddForm\n"));
7804 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7805 OUR_HANDLE(r
->in
.handle
)));
7810 /* forms can be added on printer or on the print server handle */
7812 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7814 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7817 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7818 if (!W_ERROR_IS_OK(status
))
7822 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7823 and not a printer admin, then fail */
7825 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
7826 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
7827 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
7829 p
->server_info
->ptok
,
7830 lp_printer_admin(snum
))) {
7831 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7832 status
= WERR_ACCESS_DENIED
;
7836 switch (form
->flags
) {
7837 case SPOOLSS_FORM_USER
:
7838 case SPOOLSS_FORM_BUILTIN
:
7839 case SPOOLSS_FORM_PRINTER
:
7842 status
= WERR_INVALID_PARAM
;
7846 /* can't add if builtin */
7848 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
7849 status
= WERR_FILE_EXISTS
;
7853 count
= get_ntforms(&list
);
7855 for (i
=0; i
< count
; i
++) {
7856 if (strequal(form
->form_name
, list
[i
].name
)) {
7857 status
= WERR_FILE_EXISTS
;
7862 if(!add_a_form(&list
, form
, &count
)) {
7863 status
= WERR_NOMEM
;
7868 write_ntforms(&list
, count
);
7872 * ChangeID must always be set if this is a printer
7875 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7876 status
= mod_a_printer(printer
, 2);
7880 free_a_printer(&printer
, 2);
7886 /****************************************************************
7888 ****************************************************************/
7890 WERROR
_spoolss_DeleteForm(pipes_struct
*p
,
7891 struct spoolss_DeleteForm
*r
)
7893 const char *form_name
= r
->in
.form_name
;
7894 nt_forms_struct tmpForm
;
7896 nt_forms_struct
*list
=NULL
;
7897 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7899 WERROR status
= WERR_OK
;
7900 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7901 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7904 DEBUG(5,("_spoolss_DeleteForm\n"));
7907 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7908 OUR_HANDLE(r
->in
.handle
)));
7912 /* forms can be deleted on printer of on the print server handle */
7914 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7916 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7919 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7920 if (!W_ERROR_IS_OK(status
))
7924 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
7925 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
7926 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
7928 p
->server_info
->ptok
,
7929 lp_printer_admin(snum
))) {
7930 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7931 return WERR_ACCESS_DENIED
;
7935 /* can't delete if builtin */
7937 if (get_a_builtin_ntform_by_string(form_name
,&tmpForm
)) {
7938 status
= WERR_INVALID_PARAM
;
7942 count
= get_ntforms(&list
);
7945 ret
= delete_a_form(&list
, form_name
, &count
, &status
);
7952 * ChangeID must always be set if this is a printer
7955 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7956 status
= mod_a_printer(printer
, 2);
7960 free_a_printer(&printer
, 2);
7966 /****************************************************************
7968 ****************************************************************/
7970 WERROR
_spoolss_SetForm(pipes_struct
*p
,
7971 struct spoolss_SetForm
*r
)
7973 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
7974 nt_forms_struct tmpForm
;
7976 WERROR status
= WERR_OK
;
7977 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7978 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7981 nt_forms_struct
*list
=NULL
;
7982 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7984 DEBUG(5,("_spoolss_SetForm\n"));
7987 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7988 OUR_HANDLE(r
->in
.handle
)));
7992 /* forms can be modified on printer of on the print server handle */
7994 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7996 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7999 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8000 if (!W_ERROR_IS_OK(status
))
8004 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8005 and not a printer admin, then fail */
8007 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8008 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8009 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8011 p
->server_info
->ptok
,
8012 lp_printer_admin(snum
))) {
8013 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8014 status
= WERR_ACCESS_DENIED
;
8018 /* can't set if builtin */
8019 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
8020 status
= WERR_INVALID_PARAM
;
8024 count
= get_ntforms(&list
);
8025 update_a_form(&list
, form
, count
);
8027 write_ntforms(&list
, count
);
8031 * ChangeID must always be set if this is a printer
8034 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8035 status
= mod_a_printer(printer
, 2);
8040 free_a_printer(&printer
, 2);
8046 /****************************************************************************
8047 fill_print_processor1
8048 ****************************************************************************/
8050 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8051 struct spoolss_PrintProcessorInfo1
*r
,
8052 const char *print_processor_name
)
8054 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8055 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8060 /****************************************************************************
8061 enumprintprocessors level 1.
8062 ****************************************************************************/
8064 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8065 union spoolss_PrintProcessorInfo
**info_p
,
8068 union spoolss_PrintProcessorInfo
*info
;
8071 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8072 W_ERROR_HAVE_NO_MEMORY(info
);
8076 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8077 if (!W_ERROR_IS_OK(result
)) {
8082 if (!W_ERROR_IS_OK(result
)) {
8093 /****************************************************************
8094 _spoolss_EnumPrintProcessors
8095 ****************************************************************/
8097 WERROR
_spoolss_EnumPrintProcessors(pipes_struct
*p
,
8098 struct spoolss_EnumPrintProcessors
*r
)
8102 /* that's an [in out] buffer */
8104 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8105 return WERR_INVALID_PARAM
;
8108 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8111 * Enumerate the print processors ...
8113 * Just reply with "winprint", to keep NT happy
8114 * and I can use my nice printer checker.
8119 *r
->out
.info
= NULL
;
8121 switch (r
->in
.level
) {
8123 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8127 return WERR_UNKNOWN_LEVEL
;
8130 if (!W_ERROR_IS_OK(result
)) {
8134 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8135 spoolss_EnumPrintProcessors
,
8136 *r
->out
.info
, r
->in
.level
,
8138 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8139 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8141 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8144 /****************************************************************************
8145 fill_printprocdatatype1
8146 ****************************************************************************/
8148 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8149 struct spoolss_PrintProcDataTypesInfo1
*r
,
8150 const char *name_array
)
8152 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8153 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8158 /****************************************************************************
8159 enumprintprocdatatypes level 1.
8160 ****************************************************************************/
8162 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8163 union spoolss_PrintProcDataTypesInfo
**info_p
,
8167 union spoolss_PrintProcDataTypesInfo
*info
;
8169 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8170 W_ERROR_HAVE_NO_MEMORY(info
);
8174 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8175 if (!W_ERROR_IS_OK(result
)) {
8180 if (!W_ERROR_IS_OK(result
)) {
8191 /****************************************************************
8192 _spoolss_EnumPrintProcDataTypes
8193 ****************************************************************/
8195 WERROR
_spoolss_EnumPrintProcDataTypes(pipes_struct
*p
,
8196 struct spoolss_EnumPrintProcDataTypes
*r
)
8200 /* that's an [in out] buffer */
8202 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8203 return WERR_INVALID_PARAM
;
8206 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8210 *r
->out
.info
= NULL
;
8212 switch (r
->in
.level
) {
8214 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8218 return WERR_UNKNOWN_LEVEL
;
8221 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8222 spoolss_EnumPrintProcDataTypes
,
8223 *r
->out
.info
, r
->in
.level
,
8225 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8226 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8228 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8231 /****************************************************************************
8233 ****************************************************************************/
8235 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8236 struct spoolss_MonitorInfo1
*r
,
8237 const char *monitor_name
)
8239 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8240 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8245 /****************************************************************************
8247 ****************************************************************************/
8249 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8250 struct spoolss_MonitorInfo2
*r
,
8251 const char *monitor_name
,
8252 const char *environment
,
8253 const char *dll_name
)
8255 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8256 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8257 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8258 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8259 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8260 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8265 /****************************************************************************
8266 enumprintmonitors level 1.
8267 ****************************************************************************/
8269 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8270 union spoolss_MonitorInfo
**info_p
,
8273 union spoolss_MonitorInfo
*info
;
8274 WERROR result
= WERR_OK
;
8276 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8277 W_ERROR_HAVE_NO_MEMORY(info
);
8281 result
= fill_monitor_1(info
, &info
[0].info1
,
8283 if (!W_ERROR_IS_OK(result
)) {
8287 result
= fill_monitor_1(info
, &info
[1].info1
,
8289 if (!W_ERROR_IS_OK(result
)) {
8294 if (!W_ERROR_IS_OK(result
)) {
8305 /****************************************************************************
8306 enumprintmonitors level 2.
8307 ****************************************************************************/
8309 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
8310 union spoolss_MonitorInfo
**info_p
,
8313 union spoolss_MonitorInfo
*info
;
8314 WERROR result
= WERR_OK
;
8316 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8317 W_ERROR_HAVE_NO_MEMORY(info
);
8321 result
= fill_monitor_2(info
, &info
[0].info2
,
8323 "Windows NT X86", /* FIXME */
8325 if (!W_ERROR_IS_OK(result
)) {
8329 result
= fill_monitor_2(info
, &info
[1].info2
,
8331 "Windows NT X86", /* FIXME */
8333 if (!W_ERROR_IS_OK(result
)) {
8338 if (!W_ERROR_IS_OK(result
)) {
8349 /****************************************************************
8350 _spoolss_EnumMonitors
8351 ****************************************************************/
8353 WERROR
_spoolss_EnumMonitors(pipes_struct
*p
,
8354 struct spoolss_EnumMonitors
*r
)
8358 /* that's an [in out] buffer */
8360 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8361 return WERR_INVALID_PARAM
;
8364 DEBUG(5,("_spoolss_EnumMonitors\n"));
8367 * Enumerate the print monitors ...
8369 * Just reply with "Local Port", to keep NT happy
8370 * and I can use my nice printer checker.
8375 *r
->out
.info
= NULL
;
8377 switch (r
->in
.level
) {
8379 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
8383 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
8387 return WERR_UNKNOWN_LEVEL
;
8390 if (!W_ERROR_IS_OK(result
)) {
8394 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8395 spoolss_EnumMonitors
,
8396 *r
->out
.info
, r
->in
.level
,
8398 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8399 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8401 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8404 /****************************************************************************
8405 ****************************************************************************/
8407 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
8408 const print_queue_struct
*queue
,
8409 int count
, int snum
,
8410 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8412 struct spoolss_JobInfo1
*r
)
8417 for (i
=0; i
<count
; i
++) {
8418 if (queue
[i
].job
== (int)jobid
) {
8424 if (found
== false) {
8425 /* NT treats not found as bad param... yet another bad choice */
8426 return WERR_INVALID_PARAM
;
8429 return fill_job_info1(mem_ctx
,
8437 /****************************************************************************
8438 ****************************************************************************/
8440 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
8441 const print_queue_struct
*queue
,
8442 int count
, int snum
,
8443 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8445 struct spoolss_JobInfo2
*r
)
8449 struct spoolss_DeviceMode
*devmode
;
8450 NT_DEVICEMODE
*nt_devmode
;
8453 for (i
=0; i
<count
; i
++) {
8454 if (queue
[i
].job
== (int)jobid
) {
8460 if (found
== false) {
8461 /* NT treats not found as bad param... yet another bad
8463 return WERR_INVALID_PARAM
;
8467 * if the print job does not have a DEVMODE associated with it,
8468 * just use the one for the printer. A NULL devicemode is not
8469 * a failure condition
8472 nt_devmode
= print_job_devmode(lp_const_servicename(snum
), jobid
);
8474 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
8475 W_ERROR_HAVE_NO_MEMORY(devmode
);
8476 result
= convert_nt_devicemode(devmode
, devmode
, nt_devmode
);
8477 if (!W_ERROR_IS_OK(result
)) {
8481 devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
8482 W_ERROR_HAVE_NO_MEMORY(devmode
);
8485 return fill_job_info2(mem_ctx
,
8494 /****************************************************************
8496 ****************************************************************/
8498 WERROR
_spoolss_GetJob(pipes_struct
*p
,
8499 struct spoolss_GetJob
*r
)
8501 WERROR result
= WERR_OK
;
8502 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8505 print_queue_struct
*queue
= NULL
;
8506 print_status_struct prt_status
;
8508 /* that's an [in out] buffer */
8510 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8511 return WERR_INVALID_PARAM
;
8514 DEBUG(5,("_spoolss_GetJob\n"));
8518 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8522 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8523 if (!W_ERROR_IS_OK(result
)) {
8527 count
= print_queue_status(snum
, &queue
, &prt_status
);
8529 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8530 count
, prt_status
.status
, prt_status
.message
));
8532 switch (r
->in
.level
) {
8534 result
= getjob_level_1(p
->mem_ctx
,
8535 queue
, count
, snum
, ntprinter
,
8536 r
->in
.job_id
, &r
->out
.info
->info1
);
8539 result
= getjob_level_2(p
->mem_ctx
,
8540 queue
, count
, snum
, ntprinter
,
8541 r
->in
.job_id
, &r
->out
.info
->info2
);
8544 result
= WERR_UNKNOWN_LEVEL
;
8549 free_a_printer(&ntprinter
, 2);
8551 if (!W_ERROR_IS_OK(result
)) {
8552 TALLOC_FREE(r
->out
.info
);
8556 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, r
->out
.info
,
8558 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8560 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8563 /****************************************************************
8564 _spoolss_GetPrinterDataEx
8565 ****************************************************************/
8567 WERROR
_spoolss_GetPrinterDataEx(pipes_struct
*p
,
8568 struct spoolss_GetPrinterDataEx
*r
)
8571 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8572 struct regval_blob
*val
= NULL
;
8573 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8575 WERROR result
= WERR_OK
;
8578 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8580 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8581 r
->in
.key_name
, r
->in
.value_name
));
8583 /* in case of problem, return some default values */
8586 *r
->out
.type
= REG_NONE
;
8589 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8590 OUR_HANDLE(r
->in
.handle
)));
8591 result
= WERR_BADFID
;
8595 /* Is the handle to a printer or to the server? */
8597 if (Printer
->printer_type
== SPLHND_SERVER
) {
8599 union spoolss_PrinterData data
;
8601 result
= getprinterdata_printer_server(p
->mem_ctx
,
8605 if (!W_ERROR_IS_OK(result
)) {
8609 result
= push_spoolss_PrinterData(p
->mem_ctx
, &blob
,
8610 *r
->out
.type
, &data
);
8611 if (!W_ERROR_IS_OK(result
)) {
8615 *r
->out
.needed
= blob
.length
;
8617 if (r
->in
.offered
>= *r
->out
.needed
) {
8618 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
8621 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8624 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8625 result
= WERR_BADFID
;
8629 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8630 if (!W_ERROR_IS_OK(result
)) {
8634 /* check to see if the keyname is valid */
8635 if (!strlen(r
->in
.key_name
)) {
8636 result
= WERR_INVALID_PARAM
;
8640 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8642 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
8643 strequal(r
->in
.value_name
, "ChangeId")) {
8644 *r
->out
.type
= REG_DWORD
;
8646 if (r
->in
.offered
>= *r
->out
.needed
) {
8647 SIVAL(r
->out
.data
, 0, printer
->info_2
->changeid
);
8653 if (lookup_printerkey(printer
->info_2
->data
, r
->in
.key_name
) == -1) {
8654 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8655 "Invalid keyname [%s]\n", r
->in
.key_name
));
8656 result
= WERR_BADFILE
;
8660 val
= get_printer_data(printer
->info_2
,
8661 r
->in
.key_name
, r
->in
.value_name
);
8663 result
= WERR_BADFILE
;
8667 *r
->out
.needed
= regval_size(val
);
8668 *r
->out
.type
= regval_type(val
);
8670 if (r
->in
.offered
>= *r
->out
.needed
) {
8671 memcpy(r
->out
.data
, regval_data_p(val
), regval_size(val
));
8675 free_a_printer(&printer
, 2);
8678 if (!W_ERROR_IS_OK(result
)) {
8682 *r
->out
.type
= SPOOLSS_BUFFER_OK(*r
->out
.type
, REG_NONE
);
8683 r
->out
.data
= SPOOLSS_BUFFER_OK(r
->out
.data
, r
->out
.data
);
8685 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8688 /****************************************************************
8689 _spoolss_SetPrinterDataEx
8690 ****************************************************************/
8692 WERROR
_spoolss_SetPrinterDataEx(pipes_struct
*p
,
8693 struct spoolss_SetPrinterDataEx
*r
)
8695 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8697 WERROR result
= WERR_OK
;
8698 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8701 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8703 /* From MSDN documentation of SetPrinterDataEx: pass request to
8704 SetPrinterData if key is "PrinterDriverData" */
8707 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8708 OUR_HANDLE(r
->in
.handle
)));
8712 if (Printer
->printer_type
== SPLHND_SERVER
) {
8713 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8714 "Not implemented for server handles yet\n"));
8715 return WERR_INVALID_PARAM
;
8718 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8723 * Access check : NT returns "access denied" if you make a
8724 * SetPrinterData call without the necessary privildge.
8725 * we were originally returning OK if nothing changed
8726 * which made Win2k issue **a lot** of SetPrinterData
8727 * when connecting to a printer --jerry
8730 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8731 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8732 "change denied by handle access permissions\n"));
8733 return WERR_ACCESS_DENIED
;
8736 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8737 if (!W_ERROR_IS_OK(result
)) {
8741 /* check for OID in valuename */
8743 oid_string
= strchr(r
->in
.value_name
, ',');
8749 /* save the registry data */
8751 result
= set_printer_dataex(printer
, r
->in
.key_name
, r
->in
.value_name
,
8752 r
->in
.type
, r
->in
.data
, r
->in
.offered
);
8754 if (W_ERROR_IS_OK(result
)) {
8755 /* save the OID if one was specified */
8757 char *str
= talloc_asprintf(p
->mem_ctx
, "%s\\%s",
8758 r
->in
.key_name
, SPOOL_OID_KEY
);
8760 result
= WERR_NOMEM
;
8765 * I'm not checking the status here on purpose. Don't know
8766 * if this is right, but I'm returning the status from the
8767 * previous set_printer_dataex() call. I have no idea if
8768 * this is right. --jerry
8771 set_printer_dataex(printer
, str
, r
->in
.value_name
,
8772 REG_SZ
, (uint8_t *)oid_string
,
8773 strlen(oid_string
)+1);
8776 result
= mod_a_printer(printer
, 2);
8780 free_a_printer(&printer
, 2);
8785 /****************************************************************
8786 _spoolss_DeletePrinterDataEx
8787 ****************************************************************/
8789 WERROR
_spoolss_DeletePrinterDataEx(pipes_struct
*p
,
8790 struct spoolss_DeletePrinterDataEx
*r
)
8792 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8794 WERROR status
= WERR_OK
;
8795 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8797 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8800 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8801 "Invalid handle (%s:%u:%u).\n",
8802 OUR_HANDLE(r
->in
.handle
)));
8806 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8809 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8810 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8811 "printer properties change denied by handle\n"));
8812 return WERR_ACCESS_DENIED
;
8815 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
8819 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8820 if (!W_ERROR_IS_OK(status
))
8823 status
= delete_printer_dataex( printer
, r
->in
.key_name
, r
->in
.value_name
);
8825 if ( W_ERROR_IS_OK(status
) )
8826 mod_a_printer( printer
, 2 );
8828 free_a_printer(&printer
, 2);
8833 /****************************************************************
8834 _spoolss_EnumPrinterKey
8835 ****************************************************************/
8837 WERROR
_spoolss_EnumPrinterKey(pipes_struct
*p
,
8838 struct spoolss_EnumPrinterKey
*r
)
8840 fstring
*keynames
= NULL
;
8842 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8843 NT_PRINTER_DATA
*data
;
8844 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8846 WERROR result
= WERR_BADFILE
;
8848 const char **array
= NULL
;
8851 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8854 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8855 OUR_HANDLE(r
->in
.handle
)));
8859 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8863 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8864 if (!W_ERROR_IS_OK(result
)) {
8868 /* get the list of subkey names */
8870 data
= printer
->info_2
->data
;
8872 num_keys
= get_printer_subkeys(data
, r
->in
.key_name
, &keynames
);
8873 if (num_keys
== -1) {
8874 result
= WERR_BADFILE
;
8878 array
= talloc_zero_array(r
->out
.key_buffer
, const char *, num_keys
+ 2);
8880 result
= WERR_NOMEM
;
8885 array
[0] = talloc_strdup(array
, "");
8887 result
= WERR_NOMEM
;
8892 for (i
=0; i
< num_keys
; i
++) {
8894 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8897 array
[i
] = talloc_strdup(array
, keynames
[i
]);
8899 result
= WERR_NOMEM
;
8904 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
8905 result
= WERR_NOMEM
;
8909 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
8910 *r
->out
.needed
= blob
.length
;
8912 if (r
->in
.offered
< *r
->out
.needed
) {
8913 result
= WERR_MORE_DATA
;
8916 r
->out
.key_buffer
->string_array
= array
;
8920 if (!W_ERROR_IS_OK(result
)) {
8922 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
8927 free_a_printer(&printer
, 2);
8928 SAFE_FREE(keynames
);
8933 /****************************************************************
8934 _spoolss_DeletePrinterKey
8935 ****************************************************************/
8937 WERROR
_spoolss_DeletePrinterKey(pipes_struct
*p
,
8938 struct spoolss_DeletePrinterKey
*r
)
8940 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8941 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8945 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8948 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8949 OUR_HANDLE(r
->in
.handle
)));
8953 /* if keyname == NULL, return error */
8955 if ( !r
->in
.key_name
)
8956 return WERR_INVALID_PARAM
;
8958 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8961 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8962 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8963 "printer properties change denied by handle\n"));
8964 return WERR_ACCESS_DENIED
;
8967 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8968 if (!W_ERROR_IS_OK(status
))
8971 /* delete the key and all subneys */
8973 status
= delete_all_printer_data( printer
->info_2
, r
->in
.key_name
);
8975 if ( W_ERROR_IS_OK(status
) )
8976 status
= mod_a_printer(printer
, 2);
8978 free_a_printer( &printer
, 2 );
8983 /****************************************************************
8984 ****************************************************************/
8986 static WERROR
registry_value_to_printer_enum_value(TALLOC_CTX
*mem_ctx
,
8987 struct regval_blob
*v
,
8988 struct spoolss_PrinterEnumValues
*r
)
8990 r
->data
= TALLOC_ZERO_P(mem_ctx
, DATA_BLOB
);
8991 W_ERROR_HAVE_NO_MEMORY(r
->data
);
8993 r
->value_name
= talloc_strdup(mem_ctx
, regval_name(v
));
8994 W_ERROR_HAVE_NO_MEMORY(r
->value_name
);
8996 r
->value_name_len
= strlen_m_term(regval_name(v
)) * 2;
8998 r
->type
= regval_type(v
);
8999 r
->data_length
= regval_size(v
);
9001 if (r
->data_length
) {
9002 *r
->data
= data_blob_talloc(r
->data
, regval_data_p(v
), regval_size(v
));
9008 /****************************************************************
9009 _spoolss_EnumPrinterDataEx
9010 ****************************************************************/
9012 WERROR
_spoolss_EnumPrinterDataEx(pipes_struct
*p
,
9013 struct spoolss_EnumPrinterDataEx
*r
)
9016 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9017 struct spoolss_PrinterEnumValues
*info
= NULL
;
9018 NT_PRINTER_DATA
*p_data
;
9019 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9025 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9029 *r
->out
.info
= NULL
;
9032 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9033 OUR_HANDLE(r
->in
.handle
)));
9038 * first check for a keyname of NULL or "". Win2k seems to send
9039 * this a lot and we should send back WERR_INVALID_PARAM
9040 * no need to spend time looking up the printer in this case.
9044 if (!strlen(r
->in
.key_name
)) {
9045 result
= WERR_INVALID_PARAM
;
9049 /* get the printer off of disk */
9051 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9055 ZERO_STRUCT(printer
);
9056 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9057 if (!W_ERROR_IS_OK(result
)) {
9061 /* now look for a match on the key name */
9063 p_data
= printer
->info_2
->data
;
9065 key_index
= lookup_printerkey(p_data
, r
->in
.key_name
);
9066 if (key_index
== -1) {
9067 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9069 result
= WERR_INVALID_PARAM
;
9073 /* allocate the memory for the array of pointers -- if necessary */
9075 count
= regval_ctr_numvals(p_data
->keys
[key_index
].values
);
9077 result
= WERR_OK
; /* ??? */
9081 info
= TALLOC_ZERO_ARRAY(p
->mem_ctx
,
9082 struct spoolss_PrinterEnumValues
,
9085 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9086 result
= WERR_NOMEM
;
9091 * loop through all params and build the array to pass
9092 * back to the client
9095 for (i
=0; i
< count
; i
++) {
9097 struct regval_blob
*val
;
9099 /* lookup the registry value */
9101 val
= regval_ctr_specific_value(p_data
->keys
[key_index
].values
, i
);
9103 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
)));
9107 result
= registry_value_to_printer_enum_value(info
, val
, &info
[i
]);
9108 if (!W_ERROR_IS_OK(result
)) {
9113 #if 0 /* FIXME - gd */
9114 /* housekeeping information in the reply */
9116 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9117 * the hand marshalled container size is a multiple
9118 * of 4 bytes for RPC alignment.
9122 needed
+= 4-(needed
% 4);
9125 *r
->out
.count
= count
;
9126 *r
->out
.info
= info
;
9131 free_a_printer(&printer
, 2);
9134 if (!W_ERROR_IS_OK(result
)) {
9138 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
9139 spoolss_EnumPrinterDataEx
,
9142 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9143 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
9145 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9148 /****************************************************************************
9149 ****************************************************************************/
9151 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
9152 const char *servername
,
9153 const char *environment
,
9154 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
9159 werr
= compose_spoolss_server_path(mem_ctx
,
9162 SPOOLSS_PRTPROCS_PATH
,
9164 if (!W_ERROR_IS_OK(werr
)) {
9168 DEBUG(4,("print processor directory: [%s]\n", path
));
9170 r
->directory_name
= path
;
9175 /****************************************************************
9176 _spoolss_GetPrintProcessorDirectory
9177 ****************************************************************/
9179 WERROR
_spoolss_GetPrintProcessorDirectory(pipes_struct
*p
,
9180 struct spoolss_GetPrintProcessorDirectory
*r
)
9184 /* that's an [in out] buffer */
9186 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9187 return WERR_INVALID_PARAM
;
9190 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9195 /* r->in.level is ignored */
9197 /* We always should reply with a local print processor directory so that
9198 * users are not forced to have a [prnproc$] share on the Samba spoolss
9199 * server - Guenther */
9201 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9202 NULL
, /* r->in.server */
9204 &r
->out
.info
->info1
);
9205 if (!W_ERROR_IS_OK(result
)) {
9206 TALLOC_FREE(r
->out
.info
);
9210 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
,
9211 r
->out
.info
, r
->in
.level
);
9212 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9214 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9217 /*******************************************************************
9218 ********************************************************************/
9220 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9221 const char *dllname
)
9223 enum ndr_err_code ndr_err
;
9224 struct spoolss_MonitorUi ui
;
9226 ui
.dll_name
= dllname
;
9228 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, &ui
,
9229 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9230 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9231 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9233 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9236 /*******************************************************************
9237 Streams the monitor UI DLL name in UNICODE
9238 *******************************************************************/
9240 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9241 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9242 DATA_BLOB
*out
, uint32_t *needed
)
9244 const char *dllname
= "tcpmonui.dll";
9246 *needed
= (strlen(dllname
)+1) * 2;
9248 if (out
->length
< *needed
) {
9249 return WERR_INSUFFICIENT_BUFFER
;
9252 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9259 /*******************************************************************
9260 ********************************************************************/
9262 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9263 struct spoolss_PortData1
*port1
,
9264 const DATA_BLOB
*buf
)
9266 enum ndr_err_code ndr_err
;
9267 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port1
,
9268 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9269 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9270 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9272 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9275 /*******************************************************************
9276 ********************************************************************/
9278 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9279 struct spoolss_PortData2
*port2
,
9280 const DATA_BLOB
*buf
)
9282 enum ndr_err_code ndr_err
;
9283 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port2
,
9284 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9285 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9286 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9288 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9291 /*******************************************************************
9292 Create a new TCP/IP port
9293 *******************************************************************/
9295 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9296 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9297 DATA_BLOB
*out
, uint32_t *needed
)
9299 struct spoolss_PortData1 port1
;
9300 struct spoolss_PortData2 port2
;
9301 char *device_uri
= NULL
;
9304 const char *portname
;
9305 const char *hostaddress
;
9307 uint32_t port_number
;
9310 /* peek for spoolss_PortData version */
9312 if (!in
|| (in
->length
< (128 + 4))) {
9313 return WERR_GENERAL_FAILURE
;
9316 version
= IVAL(in
->data
, 128);
9322 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9326 portname
= port1
.portname
;
9327 hostaddress
= port1
.hostaddress
;
9328 queue
= port1
.queue
;
9329 protocol
= port1
.protocol
;
9330 port_number
= port1
.port_number
;
9336 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9340 portname
= port2
.portname
;
9341 hostaddress
= port2
.hostaddress
;
9342 queue
= port2
.queue
;
9343 protocol
= port2
.protocol
;
9344 port_number
= port2
.port_number
;
9348 DEBUG(1,("xcvtcp_addport: "
9349 "unknown version of port_data: %d\n", version
));
9350 return WERR_UNKNOWN_PORT
;
9353 /* create the device URI and call the add_port_hook() */
9356 case PROTOCOL_RAWTCP_TYPE
:
9357 device_uri
= talloc_asprintf(mem_ctx
,
9358 "socket://%s:%d/", hostaddress
,
9362 case PROTOCOL_LPR_TYPE
:
9363 device_uri
= talloc_asprintf(mem_ctx
,
9364 "lpr://%s/%s", hostaddress
, queue
);
9368 return WERR_UNKNOWN_PORT
;
9375 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
9378 /*******************************************************************
9379 *******************************************************************/
9381 struct xcv_api_table xcvtcp_cmds
[] = {
9382 { "MonitorUI", xcvtcp_monitorui
},
9383 { "AddPort", xcvtcp_addport
},
9387 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
9388 NT_USER_TOKEN
*token
, const char *command
,
9395 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9397 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9398 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9399 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9402 return WERR_BADFUNC
;
9405 /*******************************************************************
9406 *******************************************************************/
9407 #if 0 /* don't support management using the "Local Port" monitor */
9409 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
9410 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9411 DATA_BLOB
*out
, uint32_t *needed
)
9413 const char *dllname
= "localui.dll";
9415 *needed
= (strlen(dllname
)+1) * 2;
9417 if (out
->length
< *needed
) {
9418 return WERR_INSUFFICIENT_BUFFER
;
9421 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9428 /*******************************************************************
9429 *******************************************************************/
9431 struct xcv_api_table xcvlocal_cmds
[] = {
9432 { "MonitorUI", xcvlocal_monitorui
},
9436 struct xcv_api_table xcvlocal_cmds
[] = {
9443 /*******************************************************************
9444 *******************************************************************/
9446 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
9447 NT_USER_TOKEN
*token
, const char *command
,
9448 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
9453 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9455 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9456 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9457 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9459 return WERR_BADFUNC
;
9462 /****************************************************************
9464 ****************************************************************/
9466 WERROR
_spoolss_XcvData(pipes_struct
*p
,
9467 struct spoolss_XcvData
*r
)
9469 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9470 DATA_BLOB out_data
= data_blob_null
;
9474 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9475 OUR_HANDLE(r
->in
.handle
)));
9479 /* Has to be a handle to the TCP/IP port monitor */
9481 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9482 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9486 /* requires administrative access to the server */
9488 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9489 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9490 return WERR_ACCESS_DENIED
;
9493 /* Allocate the outgoing buffer */
9495 if (r
->in
.out_data_size
) {
9496 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
9497 if (out_data
.data
== NULL
) {
9502 switch ( Printer
->printer_type
) {
9503 case SPLHND_PORTMON_TCP
:
9504 werror
= process_xcvtcp_command(p
->mem_ctx
,
9505 p
->server_info
->ptok
,
9506 r
->in
.function_name
,
9507 &r
->in
.in_data
, &out_data
,
9510 case SPLHND_PORTMON_LOCAL
:
9511 werror
= process_xcvlocal_command(p
->mem_ctx
,
9512 p
->server_info
->ptok
,
9513 r
->in
.function_name
,
9514 &r
->in
.in_data
, &out_data
,
9518 werror
= WERR_INVALID_PRINT_MONITOR
;
9521 if (!W_ERROR_IS_OK(werror
)) {
9525 *r
->out
.status_code
= 0;
9527 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
9528 memcpy(r
->out
.out_data
, out_data
.data
,
9529 MIN(r
->in
.out_data_size
, out_data
.length
));
9535 /****************************************************************
9536 _spoolss_AddPrintProcessor
9537 ****************************************************************/
9539 WERROR
_spoolss_AddPrintProcessor(pipes_struct
*p
,
9540 struct spoolss_AddPrintProcessor
*r
)
9542 /* for now, just indicate success and ignore the add. We'll
9543 automatically set the winprint processor for printer
9544 entries later. Used to debug the LexMark Optra S 1855 PCL
9550 /****************************************************************
9552 ****************************************************************/
9554 WERROR
_spoolss_AddPort(pipes_struct
*p
,
9555 struct spoolss_AddPort
*r
)
9557 /* do what w2k3 does */
9559 return WERR_NOT_SUPPORTED
;
9562 /****************************************************************
9563 _spoolss_GetPrinterDriver
9564 ****************************************************************/
9566 WERROR
_spoolss_GetPrinterDriver(pipes_struct
*p
,
9567 struct spoolss_GetPrinterDriver
*r
)
9569 p
->rng_fault_state
= true;
9570 return WERR_NOT_SUPPORTED
;
9573 /****************************************************************
9574 _spoolss_ReadPrinter
9575 ****************************************************************/
9577 WERROR
_spoolss_ReadPrinter(pipes_struct
*p
,
9578 struct spoolss_ReadPrinter
*r
)
9580 p
->rng_fault_state
= true;
9581 return WERR_NOT_SUPPORTED
;
9584 /****************************************************************
9585 _spoolss_WaitForPrinterChange
9586 ****************************************************************/
9588 WERROR
_spoolss_WaitForPrinterChange(pipes_struct
*p
,
9589 struct spoolss_WaitForPrinterChange
*r
)
9591 p
->rng_fault_state
= true;
9592 return WERR_NOT_SUPPORTED
;
9595 /****************************************************************
9596 _spoolss_ConfigurePort
9597 ****************************************************************/
9599 WERROR
_spoolss_ConfigurePort(pipes_struct
*p
,
9600 struct spoolss_ConfigurePort
*r
)
9602 p
->rng_fault_state
= true;
9603 return WERR_NOT_SUPPORTED
;
9606 /****************************************************************
9608 ****************************************************************/
9610 WERROR
_spoolss_DeletePort(pipes_struct
*p
,
9611 struct spoolss_DeletePort
*r
)
9613 p
->rng_fault_state
= true;
9614 return WERR_NOT_SUPPORTED
;
9617 /****************************************************************
9618 _spoolss_CreatePrinterIC
9619 ****************************************************************/
9621 WERROR
_spoolss_CreatePrinterIC(pipes_struct
*p
,
9622 struct spoolss_CreatePrinterIC
*r
)
9624 p
->rng_fault_state
= true;
9625 return WERR_NOT_SUPPORTED
;
9628 /****************************************************************
9629 _spoolss_PlayGDIScriptOnPrinterIC
9630 ****************************************************************/
9632 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(pipes_struct
*p
,
9633 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
9635 p
->rng_fault_state
= true;
9636 return WERR_NOT_SUPPORTED
;
9639 /****************************************************************
9640 _spoolss_DeletePrinterIC
9641 ****************************************************************/
9643 WERROR
_spoolss_DeletePrinterIC(pipes_struct
*p
,
9644 struct spoolss_DeletePrinterIC
*r
)
9646 p
->rng_fault_state
= true;
9647 return WERR_NOT_SUPPORTED
;
9650 /****************************************************************
9651 _spoolss_AddPrinterConnection
9652 ****************************************************************/
9654 WERROR
_spoolss_AddPrinterConnection(pipes_struct
*p
,
9655 struct spoolss_AddPrinterConnection
*r
)
9657 p
->rng_fault_state
= true;
9658 return WERR_NOT_SUPPORTED
;
9661 /****************************************************************
9662 _spoolss_DeletePrinterConnection
9663 ****************************************************************/
9665 WERROR
_spoolss_DeletePrinterConnection(pipes_struct
*p
,
9666 struct spoolss_DeletePrinterConnection
*r
)
9668 p
->rng_fault_state
= true;
9669 return WERR_NOT_SUPPORTED
;
9672 /****************************************************************
9673 _spoolss_PrinterMessageBox
9674 ****************************************************************/
9676 WERROR
_spoolss_PrinterMessageBox(pipes_struct
*p
,
9677 struct spoolss_PrinterMessageBox
*r
)
9679 p
->rng_fault_state
= true;
9680 return WERR_NOT_SUPPORTED
;
9683 /****************************************************************
9685 ****************************************************************/
9687 WERROR
_spoolss_AddMonitor(pipes_struct
*p
,
9688 struct spoolss_AddMonitor
*r
)
9690 p
->rng_fault_state
= true;
9691 return WERR_NOT_SUPPORTED
;
9694 /****************************************************************
9695 _spoolss_DeleteMonitor
9696 ****************************************************************/
9698 WERROR
_spoolss_DeleteMonitor(pipes_struct
*p
,
9699 struct spoolss_DeleteMonitor
*r
)
9701 p
->rng_fault_state
= true;
9702 return WERR_NOT_SUPPORTED
;
9705 /****************************************************************
9706 _spoolss_DeletePrintProcessor
9707 ****************************************************************/
9709 WERROR
_spoolss_DeletePrintProcessor(pipes_struct
*p
,
9710 struct spoolss_DeletePrintProcessor
*r
)
9712 p
->rng_fault_state
= true;
9713 return WERR_NOT_SUPPORTED
;
9716 /****************************************************************
9717 _spoolss_AddPrintProvidor
9718 ****************************************************************/
9720 WERROR
_spoolss_AddPrintProvidor(pipes_struct
*p
,
9721 struct spoolss_AddPrintProvidor
*r
)
9723 p
->rng_fault_state
= true;
9724 return WERR_NOT_SUPPORTED
;
9727 /****************************************************************
9728 _spoolss_DeletePrintProvidor
9729 ****************************************************************/
9731 WERROR
_spoolss_DeletePrintProvidor(pipes_struct
*p
,
9732 struct spoolss_DeletePrintProvidor
*r
)
9734 p
->rng_fault_state
= true;
9735 return WERR_NOT_SUPPORTED
;
9738 /****************************************************************
9739 _spoolss_FindFirstPrinterChangeNotification
9740 ****************************************************************/
9742 WERROR
_spoolss_FindFirstPrinterChangeNotification(pipes_struct
*p
,
9743 struct spoolss_FindFirstPrinterChangeNotification
*r
)
9745 p
->rng_fault_state
= true;
9746 return WERR_NOT_SUPPORTED
;
9749 /****************************************************************
9750 _spoolss_FindNextPrinterChangeNotification
9751 ****************************************************************/
9753 WERROR
_spoolss_FindNextPrinterChangeNotification(pipes_struct
*p
,
9754 struct spoolss_FindNextPrinterChangeNotification
*r
)
9756 p
->rng_fault_state
= true;
9757 return WERR_NOT_SUPPORTED
;
9760 /****************************************************************
9761 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9762 ****************************************************************/
9764 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct
*p
,
9765 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
9767 p
->rng_fault_state
= true;
9768 return WERR_NOT_SUPPORTED
;
9771 /****************************************************************
9772 _spoolss_ReplyOpenPrinter
9773 ****************************************************************/
9775 WERROR
_spoolss_ReplyOpenPrinter(pipes_struct
*p
,
9776 struct spoolss_ReplyOpenPrinter
*r
)
9778 p
->rng_fault_state
= true;
9779 return WERR_NOT_SUPPORTED
;
9782 /****************************************************************
9783 _spoolss_RouterReplyPrinter
9784 ****************************************************************/
9786 WERROR
_spoolss_RouterReplyPrinter(pipes_struct
*p
,
9787 struct spoolss_RouterReplyPrinter
*r
)
9789 p
->rng_fault_state
= true;
9790 return WERR_NOT_SUPPORTED
;
9793 /****************************************************************
9794 _spoolss_ReplyClosePrinter
9795 ****************************************************************/
9797 WERROR
_spoolss_ReplyClosePrinter(pipes_struct
*p
,
9798 struct spoolss_ReplyClosePrinter
*r
)
9800 p
->rng_fault_state
= true;
9801 return WERR_NOT_SUPPORTED
;
9804 /****************************************************************
9806 ****************************************************************/
9808 WERROR
_spoolss_AddPortEx(pipes_struct
*p
,
9809 struct spoolss_AddPortEx
*r
)
9811 p
->rng_fault_state
= true;
9812 return WERR_NOT_SUPPORTED
;
9815 /****************************************************************
9816 _spoolss_RouterFindFirstPrinterChangeNotification
9817 ****************************************************************/
9819 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct
*p
,
9820 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
9822 p
->rng_fault_state
= true;
9823 return WERR_NOT_SUPPORTED
;
9826 /****************************************************************
9827 _spoolss_SpoolerInit
9828 ****************************************************************/
9830 WERROR
_spoolss_SpoolerInit(pipes_struct
*p
,
9831 struct spoolss_SpoolerInit
*r
)
9833 p
->rng_fault_state
= true;
9834 return WERR_NOT_SUPPORTED
;
9837 /****************************************************************
9838 _spoolss_ResetPrinterEx
9839 ****************************************************************/
9841 WERROR
_spoolss_ResetPrinterEx(pipes_struct
*p
,
9842 struct spoolss_ResetPrinterEx
*r
)
9844 p
->rng_fault_state
= true;
9845 return WERR_NOT_SUPPORTED
;
9848 /****************************************************************
9849 _spoolss_RouterReplyPrinterEx
9850 ****************************************************************/
9852 WERROR
_spoolss_RouterReplyPrinterEx(pipes_struct
*p
,
9853 struct spoolss_RouterReplyPrinterEx
*r
)
9855 p
->rng_fault_state
= true;
9856 return WERR_NOT_SUPPORTED
;
9859 /****************************************************************
9861 ****************************************************************/
9863 WERROR
_spoolss_44(pipes_struct
*p
,
9864 struct spoolss_44
*r
)
9866 p
->rng_fault_state
= true;
9867 return WERR_NOT_SUPPORTED
;
9870 /****************************************************************
9872 ****************************************************************/
9874 WERROR
_spoolss_47(pipes_struct
*p
,
9875 struct spoolss_47
*r
)
9877 p
->rng_fault_state
= true;
9878 return WERR_NOT_SUPPORTED
;
9881 /****************************************************************
9883 ****************************************************************/
9885 WERROR
_spoolss_4a(pipes_struct
*p
,
9886 struct spoolss_4a
*r
)
9888 p
->rng_fault_state
= true;
9889 return WERR_NOT_SUPPORTED
;
9892 /****************************************************************
9894 ****************************************************************/
9896 WERROR
_spoolss_4b(pipes_struct
*p
,
9897 struct spoolss_4b
*r
)
9899 p
->rng_fault_state
= true;
9900 return WERR_NOT_SUPPORTED
;
9903 /****************************************************************
9905 ****************************************************************/
9907 WERROR
_spoolss_4c(pipes_struct
*p
,
9908 struct spoolss_4c
*r
)
9910 p
->rng_fault_state
= true;
9911 return WERR_NOT_SUPPORTED
;
9914 /****************************************************************
9916 ****************************************************************/
9918 WERROR
_spoolss_53(pipes_struct
*p
,
9919 struct spoolss_53
*r
)
9921 p
->rng_fault_state
= true;
9922 return WERR_NOT_SUPPORTED
;
9925 /****************************************************************
9927 ****************************************************************/
9929 WERROR
_spoolss_55(pipes_struct
*p
,
9930 struct spoolss_55
*r
)
9932 p
->rng_fault_state
= true;
9933 return WERR_NOT_SUPPORTED
;
9936 /****************************************************************
9938 ****************************************************************/
9940 WERROR
_spoolss_56(pipes_struct
*p
,
9941 struct spoolss_56
*r
)
9943 p
->rng_fault_state
= true;
9944 return WERR_NOT_SUPPORTED
;
9947 /****************************************************************
9949 ****************************************************************/
9951 WERROR
_spoolss_57(pipes_struct
*p
,
9952 struct spoolss_57
*r
)
9954 p
->rng_fault_state
= true;
9955 return WERR_NOT_SUPPORTED
;
9958 /****************************************************************
9960 ****************************************************************/
9962 WERROR
_spoolss_5a(pipes_struct
*p
,
9963 struct spoolss_5a
*r
)
9965 p
->rng_fault_state
= true;
9966 return WERR_NOT_SUPPORTED
;
9969 /****************************************************************
9971 ****************************************************************/
9973 WERROR
_spoolss_5b(pipes_struct
*p
,
9974 struct spoolss_5b
*r
)
9976 p
->rng_fault_state
= true;
9977 return WERR_NOT_SUPPORTED
;
9980 /****************************************************************
9982 ****************************************************************/
9984 WERROR
_spoolss_5c(pipes_struct
*p
,
9985 struct spoolss_5c
*r
)
9987 p
->rng_fault_state
= true;
9988 return WERR_NOT_SUPPORTED
;
9991 /****************************************************************
9993 ****************************************************************/
9995 WERROR
_spoolss_5d(pipes_struct
*p
,
9996 struct spoolss_5d
*r
)
9998 p
->rng_fault_state
= true;
9999 return WERR_NOT_SUPPORTED
;
10002 /****************************************************************
10004 ****************************************************************/
10006 WERROR
_spoolss_5e(pipes_struct
*p
,
10007 struct spoolss_5e
*r
)
10009 p
->rng_fault_state
= true;
10010 return WERR_NOT_SUPPORTED
;
10013 /****************************************************************
10015 ****************************************************************/
10017 WERROR
_spoolss_5f(pipes_struct
*p
,
10018 struct spoolss_5f
*r
)
10020 p
->rng_fault_state
= true;
10021 return WERR_NOT_SUPPORTED
;
10024 /****************************************************************
10026 ****************************************************************/
10028 WERROR
_spoolss_60(pipes_struct
*p
,
10029 struct spoolss_60
*r
)
10031 p
->rng_fault_state
= true;
10032 return WERR_NOT_SUPPORTED
;
10035 /****************************************************************
10037 ****************************************************************/
10039 WERROR
_spoolss_61(pipes_struct
*p
,
10040 struct spoolss_61
*r
)
10042 p
->rng_fault_state
= true;
10043 return WERR_NOT_SUPPORTED
;
10046 /****************************************************************
10048 ****************************************************************/
10050 WERROR
_spoolss_62(pipes_struct
*p
,
10051 struct spoolss_62
*r
)
10053 p
->rng_fault_state
= true;
10054 return WERR_NOT_SUPPORTED
;
10057 /****************************************************************
10059 ****************************************************************/
10061 WERROR
_spoolss_63(pipes_struct
*p
,
10062 struct spoolss_63
*r
)
10064 p
->rng_fault_state
= true;
10065 return WERR_NOT_SUPPORTED
;
10068 /****************************************************************
10070 ****************************************************************/
10072 WERROR
_spoolss_64(pipes_struct
*p
,
10073 struct spoolss_64
*r
)
10075 p
->rng_fault_state
= true;
10076 return WERR_NOT_SUPPORTED
;
10079 /****************************************************************
10081 ****************************************************************/
10083 WERROR
_spoolss_65(pipes_struct
*p
,
10084 struct spoolss_65
*r
)
10086 p
->rng_fault_state
= true;
10087 return WERR_NOT_SUPPORTED
;
10090 /****************************************************************
10091 _spoolss_GetCorePrinterDrivers
10092 ****************************************************************/
10094 WERROR
_spoolss_GetCorePrinterDrivers(pipes_struct
*p
,
10095 struct spoolss_GetCorePrinterDrivers
*r
)
10097 p
->rng_fault_state
= true;
10098 return WERR_NOT_SUPPORTED
;
10101 /****************************************************************
10103 ****************************************************************/
10105 WERROR
_spoolss_67(pipes_struct
*p
,
10106 struct spoolss_67
*r
)
10108 p
->rng_fault_state
= true;
10109 return WERR_NOT_SUPPORTED
;
10112 /****************************************************************
10113 _spoolss_GetPrinterDriverPackagePath
10114 ****************************************************************/
10116 WERROR
_spoolss_GetPrinterDriverPackagePath(pipes_struct
*p
,
10117 struct spoolss_GetPrinterDriverPackagePath
*r
)
10119 p
->rng_fault_state
= true;
10120 return WERR_NOT_SUPPORTED
;
10123 /****************************************************************
10125 ****************************************************************/
10127 WERROR
_spoolss_69(pipes_struct
*p
,
10128 struct spoolss_69
*r
)
10130 p
->rng_fault_state
= true;
10131 return WERR_NOT_SUPPORTED
;
10134 /****************************************************************
10136 ****************************************************************/
10138 WERROR
_spoolss_6a(pipes_struct
*p
,
10139 struct spoolss_6a
*r
)
10141 p
->rng_fault_state
= true;
10142 return WERR_NOT_SUPPORTED
;
10145 /****************************************************************
10147 ****************************************************************/
10149 WERROR
_spoolss_6b(pipes_struct
*p
,
10150 struct spoolss_6b
*r
)
10152 p
->rng_fault_state
= true;
10153 return WERR_NOT_SUPPORTED
;
10156 /****************************************************************
10158 ****************************************************************/
10160 WERROR
_spoolss_6c(pipes_struct
*p
,
10161 struct spoolss_6c
*r
)
10163 p
->rng_fault_state
= true;
10164 return WERR_NOT_SUPPORTED
;
10167 /****************************************************************
10169 ****************************************************************/
10171 WERROR
_spoolss_6d(pipes_struct
*p
,
10172 struct spoolss_6d
*r
)
10174 p
->rng_fault_state
= true;
10175 return WERR_NOT_SUPPORTED
;