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 "librpc/gen_ndr/messaging.h"
35 /* macros stolen from s4 spoolss server */
36 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
37 ((info)?ndr_size_##fn(info, level, 0):0)
39 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
40 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
42 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
43 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
45 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
48 extern userdom_struct current_user_info
;
51 #define DBGC_CLASS DBGC_RPC_SRV
53 #ifndef MAX_OPEN_PRINTER_EXS
54 #define MAX_OPEN_PRINTER_EXS 50
57 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
59 static Printer_entry
*printers_list
;
61 typedef struct _counter_printer_0
{
62 struct _counter_printer_0
*next
;
63 struct _counter_printer_0
*prev
;
69 static counter_printer_0
*counter_list
;
71 static struct rpc_pipe_client
*notify_cli_pipe
; /* print notify back-channel pipe handle*/
72 static uint32_t smb_connections
= 0;
75 /* in printing/nt_printing.c */
77 extern struct standard_mapping printer_std_mapping
, printserver_std_mapping
;
79 /* API table for Xcv Monitor functions */
81 struct xcv_api_table
{
83 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, NT_USER_TOKEN
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
86 /********************************************************************
87 * Canonicalize servername.
88 ********************************************************************/
90 static const char *canon_servername(const char *servername
)
92 const char *pservername
= servername
;
93 while (*pservername
== '\\') {
99 /* translate between internal status numbers and NT status numbers */
100 static int nt_printj_status(int v
)
106 return JOB_STATUS_PAUSED
;
108 return JOB_STATUS_SPOOLING
;
110 return JOB_STATUS_PRINTING
;
112 return JOB_STATUS_ERROR
;
114 return JOB_STATUS_DELETING
;
116 return JOB_STATUS_OFFLINE
;
118 return JOB_STATUS_PAPEROUT
;
120 return JOB_STATUS_PRINTED
;
122 return JOB_STATUS_DELETED
;
124 return JOB_STATUS_BLOCKED_DEVQ
;
125 case LPQ_USER_INTERVENTION
:
126 return JOB_STATUS_USER_INTERVENTION
;
131 static int nt_printq_status(int v
)
135 return PRINTER_STATUS_PAUSED
;
144 /***************************************************************************
145 Disconnect from the client
146 ****************************************************************************/
148 static void srv_spoolss_replycloseprinter(int snum
, struct policy_handle
*handle
)
154 * Tell the specific printing tdb we no longer want messages for this printer
155 * by deregistering our PID.
158 if (!print_notify_deregister_pid(snum
))
159 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum
) ));
161 /* weird if the test succeds !!! */
162 if (smb_connections
==0) {
163 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
167 status
= rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe
, talloc_tos(),
170 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
171 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
172 win_errstr(result
)));
174 /* if it's the last connection, deconnect the IPC$ share */
175 if (smb_connections
==1) {
177 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe
) );
178 notify_cli_pipe
= NULL
; /* The above call shuts downn the pipe also. */
180 messaging_deregister(smbd_messaging_context(),
181 MSG_PRINTER_NOTIFY2
, NULL
);
183 /* Tell the connections db we're no longer interested in
184 * printer notify messages. */
186 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY
);
192 /****************************************************************************
193 Functions to free a printer entry datastruct.
194 ****************************************************************************/
196 static int printer_entry_destructor(Printer_entry
*Printer
)
198 if (Printer
->notify
.client_connected
== true) {
201 if ( Printer
->printer_type
== SPLHND_SERVER
) {
203 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
204 } else if (Printer
->printer_type
== SPLHND_PRINTER
) {
205 snum
= print_queue_snum(Printer
->sharename
);
207 srv_spoolss_replycloseprinter(snum
,
208 &Printer
->notify
.client_hnd
);
212 Printer
->notify
.flags
=0;
213 Printer
->notify
.options
=0;
214 Printer
->notify
.localmachine
[0]='\0';
215 Printer
->notify
.printerlocal
=0;
216 TALLOC_FREE(Printer
->notify
.option
);
217 Printer
->notify
.client_connected
= false;
219 free_nt_devicemode( &Printer
->nt_devmode
);
220 free_a_printer( &Printer
->printer_info
, 2 );
222 /* Remove from the internal list. */
223 DLIST_REMOVE(printers_list
, Printer
);
227 /****************************************************************************
228 find printer index by handle
229 ****************************************************************************/
231 static Printer_entry
*find_printer_index_by_hnd(pipes_struct
*p
,
232 struct policy_handle
*hnd
)
234 Printer_entry
*find_printer
= NULL
;
236 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
237 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
244 /****************************************************************************
245 Close printer index by handle.
246 ****************************************************************************/
248 static bool close_printer_handle(pipes_struct
*p
, struct policy_handle
*hnd
)
250 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
253 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
258 close_policy_hnd(p
, hnd
);
263 /****************************************************************************
264 Delete a printer given a handle.
265 ****************************************************************************/
267 static WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *sharename
)
269 char *cmd
= lp_deleteprinter_cmd();
270 char *command
= NULL
;
272 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
273 bool is_print_op
= false;
275 /* can't fail if we don't try */
280 command
= talloc_asprintf(ctx
,
287 is_print_op
= user_has_privileges( token
, &se_printop
);
289 DEBUG(10,("Running [%s]\n", command
));
291 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
296 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
297 /* Tell everyone we updated smb.conf. */
298 message_send_all(smbd_messaging_context(),
299 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
305 /********** END SePrintOperatorPrivlege BLOCK **********/
307 DEBUGADD(10,("returned [%d]\n", ret
));
309 TALLOC_FREE(command
);
312 return WERR_BADFID
; /* What to return here? */
314 /* go ahead and re-read the services immediately */
316 reload_services(false);
319 if ( lp_servicenumber( sharename
) > 0 )
320 return WERR_ACCESS_DENIED
;
325 /****************************************************************************
326 Delete a printer given a handle.
327 ****************************************************************************/
329 static WERROR
delete_printer_handle(pipes_struct
*p
, struct policy_handle
*hnd
)
331 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
334 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
340 * It turns out that Windows allows delete printer on a handle
341 * opened by an admin user, then used on a pipe handle created
342 * by an anonymous user..... but they're working on security.... riiight !
346 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
347 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
348 return WERR_ACCESS_DENIED
;
351 /* this does not need a become root since the access check has been
352 done on the handle already */
354 if (del_a_printer( Printer
->sharename
) != 0) {
355 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
359 return delete_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
360 Printer
->sharename
);
363 /****************************************************************************
364 Return the snum of a printer corresponding to an handle.
365 ****************************************************************************/
367 static bool get_printer_snum(pipes_struct
*p
, struct policy_handle
*hnd
,
368 int *number
, struct share_params
**params
)
370 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
373 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
378 switch (Printer
->printer_type
) {
380 DEBUG(4,("short name:%s\n", Printer
->sharename
));
381 *number
= print_queue_snum(Printer
->sharename
);
382 return (*number
!= -1);
390 /****************************************************************************
391 Set printer handle type.
392 Check if it's \\server or \\server\printer
393 ****************************************************************************/
395 static bool set_printer_hnd_printertype(Printer_entry
*Printer
, const char *handlename
)
397 DEBUG(3,("Setting printer type=%s\n", handlename
));
399 if ( strlen(handlename
) < 3 ) {
400 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename
));
404 /* it's a print server */
405 if (*handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
406 DEBUGADD(4,("Printer is a print server\n"));
407 Printer
->printer_type
= SPLHND_SERVER
;
409 /* it's a printer (set_printer_hnd_name() will handle port monitors */
411 DEBUGADD(4,("Printer is a printer\n"));
412 Printer
->printer_type
= SPLHND_PRINTER
;
418 /****************************************************************************
419 Set printer handle name.. Accept names like \\server, \\server\printer,
420 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
421 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
422 XcvDataPort() interface.
423 ****************************************************************************/
425 static bool set_printer_hnd_name(Printer_entry
*Printer
, const char *handlename
)
428 int n_services
=lp_numservices();
429 char *aprinter
, *printername
;
430 const char *servername
;
433 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
436 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
,
437 (unsigned long)strlen(handlename
)));
439 aprinter
= CONST_DISCARD(char *, handlename
);
440 if ( *handlename
== '\\' ) {
441 servername
= canon_servername(handlename
);
442 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
447 servername
= global_myname();
450 /* save the servername to fill in replies on this handle */
452 if ( !is_myname_or_ipaddr( servername
) )
455 fstrcpy( Printer
->servername
, servername
);
457 if ( Printer
->printer_type
== SPLHND_SERVER
)
460 if ( Printer
->printer_type
!= SPLHND_PRINTER
)
463 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
465 /* check for the Port Monitor Interface */
467 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
468 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
469 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
472 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
473 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
474 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
478 /* Search all sharenames first as this is easier than pulling
479 the printer_info_2 off of disk. Don't use find_service() since
480 that calls out to map_username() */
482 /* do another loop to look for printernames */
484 for (snum
=0; !found
&& snum
<n_services
; snum
++) {
486 /* no point going on if this is not a printer */
488 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
491 fstrcpy(sname
, lp_servicename(snum
));
492 if ( strequal( aprinter
, sname
) ) {
497 /* no point looking up the printer object if
498 we aren't allowing printername != sharename */
500 if ( lp_force_printername(snum
) )
503 fstrcpy(sname
, lp_servicename(snum
));
507 /* This call doesn't fill in the location or comment from
508 * a CUPS server for efficiency with large numbers of printers.
512 result
= get_a_printer_search( NULL
, &printer
, 2, sname
);
513 if ( !W_ERROR_IS_OK(result
) ) {
514 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
515 sname
, win_errstr(result
)));
519 /* printername is always returned as \\server\printername */
520 if ( !(printername
= strchr_m(&printer
->info_2
->printername
[2], '\\')) ) {
521 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
522 printer
->info_2
->printername
));
523 free_a_printer( &printer
, 2);
529 if ( strequal(printername
, aprinter
) ) {
530 free_a_printer( &printer
, 2);
535 DEBUGADD(10, ("printername: %s\n", printername
));
537 free_a_printer( &printer
, 2);
540 free_a_printer( &printer
, 2);
543 DEBUGADD(4,("Printer not found\n"));
547 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
549 fstrcpy(Printer
->sharename
, sname
);
554 /****************************************************************************
555 Find first available printer slot. creates a printer handle for you.
556 ****************************************************************************/
558 static bool open_printer_hnd(pipes_struct
*p
, struct policy_handle
*hnd
,
559 const char *name
, uint32_t access_granted
)
561 Printer_entry
*new_printer
;
563 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
565 new_printer
= TALLOC_ZERO_P(NULL
, Printer_entry
);
566 if (new_printer
== NULL
) {
569 talloc_set_destructor(new_printer
, printer_entry_destructor
);
571 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
572 TALLOC_FREE(new_printer
);
576 /* Add to the internal list. */
577 DLIST_ADD(printers_list
, new_printer
);
579 new_printer
->notify
.option
=NULL
;
581 if (!set_printer_hnd_printertype(new_printer
, name
)) {
582 close_printer_handle(p
, hnd
);
586 if (!set_printer_hnd_name(new_printer
, name
)) {
587 close_printer_handle(p
, hnd
);
591 new_printer
->access_granted
= access_granted
;
593 DEBUG(5, ("%d printer handles active\n",
594 (int)num_pipe_handles(p
->pipe_handles
)));
599 /***************************************************************************
600 check to see if the client motify handle is monitoring the notification
601 given by (notify_type, notify_field).
602 **************************************************************************/
604 static bool is_monitoring_event_flags(uint32_t flags
, uint16_t notify_type
,
605 uint16_t notify_field
)
610 static bool is_monitoring_event(Printer_entry
*p
, uint16_t notify_type
,
611 uint16_t notify_field
)
613 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
617 * Flags should always be zero when the change notify
618 * is registered by the client's spooler. A user Win32 app
619 * might use the flags though instead of the NOTIFY_OPTION_INFO
628 return is_monitoring_event_flags(
629 p
->notify
.flags
, notify_type
, notify_field
);
631 for (i
= 0; i
< option
->count
; i
++) {
633 /* Check match for notify_type */
635 if (option
->types
[i
].type
!= notify_type
)
638 /* Check match for field */
640 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
641 if (option
->types
[i
].fields
[j
].field
== notify_field
) {
647 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
648 p
->servername
, p
->sharename
, notify_type
, notify_field
));
653 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
654 _data->data.integer[0] = _integer; \
655 _data->data.integer[1] = 0;
658 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
659 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
660 if (!_data->data.string.string) {\
661 _data->data.string.size = 0; \
663 _data->data.string.size = strlen_m_term(_p) * 2;
665 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
666 _data->data.devmode.devmode = _devmode;
668 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
669 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
670 if (!_data->data.sd.sd) { \
671 _data->data.sd.sd_size = 0; \
673 _data->data.sd.sd_size = _size;
675 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
680 struct spoolss_Time st
;
684 if (!init_systemtime(&st
, t
)) {
688 p
= talloc_array(mem_ctx
, char, len
);
694 * Systemtime must be linearized as a set of UINT16's.
695 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
698 SSVAL(p
, 0, st
.year
);
699 SSVAL(p
, 2, st
.month
);
700 SSVAL(p
, 4, st
.day_of_week
);
702 SSVAL(p
, 8, st
.hour
);
703 SSVAL(p
, 10, st
.minute
);
704 SSVAL(p
, 12, st
.second
);
705 SSVAL(p
, 14, st
.millisecond
);
711 /* Convert a notification message to a struct spoolss_Notify */
713 static void notify_one_value(struct spoolss_notify_msg
*msg
,
714 struct spoolss_Notify
*data
,
717 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
720 static void notify_string(struct spoolss_notify_msg
*msg
,
721 struct spoolss_Notify
*data
,
724 /* The length of the message includes the trailing \0 */
726 data
->data
.string
.size
= msg
->len
* 2;
727 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
728 if (!data
->data
.string
.string
) {
729 data
->data
.string
.size
= 0;
734 static void notify_system_time(struct spoolss_notify_msg
*msg
,
735 struct spoolss_Notify
*data
,
738 data
->data
.string
.string
= NULL
;
739 data
->data
.string
.size
= 0;
741 if (msg
->len
!= sizeof(time_t)) {
742 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
747 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
748 &data
->data
.string
.string
,
749 &data
->data
.string
.size
);
752 struct notify2_message_table
{
754 void (*fn
)(struct spoolss_notify_msg
*msg
,
755 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
758 static struct notify2_message_table printer_notify_table
[] = {
759 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string
},
760 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string
},
761 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string
},
762 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string
},
763 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string
},
764 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string
},
765 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string
},
766 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL
},
767 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string
},
768 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string
},
769 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL
},
770 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string
},
771 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
772 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value
},
773 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value
},
774 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL
},
775 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL
},
776 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL
},
777 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value
},
780 static struct notify2_message_table job_notify_table
[] = {
781 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL
},
782 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL
},
783 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL
},
784 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string
},
785 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL
},
786 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL
},
787 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL
},
788 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL
},
789 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL
},
790 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL
},
791 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value
},
792 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL
},
793 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
794 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string
},
795 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL
},
796 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL
},
797 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time
},
798 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL
},
799 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL
},
800 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL
},
801 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value
},
802 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL
},
803 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value
},
804 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL
},
808 /***********************************************************************
809 Allocate talloc context for container object
810 **********************************************************************/
812 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
817 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
822 /***********************************************************************
823 release all allocated memory and zero out structure
824 **********************************************************************/
826 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
832 talloc_destroy(ctr
->ctx
);
839 /***********************************************************************
840 **********************************************************************/
842 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
850 /***********************************************************************
851 **********************************************************************/
853 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
855 if ( !ctr
|| !ctr
->msg_groups
)
858 if ( idx
>= ctr
->num_groups
)
861 return &ctr
->msg_groups
[idx
];
865 /***********************************************************************
866 How many groups of change messages do we have ?
867 **********************************************************************/
869 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
874 return ctr
->num_groups
;
877 /***********************************************************************
878 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
879 **********************************************************************/
881 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
883 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
884 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
885 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
891 /* loop over all groups looking for a matching printer name */
893 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
894 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
898 /* add a new group? */
900 if ( i
== ctr
->num_groups
) {
903 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
904 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
907 ctr
->msg_groups
= groups
;
909 /* clear the new entry and set the printer name */
911 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
912 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
915 /* add the change messages; 'i' is the correct index now regardless */
917 msg_grp
= &ctr
->msg_groups
[i
];
921 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
922 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
925 msg_grp
->msgs
= msg_list
;
927 new_slot
= msg_grp
->num_msgs
-1;
928 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
930 /* need to allocate own copy of data */
933 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
934 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
936 return ctr
->num_groups
;
939 void construct_info_data(struct spoolss_Notify
*info_data
,
940 enum spoolss_NotifyType type
,
944 /***********************************************************************
945 Send a change notication message on all handles which have a call
947 **********************************************************************/
949 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
952 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
953 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
954 SPOOLSS_NOTIFY_MSG
*messages
;
955 int sending_msg_count
;
958 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
962 messages
= msg_group
->msgs
;
965 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
969 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
971 /* loop over all printers */
973 for (p
= printers_list
; p
; p
= p
->next
) {
974 struct spoolss_Notify
*notifies
;
979 /* Is there notification on this handle? */
981 if ( !p
->notify
.client_connected
)
984 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p
->servername
, p
->sharename
));
986 /* For this printer? Print servers always receive
989 if ( ( p
->printer_type
== SPLHND_PRINTER
) &&
990 ( !strequal(msg_group
->printername
, p
->sharename
) ) )
993 DEBUG(10,("Our printer\n"));
995 /* allocate the max entries possible */
997 notifies
= TALLOC_ZERO_ARRAY(mem_ctx
, struct spoolss_Notify
, msg_group
->num_msgs
);
1002 /* build the array of change notifications */
1004 sending_msg_count
= 0;
1006 for ( i
=0; i
<msg_group
->num_msgs
; i
++ ) {
1007 SPOOLSS_NOTIFY_MSG
*msg
= &messages
[i
];
1009 /* Are we monitoring this event? */
1011 if (!is_monitoring_event(p
, msg
->type
, msg
->field
))
1014 sending_msg_count
++;
1017 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1018 msg
->type
, msg
->field
, p
->sharename
));
1021 * if the is a printer notification handle and not a job notification
1022 * type, then set the id to 0. Other wise just use what was specified
1025 * When registering change notification on a print server handle
1026 * we always need to send back the id (snum) matching the printer
1027 * for which the change took place. For change notify registered
1028 * on a printer handle, this does not matter and the id should be 0.
1033 if ( ( p
->printer_type
== SPLHND_PRINTER
) && ( msg
->type
== PRINTER_NOTIFY_TYPE
) )
1039 /* Convert unix jobid to smb jobid */
1041 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1042 id
= sysjob_to_jobid(msg
->id
);
1045 DEBUG(3, ("no such unix jobid %d\n", msg
->id
));
1050 construct_info_data( ¬ifies
[count
], msg
->type
, msg
->field
, id
);
1053 case PRINTER_NOTIFY_TYPE
:
1054 if ( printer_notify_table
[msg
->field
].fn
)
1055 printer_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1058 case JOB_NOTIFY_TYPE
:
1059 if ( job_notify_table
[msg
->field
].fn
)
1060 job_notify_table
[msg
->field
].fn(msg
, ¬ifies
[count
], mem_ctx
);
1064 DEBUG(5, ("Unknown notification type %d\n", msg
->type
));
1071 if ( sending_msg_count
) {
1074 union spoolss_ReplyPrinterInfo info
;
1075 struct spoolss_NotifyInfo info0
;
1076 uint32_t reply_result
;
1078 info0
.version
= 0x2;
1079 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1080 info0
.count
= count
;
1081 info0
.notifies
= notifies
;
1083 info
.info0
= &info0
;
1085 status
= rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe
, mem_ctx
,
1086 &p
->notify
.client_hnd
,
1087 p
->notify
.change
, /* color */
1090 0, /* reply_type, must be 0 */
1093 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(werr
)) {
1094 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1095 notify_cli_pipe
->srv_name_slash
,
1098 switch (reply_result
) {
1101 case PRINTER_NOTIFY_INFO_DISCARDED
:
1102 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1103 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1112 DEBUG(8,("send_notify2_changes: Exit...\n"));
1116 /***********************************************************************
1117 **********************************************************************/
1119 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1122 uint32_t tv_sec
, tv_usec
;
1125 /* Unpack message */
1127 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "f",
1130 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "ddddddd",
1132 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1135 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "dd",
1136 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1138 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "B",
1139 &msg
->len
, &msg
->notify
.data
);
1141 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1142 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1144 tv
->tv_sec
= tv_sec
;
1145 tv
->tv_usec
= tv_usec
;
1148 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1149 msg
->notify
.value
[1]));
1151 dump_data(3, (uint8_t *)msg
->notify
.data
, msg
->len
);
1156 /********************************************************************
1157 Receive a notify2 message list
1158 ********************************************************************/
1160 static void receive_notify2_message_list(struct messaging_context
*msg
,
1163 struct server_id server_id
,
1166 size_t msg_count
, i
;
1167 char *buf
= (char *)data
->data
;
1170 SPOOLSS_NOTIFY_MSG notify
;
1171 SPOOLSS_NOTIFY_MSG_CTR messages
;
1174 if (data
->length
< 4) {
1175 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1179 msg_count
= IVAL(buf
, 0);
1182 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1184 if (msg_count
== 0) {
1185 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1189 /* initialize the container */
1191 ZERO_STRUCT( messages
);
1192 notify_msg_ctr_init( &messages
);
1195 * build message groups for each printer identified
1196 * in a change_notify msg. Remember that a PCN message
1197 * includes the handle returned for the srv_spoolss_replyopenprinter()
1198 * call. Therefore messages are grouped according to printer handle.
1201 for ( i
=0; i
<msg_count
; i
++ ) {
1202 struct timeval msg_tv
;
1204 if (msg_ptr
+ 4 - buf
> data
->length
) {
1205 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1209 msg_len
= IVAL(msg_ptr
,0);
1212 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1213 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1217 /* unpack messages */
1219 ZERO_STRUCT( notify
);
1220 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1223 /* add to correct list in container */
1225 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1227 /* free memory that might have been allocated by notify2_unpack_msg() */
1229 if ( notify
.len
!= 0 )
1230 SAFE_FREE( notify
.notify
.data
);
1233 /* process each group of messages */
1235 num_groups
= notify_msg_ctr_numgroups( &messages
);
1236 for ( i
=0; i
<num_groups
; i
++ )
1237 send_notify2_changes( &messages
, i
);
1242 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1243 (uint32_t)msg_count
));
1245 notify_msg_ctr_destroy( &messages
);
1250 /********************************************************************
1251 Send a message to ourself about new driver being installed
1252 so we can upgrade the information for each printer bound to this
1254 ********************************************************************/
1256 static bool srv_spoolss_drv_upgrade_printer(const char *drivername
)
1258 int len
= strlen(drivername
);
1263 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1266 messaging_send_buf(smbd_messaging_context(), procid_self(),
1267 MSG_PRINTER_DRVUPGRADE
,
1268 (uint8_t *)drivername
, len
+1);
1273 /**********************************************************************
1274 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1275 over all printers, upgrading ones as necessary
1276 **********************************************************************/
1278 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1281 struct server_id server_id
,
1286 int n_services
= lp_numservices();
1289 len
= MIN(data
->length
,sizeof(drivername
)-1);
1290 strncpy(drivername
, (const char *)data
->data
, len
);
1292 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername
));
1294 /* Iterate the printer list */
1296 for (snum
=0; snum
<n_services
; snum
++)
1298 if (lp_snum_ok(snum
) && lp_print_ok(snum
) )
1301 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
1303 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
1304 if (!W_ERROR_IS_OK(result
))
1307 if (printer
&& printer
->info_2
&& !strcmp(drivername
, printer
->info_2
->drivername
))
1309 DEBUG(6,("Updating printer [%s]\n", printer
->info_2
->printername
));
1311 /* all we care about currently is the change_id */
1313 result
= mod_a_printer(printer
, 2);
1314 if (!W_ERROR_IS_OK(result
)) {
1315 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1316 win_errstr(result
)));
1320 free_a_printer(&printer
, 2);
1327 /********************************************************************
1328 Update the cache for all printq's with a registered client
1330 ********************************************************************/
1332 void update_monitored_printq_cache( void )
1334 Printer_entry
*printer
= printers_list
;
1337 /* loop through all printers and update the cache where
1338 client_connected == true */
1341 if ( (printer
->printer_type
== SPLHND_PRINTER
)
1342 && printer
->notify
.client_connected
)
1344 snum
= print_queue_snum(printer
->sharename
);
1345 print_queue_status( snum
, NULL
, NULL
);
1348 printer
= printer
->next
;
1354 /****************************************************************
1355 _spoolss_OpenPrinter
1356 ****************************************************************/
1358 WERROR
_spoolss_OpenPrinter(pipes_struct
*p
,
1359 struct spoolss_OpenPrinter
*r
)
1361 struct spoolss_OpenPrinterEx e
;
1364 ZERO_STRUCT(e
.in
.userlevel
);
1366 e
.in
.printername
= r
->in
.printername
;
1367 e
.in
.datatype
= r
->in
.datatype
;
1368 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1369 e
.in
.access_mask
= r
->in
.access_mask
;
1372 e
.out
.handle
= r
->out
.handle
;
1374 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1376 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1377 /* OpenPrinterEx returns this for a bad
1378 * printer name. We must return WERR_INVALID_PRINTER_NAME
1381 werr
= WERR_INVALID_PRINTER_NAME
;
1387 /********************************************************************
1388 ********************************************************************/
1390 bool convert_devicemode(const char *printername
,
1391 const struct spoolss_DeviceMode
*devmode
,
1392 NT_DEVICEMODE
**pp_nt_devmode
)
1394 NT_DEVICEMODE
*nt_devmode
= *pp_nt_devmode
;
1397 * Ensure nt_devmode is a valid pointer
1398 * as we will be overwriting it.
1401 if (nt_devmode
== NULL
) {
1402 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1403 if ((nt_devmode
= construct_nt_devicemode(printername
)) == NULL
)
1407 fstrcpy(nt_devmode
->devicename
, devmode
->devicename
);
1408 fstrcpy(nt_devmode
->formname
, devmode
->formname
);
1410 nt_devmode
->devicename
[31] = '\0';
1411 nt_devmode
->formname
[31] = '\0';
1413 nt_devmode
->specversion
= devmode
->specversion
;
1414 nt_devmode
->driverversion
= devmode
->driverversion
;
1415 nt_devmode
->size
= devmode
->size
;
1416 nt_devmode
->fields
= devmode
->fields
;
1417 nt_devmode
->orientation
= devmode
->orientation
;
1418 nt_devmode
->papersize
= devmode
->papersize
;
1419 nt_devmode
->paperlength
= devmode
->paperlength
;
1420 nt_devmode
->paperwidth
= devmode
->paperwidth
;
1421 nt_devmode
->scale
= devmode
->scale
;
1422 nt_devmode
->copies
= devmode
->copies
;
1423 nt_devmode
->defaultsource
= devmode
->defaultsource
;
1424 nt_devmode
->printquality
= devmode
->printquality
;
1425 nt_devmode
->color
= devmode
->color
;
1426 nt_devmode
->duplex
= devmode
->duplex
;
1427 nt_devmode
->yresolution
= devmode
->yresolution
;
1428 nt_devmode
->ttoption
= devmode
->ttoption
;
1429 nt_devmode
->collate
= devmode
->collate
;
1431 nt_devmode
->logpixels
= devmode
->logpixels
;
1432 nt_devmode
->bitsperpel
= devmode
->bitsperpel
;
1433 nt_devmode
->pelswidth
= devmode
->pelswidth
;
1434 nt_devmode
->pelsheight
= devmode
->pelsheight
;
1435 nt_devmode
->displayflags
= devmode
->displayflags
;
1436 nt_devmode
->displayfrequency
= devmode
->displayfrequency
;
1437 nt_devmode
->icmmethod
= devmode
->icmmethod
;
1438 nt_devmode
->icmintent
= devmode
->icmintent
;
1439 nt_devmode
->mediatype
= devmode
->mediatype
;
1440 nt_devmode
->dithertype
= devmode
->dithertype
;
1441 nt_devmode
->reserved1
= devmode
->reserved1
;
1442 nt_devmode
->reserved2
= devmode
->reserved2
;
1443 nt_devmode
->panningwidth
= devmode
->panningwidth
;
1444 nt_devmode
->panningheight
= devmode
->panningheight
;
1447 * Only change private and driverextra if the incoming devmode
1448 * has a new one. JRA.
1451 if ((devmode
->__driverextra_length
!= 0) && (devmode
->driverextra_data
.data
!= NULL
)) {
1452 SAFE_FREE(nt_devmode
->nt_dev_private
);
1453 nt_devmode
->driverextra
= devmode
->__driverextra_length
;
1454 if((nt_devmode
->nt_dev_private
= SMB_MALLOC_ARRAY(uint8_t, nt_devmode
->driverextra
)) == NULL
)
1456 memcpy(nt_devmode
->nt_dev_private
, devmode
->driverextra_data
.data
, nt_devmode
->driverextra
);
1459 *pp_nt_devmode
= nt_devmode
;
1464 /****************************************************************
1465 _spoolss_OpenPrinterEx
1466 ****************************************************************/
1468 WERROR
_spoolss_OpenPrinterEx(pipes_struct
*p
,
1469 struct spoolss_OpenPrinterEx
*r
)
1472 Printer_entry
*Printer
=NULL
;
1474 if (!r
->in
.printername
) {
1475 return WERR_INVALID_PARAM
;
1478 /* some sanity check because you can open a printer or a print server */
1479 /* aka: \\server\printer or \\server */
1481 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1483 if (!open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0)) {
1484 ZERO_STRUCTP(r
->out
.handle
);
1485 return WERR_INVALID_PARAM
;
1488 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1490 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1491 "handle we created for printer %s\n", r
->in
.printername
));
1492 close_printer_handle(p
, r
->out
.handle
);
1493 ZERO_STRUCTP(r
->out
.handle
);
1494 return WERR_INVALID_PARAM
;
1498 * First case: the user is opening the print server:
1500 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1501 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1503 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1504 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1505 * or if the user is listed in the smb.conf printer admin parameter.
1507 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1508 * client view printer folder, but does not show the MSAPW.
1510 * Note: this test needs code to check access rights here too. Jeremy
1511 * could you look at this?
1513 * Second case: the user is opening a printer:
1514 * NT doesn't let us connect to a printer if the connecting user
1515 * doesn't have print permission.
1517 * Third case: user is opening a Port Monitor
1518 * access checks same as opening a handle to the print server.
1521 switch (Printer
->printer_type
)
1524 case SPLHND_PORTMON_TCP
:
1525 case SPLHND_PORTMON_LOCAL
:
1526 /* Printserver handles use global struct... */
1530 /* Map standard access rights to object specific access rights */
1532 se_map_standard(&r
->in
.access_mask
,
1533 &printserver_std_mapping
);
1535 /* Deny any object specific bits that don't apply to print
1536 servers (i.e printer and job specific bits) */
1538 r
->in
.access_mask
&= SPECIFIC_RIGHTS_MASK
;
1540 if (r
->in
.access_mask
&
1541 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1542 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1543 close_printer_handle(p
, r
->out
.handle
);
1544 ZERO_STRUCTP(r
->out
.handle
);
1545 return WERR_ACCESS_DENIED
;
1548 /* Allow admin access */
1550 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1552 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1554 if (!lp_ms_add_printer_wizard()) {
1555 close_printer_handle(p
, r
->out
.handle
);
1556 ZERO_STRUCTP(r
->out
.handle
);
1557 return WERR_ACCESS_DENIED
;
1560 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1561 and not a printer admin, then fail */
1563 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
1564 !user_has_privileges(p
->server_info
->ptok
,
1566 !token_contains_name_in_list(
1567 uidtoname(p
->server_info
->utok
.uid
),
1569 p
->server_info
->ptok
,
1570 lp_printer_admin(snum
))) {
1571 close_printer_handle(p
, r
->out
.handle
);
1572 ZERO_STRUCTP(r
->out
.handle
);
1573 return WERR_ACCESS_DENIED
;
1576 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1580 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1583 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1584 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1586 /* We fall through to return WERR_OK */
1589 case SPLHND_PRINTER
:
1590 /* NT doesn't let us connect to a printer if the connecting user
1591 doesn't have print permission. */
1593 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1594 close_printer_handle(p
, r
->out
.handle
);
1595 ZERO_STRUCTP(r
->out
.handle
);
1599 if (r
->in
.access_mask
== SEC_FLAG_MAXIMUM_ALLOWED
) {
1600 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1603 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1605 /* map an empty access mask to the minimum access mask */
1606 if (r
->in
.access_mask
== 0x0)
1607 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1610 * If we are not serving the printer driver for this printer,
1611 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1612 * will keep NT clients happy --jerry
1615 if (lp_use_client_driver(snum
)
1616 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1618 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1621 /* check smb.conf parameters and the the sec_desc */
1623 if ( !check_access(get_client_fd(), lp_hostsallow(snum
), lp_hostsdeny(snum
)) ) {
1624 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1625 ZERO_STRUCTP(r
->out
.handle
);
1626 return WERR_ACCESS_DENIED
;
1629 if (!user_ok_token(uidtoname(p
->server_info
->utok
.uid
), NULL
,
1630 p
->server_info
->ptok
, snum
) ||
1631 !print_access_check(p
->server_info
, snum
,
1632 r
->in
.access_mask
)) {
1633 DEBUG(3, ("access DENIED for printer open\n"));
1634 close_printer_handle(p
, r
->out
.handle
);
1635 ZERO_STRUCTP(r
->out
.handle
);
1636 return WERR_ACCESS_DENIED
;
1639 if ((r
->in
.access_mask
& SPECIFIC_RIGHTS_MASK
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1640 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1641 close_printer_handle(p
, r
->out
.handle
);
1642 ZERO_STRUCTP(r
->out
.handle
);
1643 return WERR_ACCESS_DENIED
;
1646 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1647 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1649 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1651 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1652 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1657 /* sanity check to prevent programmer error */
1658 ZERO_STRUCTP(r
->out
.handle
);
1662 Printer
->access_granted
= r
->in
.access_mask
;
1665 * If the client sent a devmode in the OpenPrinter() call, then
1666 * save it here in case we get a job submission on this handle
1669 if ((Printer
->printer_type
!= SPLHND_SERVER
) &&
1670 r
->in
.devmode_ctr
.devmode
) {
1671 convert_devicemode(Printer
->sharename
,
1672 r
->in
.devmode_ctr
.devmode
,
1673 &Printer
->nt_devmode
);
1676 #if 0 /* JERRY -- I'm doubtful this is really effective */
1677 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1678 optimization in Windows 2000 clients --jerry */
1680 if ( (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1681 && (RA_WIN2K
== get_remote_arch()) )
1683 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1684 sys_usleep( 500000 );
1691 /****************************************************************************
1692 ****************************************************************************/
1694 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2
*r
,
1695 NT_PRINTER_INFO_LEVEL_2
*d
)
1697 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1703 d
->attributes
= r
->attributes
;
1704 d
->priority
= r
->priority
;
1705 d
->default_priority
= r
->defaultpriority
;
1706 d
->starttime
= r
->starttime
;
1707 d
->untiltime
= r
->untiltime
;
1708 d
->status
= r
->status
;
1709 d
->cjobs
= r
->cjobs
;
1711 fstrcpy(d
->servername
, r
->servername
);
1712 fstrcpy(d
->printername
, r
->printername
);
1713 fstrcpy(d
->sharename
, r
->sharename
);
1714 fstrcpy(d
->portname
, r
->portname
);
1715 fstrcpy(d
->drivername
, r
->drivername
);
1716 slprintf(d
->comment
, sizeof(d
->comment
)-1, "%s", r
->comment
);
1717 fstrcpy(d
->location
, r
->location
);
1718 fstrcpy(d
->sepfile
, r
->sepfile
);
1719 fstrcpy(d
->printprocessor
, r
->printprocessor
);
1720 fstrcpy(d
->datatype
, r
->datatype
);
1721 fstrcpy(d
->parameters
, r
->parameters
);
1726 /****************************************************************************
1727 ****************************************************************************/
1729 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr
*info_ctr
,
1730 NT_PRINTER_INFO_LEVEL
*printer
)
1734 switch (info_ctr
->level
) {
1736 /* allocate memory if needed. Messy because
1737 convert_printer_info is used to update an existing
1738 printer or build a new one */
1740 if (!printer
->info_2
) {
1741 printer
->info_2
= TALLOC_ZERO_P(printer
, NT_PRINTER_INFO_LEVEL_2
);
1742 if (!printer
->info_2
) {
1743 DEBUG(0,("convert_printer_info: "
1744 "talloc() failed!\n"));
1749 ret
= printer_info2_to_nt_printer_info2(info_ctr
->info
.info2
,
1751 printer
->info_2
->setuptime
= time(NULL
);
1758 /****************************************************************
1759 _spoolss_ClosePrinter
1760 ****************************************************************/
1762 WERROR
_spoolss_ClosePrinter(pipes_struct
*p
,
1763 struct spoolss_ClosePrinter
*r
)
1765 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1767 if (Printer
&& Printer
->document_started
) {
1768 struct spoolss_EndDocPrinter e
;
1770 e
.in
.handle
= r
->in
.handle
;
1772 _spoolss_EndDocPrinter(p
, &e
);
1775 if (!close_printer_handle(p
, r
->in
.handle
))
1778 /* clear the returned printer handle. Observed behavior
1779 from Win2k server. Don't think this really matters.
1780 Previous code just copied the value of the closed
1783 ZERO_STRUCTP(r
->out
.handle
);
1788 /****************************************************************
1789 _spoolss_DeletePrinter
1790 ****************************************************************/
1792 WERROR
_spoolss_DeletePrinter(pipes_struct
*p
,
1793 struct spoolss_DeletePrinter
*r
)
1795 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1798 if (Printer
&& Printer
->document_started
) {
1799 struct spoolss_EndDocPrinter e
;
1801 e
.in
.handle
= r
->in
.handle
;
1803 _spoolss_EndDocPrinter(p
, &e
);
1806 result
= delete_printer_handle(p
, r
->in
.handle
);
1808 update_c_setprinter(false);
1813 /*******************************************************************
1814 * static function to lookup the version id corresponding to an
1815 * long architecture string
1816 ******************************************************************/
1818 static const struct print_architecture_table_node archi_table
[]= {
1820 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
1821 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
1822 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
1823 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
1824 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
1825 {"Windows IA64", SPL_ARCH_IA64
, 3 },
1826 {"Windows x64", SPL_ARCH_X64
, 3 },
1830 static int get_version_id(const char *arch
)
1834 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
1836 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
1837 return (archi_table
[i
].version
);
1843 /****************************************************************
1844 _spoolss_DeletePrinterDriver
1845 ****************************************************************/
1847 WERROR
_spoolss_DeletePrinterDriver(pipes_struct
*p
,
1848 struct spoolss_DeletePrinterDriver
*r
)
1851 struct spoolss_DriverInfo8
*info
= NULL
;
1852 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
1855 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1856 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1858 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1859 and not a printer admin, then fail */
1861 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
1862 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
1863 && !token_contains_name_in_list(
1864 uidtoname(p
->server_info
->utok
.uid
), NULL
,
1865 NULL
, p
->server_info
->ptok
,
1866 lp_printer_admin(-1)) )
1868 return WERR_ACCESS_DENIED
;
1871 /* check that we have a valid driver name first */
1873 if ((version
= get_version_id(r
->in
.architecture
)) == -1)
1874 return WERR_INVALID_ENVIRONMENT
;
1876 if (!W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
, &info
, r
->in
.driver
,
1880 /* try for Win2k driver if "Windows NT x86" */
1882 if ( version
== 2 ) {
1884 if (!W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
,
1889 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1893 /* otherwise it was a failure */
1895 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
1901 if (printer_driver_in_use(info
)) {
1902 status
= WERR_PRINTER_DRIVER_IN_USE
;
1908 if (W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
,
1911 r
->in
.architecture
, 3)))
1913 /* if we get to here, we now have 2 driver info structures to remove */
1914 /* remove the Win2k driver first*/
1916 status_win2k
= delete_printer_driver(
1917 p
, info_win2k
, 3, false);
1918 free_a_printer_driver(info_win2k
);
1920 /* this should not have failed---if it did, report to client */
1921 if ( !W_ERROR_IS_OK(status_win2k
) )
1923 status
= status_win2k
;
1929 status
= delete_printer_driver(p
, info
, version
, false);
1931 /* if at least one of the deletes succeeded return OK */
1933 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
1937 free_a_printer_driver(info
);
1942 /****************************************************************
1943 _spoolss_DeletePrinterDriverEx
1944 ****************************************************************/
1946 WERROR
_spoolss_DeletePrinterDriverEx(pipes_struct
*p
,
1947 struct spoolss_DeletePrinterDriverEx
*r
)
1949 struct spoolss_DriverInfo8
*info
= NULL
;
1950 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
1954 WERROR status_win2k
= WERR_ACCESS_DENIED
;
1955 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
1957 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1958 and not a printer admin, then fail */
1960 if ( (p
->server_info
->utok
.uid
!= sec_initial_uid())
1961 && !user_has_privileges(p
->server_info
->ptok
, &se_printop
)
1962 && !token_contains_name_in_list(
1963 uidtoname(p
->server_info
->utok
.uid
), NULL
, NULL
,
1964 p
->server_info
->ptok
, lp_printer_admin(-1)) )
1966 return WERR_ACCESS_DENIED
;
1969 /* check that we have a valid driver name first */
1970 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
1971 /* this is what NT returns */
1972 return WERR_INVALID_ENVIRONMENT
;
1975 if (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
1976 version
= r
->in
.version
;
1978 status
= get_a_printer_driver(p
->mem_ctx
, &info
, r
->in
.driver
,
1979 r
->in
.architecture
, version
);
1981 if ( !W_ERROR_IS_OK(status
) )
1984 * if the client asked for a specific version,
1985 * or this is something other than Windows NT x86,
1989 if ( (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
1992 /* try for Win2k driver if "Windows NT x86" */
1995 if (!W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
, &info
, r
->in
.driver
,
1998 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2003 if (printer_driver_in_use(info
)) {
2004 status
= WERR_PRINTER_DRIVER_IN_USE
;
2009 * we have a couple of cases to consider.
2010 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2011 * then the delete should fail if **any** files overlap with
2013 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2014 * non-overlapping files
2015 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2016 * is set, the do not delete any files
2017 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2020 delete_files
= r
->in
.delete_flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2022 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2024 if (delete_files
&& printer_driver_files_in_use(info
, info
) & (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
)) {
2025 /* no idea of the correct error here */
2026 status
= WERR_ACCESS_DENIED
;
2031 /* also check for W32X86/3 if necessary; maybe we already have? */
2033 if ( (version
== 2) && ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2034 if (W_ERROR_IS_OK(get_a_printer_driver(p
->mem_ctx
, &info_win2k
,
2036 r
->in
.architecture
, 3)))
2039 if (delete_files
&& printer_driver_files_in_use(info
, info_win2k
) & (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) ) {
2040 /* no idea of the correct error here */
2041 free_a_printer_driver(info_win2k
);
2042 status
= WERR_ACCESS_DENIED
;
2046 /* if we get to here, we now have 2 driver info structures to remove */
2047 /* remove the Win2k driver first*/
2049 status_win2k
= delete_printer_driver(
2050 p
, info_win2k
, 3, delete_files
);
2051 free_a_printer_driver(info_win2k
);
2053 /* this should not have failed---if it did, report to client */
2055 if ( !W_ERROR_IS_OK(status_win2k
) )
2060 status
= delete_printer_driver(p
, info
, version
, delete_files
);
2062 if ( W_ERROR_IS_OK(status
) || W_ERROR_IS_OK(status_win2k
) )
2065 free_a_printer_driver(info
);
2071 /****************************************************************************
2072 Internal routine for removing printerdata
2073 ***************************************************************************/
2075 static WERROR
delete_printer_dataex( NT_PRINTER_INFO_LEVEL
*printer
, const char *key
, const char *value
)
2077 return delete_printer_data( printer
->info_2
, key
, value
);
2080 /****************************************************************************
2081 Internal routine for storing printerdata
2082 ***************************************************************************/
2084 WERROR
set_printer_dataex(NT_PRINTER_INFO_LEVEL
*printer
,
2085 const char *key
, const char *value
,
2086 uint32_t type
, uint8_t *data
, int real_len
)
2088 /* the registry objects enforce uniqueness based on value name */
2090 return add_printer_data( printer
->info_2
, key
, value
, type
, data
, real_len
);
2093 /********************************************************************
2094 GetPrinterData on a printer server Handle.
2095 ********************************************************************/
2097 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2099 enum winreg_Type
*type
,
2100 union spoolss_PrinterData
*data
)
2102 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2104 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2110 if (!StrCaseCmp(value
, "BeepEnabled")) {
2116 if (!StrCaseCmp(value
, "EventLog")) {
2118 /* formally was 0x1b */
2123 if (!StrCaseCmp(value
, "NetPopup")) {
2129 if (!StrCaseCmp(value
, "MajorVersion")) {
2132 /* Windows NT 4.0 seems to not allow uploading of drivers
2133 to a server that reports 0x3 as the MajorVersion.
2134 need to investigate more how Win2k gets around this .
2137 if (RA_WINNT
== get_remote_arch()) {
2146 if (!StrCaseCmp(value
, "MinorVersion")) {
2153 * uint32_t size = 0x114
2154 * uint32_t major = 5
2155 * uint32_t minor = [0|1]
2156 * uint32_t build = [2195|2600]
2157 * extra unicode string = e.g. "Service Pack 3"
2159 if (!StrCaseCmp(value
, "OSVersion")) {
2161 enum ndr_err_code ndr_err
;
2162 struct spoolss_OSVersion os
;
2164 os
.major
= 5; /* Windows 2000 == 5.0 */
2166 os
.build
= 2195; /* build */
2167 os
.extra_string
= ""; /* leave extra string empty */
2169 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &os
,
2170 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2171 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2172 return WERR_GENERAL_FAILURE
;
2176 data
->binary
= blob
;
2182 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2185 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2186 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2191 if (!StrCaseCmp(value
, "Architecture")) {
2193 data
->string
= talloc_strdup(mem_ctx
,
2194 lp_parm_const_string(GLOBAL_SECTION_SNUM
, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86
));
2195 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2200 if (!StrCaseCmp(value
, "DsPresent")) {
2203 /* only show the publish check box if we are a
2204 member of a AD domain */
2206 if (lp_security() == SEC_ADS
) {
2214 if (!StrCaseCmp(value
, "DNSMachineName")) {
2215 const char *hostname
= get_mydnsfullname();
2218 return WERR_BADFILE
;
2222 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2223 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2230 return WERR_INVALID_PARAM
;
2233 /****************************************************************
2234 _spoolss_GetPrinterData
2235 ****************************************************************/
2237 WERROR
_spoolss_GetPrinterData(pipes_struct
*p
,
2238 struct spoolss_GetPrinterData
*r
)
2240 struct spoolss_GetPrinterDataEx r2
;
2242 r2
.in
.handle
= r
->in
.handle
;
2243 r2
.in
.key_name
= "PrinterDriverData";
2244 r2
.in
.value_name
= r
->in
.value_name
;
2245 r2
.in
.offered
= r
->in
.offered
;
2246 r2
.out
.type
= r
->out
.type
;
2247 r2
.out
.data
= r
->out
.data
;
2248 r2
.out
.needed
= r
->out
.needed
;
2250 return _spoolss_GetPrinterDataEx(p
, &r2
);
2253 /*********************************************************
2254 Connect to the client machine.
2255 **********************************************************/
2257 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2258 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2261 struct cli_state
*the_cli
;
2262 struct sockaddr_storage rm_addr
;
2263 char addr
[INET6_ADDRSTRLEN
];
2265 if ( is_zero_addr((struct sockaddr
*)client_ss
) ) {
2266 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2268 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20, false) ) {
2269 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2272 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2274 rm_addr
= *client_ss
;
2275 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2276 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2280 if (ismyaddr((struct sockaddr
*)&rm_addr
)) {
2281 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2286 /* setup the connection */
2287 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2288 &rm_addr
, 0, "IPC$", "IPC",
2292 0, lp_client_signing(), NULL
);
2294 if ( !NT_STATUS_IS_OK( ret
) ) {
2295 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2300 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2301 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2302 cli_shutdown(the_cli
);
2307 * Ok - we have an anonymous connection to the IPC$ share.
2308 * Now start the NT Domain stuff :-).
2311 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2312 if (!NT_STATUS_IS_OK(ret
)) {
2313 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2314 remote_machine
, nt_errstr(ret
)));
2315 cli_shutdown(the_cli
);
2322 /***************************************************************************
2323 Connect to the client.
2324 ****************************************************************************/
2326 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2327 uint32_t localprinter
, uint32_t type
,
2328 struct policy_handle
*handle
,
2329 struct sockaddr_storage
*client_ss
)
2335 * If it's the first connection, contact the client
2336 * and connect to the IPC$ share anonymously
2338 if (smb_connections
==0) {
2339 fstring unix_printer
;
2341 fstrcpy(unix_printer
, printer
+2); /* the +2 is to strip the leading 2 backslashs */
2343 if ( !spoolss_connect_to_client( ¬ify_cli_pipe
, client_ss
, unix_printer
))
2346 messaging_register(smbd_messaging_context(), NULL
,
2347 MSG_PRINTER_NOTIFY2
,
2348 receive_notify2_message_list
);
2349 /* Tell the connections db we're now interested in printer
2350 * notify messages. */
2351 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY
);
2355 * Tell the specific printing tdb we want messages for this printer
2356 * by registering our PID.
2359 if (!print_notify_register_pid(snum
))
2360 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer
));
2364 status
= rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe
, talloc_tos(),
2372 if (!NT_STATUS_IS_OK(status
) || !W_ERROR_IS_OK(result
))
2373 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2374 win_errstr(result
)));
2376 return (W_ERROR_IS_OK(result
));
2379 /****************************************************************
2380 ****************************************************************/
2382 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2383 const struct spoolss_NotifyOption
*r
)
2385 struct spoolss_NotifyOption
*option
;
2392 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2399 if (!option
->count
) {
2403 option
->types
= talloc_zero_array(option
,
2404 struct spoolss_NotifyOptionType
, option
->count
);
2405 if (!option
->types
) {
2406 talloc_free(option
);
2410 for (i
=0; i
< option
->count
; i
++) {
2411 option
->types
[i
] = r
->types
[i
];
2413 if (option
->types
[i
].count
) {
2414 option
->types
[i
].fields
= talloc_zero_array(option
,
2415 union spoolss_Field
, option
->types
[i
].count
);
2416 if (!option
->types
[i
].fields
) {
2417 talloc_free(option
);
2420 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2421 option
->types
[i
].fields
[k
] =
2422 r
->types
[i
].fields
[k
];
2430 /****************************************************************
2431 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2433 * before replying OK: status=0 a rpc call is made to the workstation
2434 * asking ReplyOpenPrinter
2436 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2437 * called from api_spoolss_rffpcnex
2438 ****************************************************************/
2440 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct
*p
,
2441 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2444 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2445 struct sockaddr_storage client_ss
;
2447 /* store the notify value in the printer struct */
2449 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2452 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2453 "Invalid handle (%s:%u:%u).\n",
2454 OUR_HANDLE(r
->in
.handle
)));
2458 Printer
->notify
.flags
= r
->in
.flags
;
2459 Printer
->notify
.options
= r
->in
.options
;
2460 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2462 TALLOC_FREE(Printer
->notify
.option
);
2463 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2465 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2467 /* Connect to the client machine and send a ReplyOpenPrinter */
2469 if ( Printer
->printer_type
== SPLHND_SERVER
)
2471 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2472 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2475 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2476 "client_address is %s\n", p
->client_address
));
2478 if (!interpret_string_addr(&client_ss
, p
->client_address
,
2480 return WERR_SERVER_UNAVAILABLE
;
2483 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2484 Printer
->notify
.printerlocal
, 1,
2485 &Printer
->notify
.client_hnd
, &client_ss
))
2486 return WERR_SERVER_UNAVAILABLE
;
2488 Printer
->notify
.client_connected
= true;
2493 /*******************************************************************
2494 * fill a notify_info_data with the servername
2495 ********************************************************************/
2497 static void spoolss_notify_server_name(int snum
,
2498 struct spoolss_Notify
*data
,
2499 print_queue_struct
*queue
,
2500 NT_PRINTER_INFO_LEVEL
*printer
,
2501 TALLOC_CTX
*mem_ctx
)
2503 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->servername
);
2506 /*******************************************************************
2507 * fill a notify_info_data with the printername (not including the servername).
2508 ********************************************************************/
2510 static void spoolss_notify_printer_name(int snum
,
2511 struct spoolss_Notify
*data
,
2512 print_queue_struct
*queue
,
2513 NT_PRINTER_INFO_LEVEL
*printer
,
2514 TALLOC_CTX
*mem_ctx
)
2516 /* the notify name should not contain the \\server\ part */
2517 char *p
= strrchr(printer
->info_2
->printername
, '\\');
2520 p
= printer
->info_2
->printername
;
2525 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2528 /*******************************************************************
2529 * fill a notify_info_data with the servicename
2530 ********************************************************************/
2532 static void spoolss_notify_share_name(int snum
,
2533 struct spoolss_Notify
*data
,
2534 print_queue_struct
*queue
,
2535 NT_PRINTER_INFO_LEVEL
*printer
,
2536 TALLOC_CTX
*mem_ctx
)
2538 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2541 /*******************************************************************
2542 * fill a notify_info_data with the port name
2543 ********************************************************************/
2545 static void spoolss_notify_port_name(int snum
,
2546 struct spoolss_Notify
*data
,
2547 print_queue_struct
*queue
,
2548 NT_PRINTER_INFO_LEVEL
*printer
,
2549 TALLOC_CTX
*mem_ctx
)
2551 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->portname
);
2554 /*******************************************************************
2555 * fill a notify_info_data with the printername
2556 * but it doesn't exist, have to see what to do
2557 ********************************************************************/
2559 static void spoolss_notify_driver_name(int snum
,
2560 struct spoolss_Notify
*data
,
2561 print_queue_struct
*queue
,
2562 NT_PRINTER_INFO_LEVEL
*printer
,
2563 TALLOC_CTX
*mem_ctx
)
2565 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->drivername
);
2568 /*******************************************************************
2569 * fill a notify_info_data with the comment
2570 ********************************************************************/
2572 static void spoolss_notify_comment(int snum
,
2573 struct spoolss_Notify
*data
,
2574 print_queue_struct
*queue
,
2575 NT_PRINTER_INFO_LEVEL
*printer
,
2576 TALLOC_CTX
*mem_ctx
)
2580 if (*printer
->info_2
->comment
== '\0') {
2581 p
= lp_comment(snum
);
2583 p
= printer
->info_2
->comment
;
2586 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->comment
);
2589 /*******************************************************************
2590 * fill a notify_info_data with the comment
2591 * location = "Room 1, floor 2, building 3"
2592 ********************************************************************/
2594 static void spoolss_notify_location(int snum
,
2595 struct spoolss_Notify
*data
,
2596 print_queue_struct
*queue
,
2597 NT_PRINTER_INFO_LEVEL
*printer
,
2598 TALLOC_CTX
*mem_ctx
)
2600 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->location
);
2603 /*******************************************************************
2604 * fill a notify_info_data with the device mode
2605 * jfm:xxxx don't to it for know but that's a real problem !!!
2606 ********************************************************************/
2608 static void spoolss_notify_devmode(int snum
,
2609 struct spoolss_Notify
*data
,
2610 print_queue_struct
*queue
,
2611 NT_PRINTER_INFO_LEVEL
*printer
,
2612 TALLOC_CTX
*mem_ctx
)
2614 /* for a dummy implementation we have to zero the fields */
2615 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2618 /*******************************************************************
2619 * fill a notify_info_data with the separator file name
2620 ********************************************************************/
2622 static void spoolss_notify_sepfile(int snum
,
2623 struct spoolss_Notify
*data
,
2624 print_queue_struct
*queue
,
2625 NT_PRINTER_INFO_LEVEL
*printer
,
2626 TALLOC_CTX
*mem_ctx
)
2628 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->sepfile
);
2631 /*******************************************************************
2632 * fill a notify_info_data with the print processor
2633 * jfm:xxxx return always winprint to indicate we don't do anything to it
2634 ********************************************************************/
2636 static void spoolss_notify_print_processor(int snum
,
2637 struct spoolss_Notify
*data
,
2638 print_queue_struct
*queue
,
2639 NT_PRINTER_INFO_LEVEL
*printer
,
2640 TALLOC_CTX
*mem_ctx
)
2642 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->printprocessor
);
2645 /*******************************************************************
2646 * fill a notify_info_data with the print processor options
2647 * jfm:xxxx send an empty string
2648 ********************************************************************/
2650 static void spoolss_notify_parameters(int snum
,
2651 struct spoolss_Notify
*data
,
2652 print_queue_struct
*queue
,
2653 NT_PRINTER_INFO_LEVEL
*printer
,
2654 TALLOC_CTX
*mem_ctx
)
2656 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->parameters
);
2659 /*******************************************************************
2660 * fill a notify_info_data with the data type
2661 * jfm:xxxx always send RAW as data type
2662 ********************************************************************/
2664 static void spoolss_notify_datatype(int snum
,
2665 struct spoolss_Notify
*data
,
2666 print_queue_struct
*queue
,
2667 NT_PRINTER_INFO_LEVEL
*printer
,
2668 TALLOC_CTX
*mem_ctx
)
2670 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, printer
->info_2
->datatype
);
2673 /*******************************************************************
2674 * fill a notify_info_data with the security descriptor
2675 * jfm:xxxx send an null pointer to say no security desc
2676 * have to implement security before !
2677 ********************************************************************/
2679 static void spoolss_notify_security_desc(int snum
,
2680 struct spoolss_Notify
*data
,
2681 print_queue_struct
*queue
,
2682 NT_PRINTER_INFO_LEVEL
*printer
,
2683 TALLOC_CTX
*mem_ctx
)
2685 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
,
2686 printer
->info_2
->secdesc_buf
->sd_size
,
2687 printer
->info_2
->secdesc_buf
->sd
);
2690 /*******************************************************************
2691 * fill a notify_info_data with the attributes
2692 * jfm:xxxx a samba printer is always shared
2693 ********************************************************************/
2695 static void spoolss_notify_attributes(int snum
,
2696 struct spoolss_Notify
*data
,
2697 print_queue_struct
*queue
,
2698 NT_PRINTER_INFO_LEVEL
*printer
,
2699 TALLOC_CTX
*mem_ctx
)
2701 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->attributes
);
2704 /*******************************************************************
2705 * fill a notify_info_data with the priority
2706 ********************************************************************/
2708 static void spoolss_notify_priority(int snum
,
2709 struct spoolss_Notify
*data
,
2710 print_queue_struct
*queue
,
2711 NT_PRINTER_INFO_LEVEL
*printer
,
2712 TALLOC_CTX
*mem_ctx
)
2714 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->priority
);
2717 /*******************************************************************
2718 * fill a notify_info_data with the default priority
2719 ********************************************************************/
2721 static void spoolss_notify_default_priority(int snum
,
2722 struct spoolss_Notify
*data
,
2723 print_queue_struct
*queue
,
2724 NT_PRINTER_INFO_LEVEL
*printer
,
2725 TALLOC_CTX
*mem_ctx
)
2727 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->default_priority
);
2730 /*******************************************************************
2731 * fill a notify_info_data with the start time
2732 ********************************************************************/
2734 static void spoolss_notify_start_time(int snum
,
2735 struct spoolss_Notify
*data
,
2736 print_queue_struct
*queue
,
2737 NT_PRINTER_INFO_LEVEL
*printer
,
2738 TALLOC_CTX
*mem_ctx
)
2740 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->starttime
);
2743 /*******************************************************************
2744 * fill a notify_info_data with the until time
2745 ********************************************************************/
2747 static void spoolss_notify_until_time(int snum
,
2748 struct spoolss_Notify
*data
,
2749 print_queue_struct
*queue
,
2750 NT_PRINTER_INFO_LEVEL
*printer
,
2751 TALLOC_CTX
*mem_ctx
)
2753 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->untiltime
);
2756 /*******************************************************************
2757 * fill a notify_info_data with the status
2758 ********************************************************************/
2760 static void spoolss_notify_status(int snum
,
2761 struct spoolss_Notify
*data
,
2762 print_queue_struct
*queue
,
2763 NT_PRINTER_INFO_LEVEL
*printer
,
2764 TALLOC_CTX
*mem_ctx
)
2766 print_status_struct status
;
2768 print_queue_length(snum
, &status
);
2769 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
2772 /*******************************************************************
2773 * fill a notify_info_data with the number of jobs queued
2774 ********************************************************************/
2776 static void spoolss_notify_cjobs(int snum
,
2777 struct spoolss_Notify
*data
,
2778 print_queue_struct
*queue
,
2779 NT_PRINTER_INFO_LEVEL
*printer
,
2780 TALLOC_CTX
*mem_ctx
)
2782 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, print_queue_length(snum
, NULL
));
2785 /*******************************************************************
2786 * fill a notify_info_data with the average ppm
2787 ********************************************************************/
2789 static void spoolss_notify_average_ppm(int snum
,
2790 struct spoolss_Notify
*data
,
2791 print_queue_struct
*queue
,
2792 NT_PRINTER_INFO_LEVEL
*printer
,
2793 TALLOC_CTX
*mem_ctx
)
2795 /* always respond 8 pages per minutes */
2796 /* a little hard ! */
2797 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, printer
->info_2
->averageppm
);
2800 /*******************************************************************
2801 * fill a notify_info_data with username
2802 ********************************************************************/
2804 static void spoolss_notify_username(int snum
,
2805 struct spoolss_Notify
*data
,
2806 print_queue_struct
*queue
,
2807 NT_PRINTER_INFO_LEVEL
*printer
,
2808 TALLOC_CTX
*mem_ctx
)
2810 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
2813 /*******************************************************************
2814 * fill a notify_info_data with job status
2815 ********************************************************************/
2817 static void spoolss_notify_job_status(int snum
,
2818 struct spoolss_Notify
*data
,
2819 print_queue_struct
*queue
,
2820 NT_PRINTER_INFO_LEVEL
*printer
,
2821 TALLOC_CTX
*mem_ctx
)
2823 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
2826 /*******************************************************************
2827 * fill a notify_info_data with job name
2828 ********************************************************************/
2830 static void spoolss_notify_job_name(int snum
,
2831 struct spoolss_Notify
*data
,
2832 print_queue_struct
*queue
,
2833 NT_PRINTER_INFO_LEVEL
*printer
,
2834 TALLOC_CTX
*mem_ctx
)
2836 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
2839 /*******************************************************************
2840 * fill a notify_info_data with job status
2841 ********************************************************************/
2843 static void spoolss_notify_job_status_string(int snum
,
2844 struct spoolss_Notify
*data
,
2845 print_queue_struct
*queue
,
2846 NT_PRINTER_INFO_LEVEL
*printer
,
2847 TALLOC_CTX
*mem_ctx
)
2850 * Now we're returning job status codes we just return a "" here. JRA.
2855 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2858 switch (queue
->status
) {
2863 p
= ""; /* NT provides the paused string */
2872 #endif /* NO LONGER NEEDED. */
2874 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2877 /*******************************************************************
2878 * fill a notify_info_data with job time
2879 ********************************************************************/
2881 static void spoolss_notify_job_time(int snum
,
2882 struct spoolss_Notify
*data
,
2883 print_queue_struct
*queue
,
2884 NT_PRINTER_INFO_LEVEL
*printer
,
2885 TALLOC_CTX
*mem_ctx
)
2887 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
2890 /*******************************************************************
2891 * fill a notify_info_data with job size
2892 ********************************************************************/
2894 static void spoolss_notify_job_size(int snum
,
2895 struct spoolss_Notify
*data
,
2896 print_queue_struct
*queue
,
2897 NT_PRINTER_INFO_LEVEL
*printer
,
2898 TALLOC_CTX
*mem_ctx
)
2900 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
2903 /*******************************************************************
2904 * fill a notify_info_data with page info
2905 ********************************************************************/
2906 static void spoolss_notify_total_pages(int snum
,
2907 struct spoolss_Notify
*data
,
2908 print_queue_struct
*queue
,
2909 NT_PRINTER_INFO_LEVEL
*printer
,
2910 TALLOC_CTX
*mem_ctx
)
2912 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
2915 /*******************************************************************
2916 * fill a notify_info_data with pages printed info.
2917 ********************************************************************/
2918 static void spoolss_notify_pages_printed(int snum
,
2919 struct spoolss_Notify
*data
,
2920 print_queue_struct
*queue
,
2921 NT_PRINTER_INFO_LEVEL
*printer
,
2922 TALLOC_CTX
*mem_ctx
)
2924 /* Add code when back-end tracks this */
2925 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
2928 /*******************************************************************
2929 Fill a notify_info_data with job position.
2930 ********************************************************************/
2932 static void spoolss_notify_job_position(int snum
,
2933 struct spoolss_Notify
*data
,
2934 print_queue_struct
*queue
,
2935 NT_PRINTER_INFO_LEVEL
*printer
,
2936 TALLOC_CTX
*mem_ctx
)
2938 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->job
);
2941 /*******************************************************************
2942 Fill a notify_info_data with submitted time.
2943 ********************************************************************/
2945 static void spoolss_notify_submitted_time(int snum
,
2946 struct spoolss_Notify
*data
,
2947 print_queue_struct
*queue
,
2948 NT_PRINTER_INFO_LEVEL
*printer
,
2949 TALLOC_CTX
*mem_ctx
)
2951 data
->data
.string
.string
= NULL
;
2952 data
->data
.string
.size
= 0;
2954 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
2955 &data
->data
.string
.string
,
2956 &data
->data
.string
.size
);
2960 struct s_notify_info_data_table
2962 enum spoolss_NotifyType type
;
2965 enum spoolss_NotifyTable variable_type
;
2966 void (*fn
) (int snum
, struct spoolss_Notify
*data
,
2967 print_queue_struct
*queue
,
2968 NT_PRINTER_INFO_LEVEL
*printer
, TALLOC_CTX
*mem_ctx
);
2971 /* A table describing the various print notification constants and
2972 whether the notification data is a pointer to a variable sized
2973 buffer, a one value uint32_t or a two value uint32_t. */
2975 static const struct s_notify_info_data_table notify_info_data_table
[] =
2977 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
2978 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
2979 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
2980 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
2981 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
2982 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
2983 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
2984 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
2985 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
2986 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
2987 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
2988 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
2989 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
2990 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
2991 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
2992 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
2993 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
2994 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
2995 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
2996 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
2997 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
2998 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
2999 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3000 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3001 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3002 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3003 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3004 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3005 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3006 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3007 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3008 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3009 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3010 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3011 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3012 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3013 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3014 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3015 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3016 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3017 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3018 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3019 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3020 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3021 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3022 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3023 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3024 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3025 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3028 /*******************************************************************
3029 Return the variable_type of info_data structure.
3030 ********************************************************************/
3032 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3037 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3038 if ( (notify_info_data_table
[i
].type
== type
) &&
3039 (notify_info_data_table
[i
].field
== field
) ) {
3040 return notify_info_data_table
[i
].variable_type
;
3044 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3049 /****************************************************************************
3050 ****************************************************************************/
3052 static bool search_notify(enum spoolss_NotifyType type
,
3058 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3059 if (notify_info_data_table
[i
].type
== type
&&
3060 notify_info_data_table
[i
].field
== field
&&
3061 notify_info_data_table
[i
].fn
!= NULL
) {
3070 /****************************************************************************
3071 ****************************************************************************/
3073 void construct_info_data(struct spoolss_Notify
*info_data
,
3074 enum spoolss_NotifyType type
,
3078 info_data
->type
= type
;
3079 info_data
->field
.field
= field
;
3080 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3081 info_data
->job_id
= id
;
3084 /*******************************************************************
3086 * fill a notify_info struct with info asked
3088 ********************************************************************/
3090 static bool construct_notify_printer_info(Printer_entry
*print_hnd
,
3091 struct spoolss_NotifyInfo
*info
,
3093 const struct spoolss_NotifyOptionType
*option_type
,
3095 TALLOC_CTX
*mem_ctx
)
3098 enum spoolss_NotifyType type
;
3101 struct spoolss_Notify
*current_data
;
3102 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3103 print_queue_struct
*queue
=NULL
;
3105 type
= option_type
->type
;
3107 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3108 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3109 option_type
->count
, lp_servicename(snum
)));
3111 if (!W_ERROR_IS_OK(get_a_printer(print_hnd
, &printer
, 2, lp_const_servicename(snum
))))
3114 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3115 field
= option_type
->fields
[field_num
].field
;
3117 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3119 if (!search_notify(type
, field
, &j
) )
3122 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3123 struct spoolss_Notify
,
3125 if (info
->notifies
== NULL
) {
3126 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3127 free_a_printer(&printer
, 2);
3131 current_data
= &info
->notifies
[info
->count
];
3133 construct_info_data(current_data
, type
, field
, id
);
3135 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3136 notify_info_data_table
[j
].name
, snum
, printer
->info_2
->printername
));
3138 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3144 free_a_printer(&printer
, 2);
3148 /*******************************************************************
3150 * fill a notify_info struct with info asked
3152 ********************************************************************/
3154 static bool construct_notify_jobs_info(print_queue_struct
*queue
,
3155 struct spoolss_NotifyInfo
*info
,
3156 NT_PRINTER_INFO_LEVEL
*printer
,
3158 const struct spoolss_NotifyOptionType
*option_type
,
3160 TALLOC_CTX
*mem_ctx
)
3163 enum spoolss_NotifyType type
;
3165 struct spoolss_Notify
*current_data
;
3167 DEBUG(4,("construct_notify_jobs_info\n"));
3169 type
= option_type
->type
;
3171 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3172 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3173 option_type
->count
));
3175 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3176 field
= option_type
->fields
[field_num
].field
;
3178 if (!search_notify(type
, field
, &j
) )
3181 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3182 struct spoolss_Notify
,
3184 if (info
->notifies
== NULL
) {
3185 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3189 current_data
=&(info
->notifies
[info
->count
]);
3191 construct_info_data(current_data
, type
, field
, id
);
3192 notify_info_data_table
[j
].fn(snum
, current_data
, queue
,
3201 * JFM: The enumeration is not that simple, it's even non obvious.
3203 * let's take an example: I want to monitor the PRINTER SERVER for
3204 * the printer's name and the number of jobs currently queued.
3205 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3206 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3208 * I have 3 printers on the back of my server.
3210 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3213 * 1 printer 1 name 1
3214 * 2 printer 1 cjob 1
3215 * 3 printer 2 name 2
3216 * 4 printer 2 cjob 2
3217 * 5 printer 3 name 3
3218 * 6 printer 3 name 3
3220 * that's the print server case, the printer case is even worse.
3223 /*******************************************************************
3225 * enumerate all printers on the printserver
3226 * fill a notify_info struct with info asked
3228 ********************************************************************/
3230 static WERROR
printserver_notify_info(pipes_struct
*p
,
3231 struct policy_handle
*hnd
,
3232 struct spoolss_NotifyInfo
*info
,
3233 TALLOC_CTX
*mem_ctx
)
3236 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3237 int n_services
=lp_numservices();
3239 struct spoolss_NotifyOption
*option
;
3240 struct spoolss_NotifyOptionType option_type
;
3242 DEBUG(4,("printserver_notify_info\n"));
3247 option
= Printer
->notify
.option
;
3250 info
->notifies
= NULL
;
3253 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3254 sending a ffpcn() request first */
3259 for (i
=0; i
<option
->count
; i
++) {
3260 option_type
= option
->types
[i
];
3262 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3265 for (snum
=0; snum
<n_services
; snum
++)
3267 if ( lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
) )
3268 construct_notify_printer_info ( Printer
, info
, snum
, &option_type
, snum
, mem_ctx
);
3274 * Debugging information, don't delete.
3277 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3278 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3279 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3281 for (i
=0; i
<info
->count
; i
++) {
3282 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3283 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3284 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3291 /*******************************************************************
3293 * fill a notify_info struct with info asked
3295 ********************************************************************/
3297 static WERROR
printer_notify_info(pipes_struct
*p
, struct policy_handle
*hnd
,
3298 struct spoolss_NotifyInfo
*info
,
3299 TALLOC_CTX
*mem_ctx
)
3302 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3305 struct spoolss_NotifyOption
*option
;
3306 struct spoolss_NotifyOptionType option_type
;
3308 print_queue_struct
*queue
=NULL
;
3309 print_status_struct status
;
3311 DEBUG(4,("printer_notify_info\n"));
3316 option
= Printer
->notify
.option
;
3320 info
->notifies
= NULL
;
3323 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3324 sending a ffpcn() request first */
3329 get_printer_snum(p
, hnd
, &snum
, NULL
);
3331 for (i
=0; i
<option
->count
; i
++) {
3332 option_type
= option
->types
[i
];
3334 switch (option_type
.type
) {
3335 case PRINTER_NOTIFY_TYPE
:
3336 if(construct_notify_printer_info(Printer
, info
, snum
,
3342 case JOB_NOTIFY_TYPE
: {
3343 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3345 count
= print_queue_status(snum
, &queue
, &status
);
3347 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))))
3350 for (j
=0; j
<count
; j
++) {
3351 construct_notify_jobs_info(&queue
[j
], info
,
3358 free_a_printer(&printer
, 2);
3368 * Debugging information, don't delete.
3371 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3372 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3373 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3375 for (i=0; i<info->count; i++) {
3376 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3377 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3378 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3384 /****************************************************************
3385 _spoolss_RouterRefreshPrinterChangeNotify
3386 ****************************************************************/
3388 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(pipes_struct
*p
,
3389 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3391 struct spoolss_NotifyInfo
*info
;
3393 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3394 WERROR result
= WERR_BADFID
;
3396 /* we always have a spoolss_NotifyInfo struct */
3397 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3399 result
= WERR_NOMEM
;
3403 *r
->out
.info
= info
;
3406 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3407 "Invalid handle (%s:%u:%u).\n",
3408 OUR_HANDLE(r
->in
.handle
)));
3412 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3415 * We are now using the change value, and
3416 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3417 * I don't have a global notification system, I'm sending back all the
3418 * informations even when _NOTHING_ has changed.
3421 /* We need to keep track of the change value to send back in
3422 RRPCN replies otherwise our updates are ignored. */
3424 Printer
->notify
.fnpcn
= true;
3426 if (Printer
->notify
.client_connected
) {
3427 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3428 "Saving change value in request [%x]\n",
3430 Printer
->notify
.change
= r
->in
.change_low
;
3433 /* just ignore the spoolss_NotifyOption */
3435 switch (Printer
->printer_type
) {
3437 result
= printserver_notify_info(p
, r
->in
.handle
,
3441 case SPLHND_PRINTER
:
3442 result
= printer_notify_info(p
, r
->in
.handle
,
3447 Printer
->notify
.fnpcn
= false;
3453 /********************************************************************
3454 * construct_printer_info_0
3455 * fill a printer_info_0 struct
3456 ********************************************************************/
3458 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3459 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3460 struct spoolss_PrinterInfo0
*r
,
3464 counter_printer_0
*session_counter
;
3466 print_status_struct status
;
3468 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3469 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3471 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3472 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3474 count
= print_queue_length(snum
, &status
);
3476 /* check if we already have a counter for this printer */
3477 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3478 if (session_counter
->snum
== snum
)
3482 /* it's the first time, add it to the list */
3483 if (session_counter
== NULL
) {
3484 session_counter
= SMB_MALLOC_P(counter_printer_0
);
3485 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3486 ZERO_STRUCTP(session_counter
);
3487 session_counter
->snum
= snum
;
3488 session_counter
->counter
= 0;
3489 DLIST_ADD(counter_list
, session_counter
);
3493 session_counter
->counter
++;
3499 setuptime
= (time_t)ntprinter
->info_2
->setuptime
;
3501 init_systemtime(&r
->time
, gmtime(&setuptime
));
3504 * the global_counter should be stored in a TDB as it's common to all the clients
3505 * and should be zeroed on samba startup
3507 r
->global_counter
= session_counter
->counter
;
3509 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3510 SSVAL(&r
->version
, 0, 0x0005); /* NT 5 */
3511 SSVAL(&r
->version
, 2, 0x0893); /* build 2195 */
3512 r
->free_build
= SPOOLSS_RELEASE_BUILD
;
3514 r
->max_spooling
= 0;
3515 r
->session_counter
= session_counter
->counter
;
3516 r
->num_error_out_of_paper
= 0x0;
3517 r
->num_error_not_ready
= 0x0; /* number of print failure */
3519 r
->number_of_processors
= 0x1;
3520 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3521 r
->high_part_total_bytes
= 0x0;
3522 r
->change_id
= ntprinter
->info_2
->changeid
; /* ChangeID in milliseconds*/
3523 r
->last_error
= WERR_OK
;
3524 r
->status
= nt_printq_status(status
.status
);
3525 r
->enumerate_network_printers
= 0x0;
3526 r
->c_setprinter
= get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
3527 r
->processor_architecture
= 0x0;
3528 r
->processor_level
= 0x6; /* 6 ???*/
3536 /****************************************************************************
3537 Convert an NT_DEVICEMODE to a spoolss_DeviceMode structure. Both pointers
3538 should be valid upon entry
3539 ****************************************************************************/
3541 static WERROR
convert_nt_devicemode(TALLOC_CTX
*mem_ctx
,
3542 struct spoolss_DeviceMode
*r
,
3543 const NT_DEVICEMODE
*ntdevmode
)
3545 if (!r
|| !ntdevmode
) {
3546 return WERR_INVALID_PARAM
;
3549 r
->devicename
= talloc_strdup(mem_ctx
, ntdevmode
->devicename
);
3550 W_ERROR_HAVE_NO_MEMORY(r
->devicename
);
3552 r
->specversion
= ntdevmode
->specversion
;
3553 r
->driverversion
= ntdevmode
->driverversion
;
3554 r
->size
= ntdevmode
->size
;
3555 r
->__driverextra_length
= ntdevmode
->driverextra
;
3556 r
->fields
= ntdevmode
->fields
;
3558 r
->orientation
= ntdevmode
->orientation
;
3559 r
->papersize
= ntdevmode
->papersize
;
3560 r
->paperlength
= ntdevmode
->paperlength
;
3561 r
->paperwidth
= ntdevmode
->paperwidth
;
3562 r
->scale
= ntdevmode
->scale
;
3563 r
->copies
= ntdevmode
->copies
;
3564 r
->defaultsource
= ntdevmode
->defaultsource
;
3565 r
->printquality
= ntdevmode
->printquality
;
3566 r
->color
= ntdevmode
->color
;
3567 r
->duplex
= ntdevmode
->duplex
;
3568 r
->yresolution
= ntdevmode
->yresolution
;
3569 r
->ttoption
= ntdevmode
->ttoption
;
3570 r
->collate
= ntdevmode
->collate
;
3572 r
->formname
= talloc_strdup(mem_ctx
, ntdevmode
->formname
);
3573 W_ERROR_HAVE_NO_MEMORY(r
->formname
);
3575 r
->logpixels
= ntdevmode
->logpixels
;
3576 r
->bitsperpel
= ntdevmode
->bitsperpel
;
3577 r
->pelswidth
= ntdevmode
->pelswidth
;
3578 r
->pelsheight
= ntdevmode
->pelsheight
;
3579 r
->displayflags
= ntdevmode
->displayflags
;
3580 r
->displayfrequency
= ntdevmode
->displayfrequency
;
3581 r
->icmmethod
= ntdevmode
->icmmethod
;
3582 r
->icmintent
= ntdevmode
->icmintent
;
3583 r
->mediatype
= ntdevmode
->mediatype
;
3584 r
->dithertype
= ntdevmode
->dithertype
;
3585 r
->reserved1
= ntdevmode
->reserved1
;
3586 r
->reserved2
= ntdevmode
->reserved2
;
3587 r
->panningwidth
= ntdevmode
->panningwidth
;
3588 r
->panningheight
= ntdevmode
->panningheight
;
3590 if (ntdevmode
->nt_dev_private
!= NULL
) {
3591 r
->driverextra_data
= data_blob_talloc(mem_ctx
,
3592 ntdevmode
->nt_dev_private
,
3593 ntdevmode
->driverextra
);
3594 W_ERROR_HAVE_NO_MEMORY(r
->driverextra_data
.data
);
3601 /****************************************************************************
3602 Create a spoolss_DeviceMode struct. Returns talloced memory.
3603 ****************************************************************************/
3605 struct spoolss_DeviceMode
*construct_dev_mode(TALLOC_CTX
*mem_ctx
,
3606 const char *servicename
)
3609 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
3610 struct spoolss_DeviceMode
*devmode
= NULL
;
3612 DEBUG(7,("construct_dev_mode\n"));
3614 DEBUGADD(8,("getting printer characteristics\n"));
3616 if (!W_ERROR_IS_OK(get_a_printer(NULL
, &printer
, 2, servicename
)))
3619 if (!printer
->info_2
->devmode
) {
3620 DEBUG(5, ("BONG! There was no device mode!\n"));
3624 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
3626 DEBUG(2,("construct_dev_mode: talloc fail.\n"));
3630 DEBUGADD(8,("loading DEVICEMODE\n"));
3632 result
= convert_nt_devicemode(mem_ctx
, devmode
, printer
->info_2
->devmode
);
3633 if (!W_ERROR_IS_OK(result
)) {
3634 TALLOC_FREE(devmode
);
3638 free_a_printer(&printer
,2);
3643 /********************************************************************
3644 * construct_printer_info1
3645 * fill a spoolss_PrinterInfo1 struct
3646 ********************************************************************/
3648 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
3649 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3651 struct spoolss_PrinterInfo1
*r
,
3656 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
3657 ntprinter
->info_2
->printername
,
3658 ntprinter
->info_2
->drivername
,
3659 ntprinter
->info_2
->location
);
3660 W_ERROR_HAVE_NO_MEMORY(r
->description
);
3662 if (*ntprinter
->info_2
->comment
== '\0') {
3663 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3665 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
); /* saved comment */
3667 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3669 r
->name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3670 W_ERROR_HAVE_NO_MEMORY(r
->name
);
3675 /********************************************************************
3676 * construct_printer_info2
3677 * fill a spoolss_PrinterInfo2 struct
3678 ********************************************************************/
3680 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
3681 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3682 struct spoolss_PrinterInfo2
*r
,
3687 print_status_struct status
;
3689 count
= print_queue_length(snum
, &status
);
3691 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3692 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3693 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3694 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3695 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
3696 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
3697 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
3698 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3699 r
->drivername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
3700 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
3702 if (*ntprinter
->info_2
->comment
== '\0') {
3703 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3705 r
->comment
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->comment
);
3707 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3709 r
->location
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->location
);
3710 W_ERROR_HAVE_NO_MEMORY(r
->location
);
3711 r
->sepfile
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->sepfile
);
3712 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
3713 r
->printprocessor
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printprocessor
);
3714 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
3715 r
->datatype
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->datatype
);
3716 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
3717 r
->parameters
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->parameters
);
3718 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
3720 r
->attributes
= ntprinter
->info_2
->attributes
;
3722 r
->priority
= ntprinter
->info_2
->priority
;
3723 r
->defaultpriority
= ntprinter
->info_2
->default_priority
;
3724 r
->starttime
= ntprinter
->info_2
->starttime
;
3725 r
->untiltime
= ntprinter
->info_2
->untiltime
;
3726 r
->status
= nt_printq_status(status
.status
);
3728 r
->averageppm
= ntprinter
->info_2
->averageppm
;
3730 r
->devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
3732 DEBUG(8,("Returning NULL Devicemode!\n"));
3737 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
3738 /* don't use talloc_steal() here unless you do a deep steal of all
3739 the SEC_DESC members */
3741 r
->secdesc
= dup_sec_desc(mem_ctx
, ntprinter
->info_2
->secdesc_buf
->sd
);
3747 /********************************************************************
3748 * construct_printer_info3
3749 * fill a spoolss_PrinterInfo3 struct
3750 ********************************************************************/
3752 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
3753 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3754 struct spoolss_PrinterInfo3
*r
,
3757 /* These are the components of the SD we are returning. */
3759 if (ntprinter
->info_2
->secdesc_buf
&& ntprinter
->info_2
->secdesc_buf
->sd_size
!= 0) {
3760 /* don't use talloc_steal() here unless you do a deep steal of all
3761 the SEC_DESC members */
3763 r
->secdesc
= dup_sec_desc(mem_ctx
,
3764 ntprinter
->info_2
->secdesc_buf
->sd
);
3765 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
3771 /********************************************************************
3772 * construct_printer_info4
3773 * fill a spoolss_PrinterInfo4 struct
3774 ********************************************************************/
3776 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
3777 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3778 struct spoolss_PrinterInfo4
*r
,
3781 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3782 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3783 r
->servername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
3784 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3786 r
->attributes
= ntprinter
->info_2
->attributes
;
3791 /********************************************************************
3792 * construct_printer_info5
3793 * fill a spoolss_PrinterInfo5 struct
3794 ********************************************************************/
3796 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
3797 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3798 struct spoolss_PrinterInfo5
*r
,
3801 r
->printername
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->printername
);
3802 W_ERROR_HAVE_NO_MEMORY(r
->printername
);
3803 r
->portname
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->portname
);
3804 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3806 r
->attributes
= ntprinter
->info_2
->attributes
;
3808 /* these two are not used by NT+ according to MSDN */
3810 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
3811 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
3816 /********************************************************************
3817 * construct_printer_info_6
3818 * fill a spoolss_PrinterInfo6 struct
3819 ********************************************************************/
3821 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
3822 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3823 struct spoolss_PrinterInfo6
*r
,
3827 print_status_struct status
;
3829 count
= print_queue_length(snum
, &status
);
3831 r
->status
= nt_printq_status(status
.status
);
3836 /********************************************************************
3837 * construct_printer_info7
3838 * fill a spoolss_PrinterInfo7 struct
3839 ********************************************************************/
3841 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
3842 Printer_entry
*print_hnd
,
3843 struct spoolss_PrinterInfo7
*r
,
3848 if (is_printer_published(print_hnd
, snum
, &guid
)) {
3849 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
3850 r
->action
= DSPRINT_PUBLISH
;
3852 r
->guid
= talloc_strdup(mem_ctx
, "");
3853 r
->action
= DSPRINT_UNPUBLISH
;
3855 W_ERROR_HAVE_NO_MEMORY(r
->guid
);
3860 /********************************************************************
3861 * construct_printer_info8
3862 * fill a spoolss_PrinterInfo8 struct
3863 ********************************************************************/
3865 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
3866 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
3867 struct spoolss_DeviceModeInfo
*r
,
3870 r
->devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
3872 DEBUG(8,("Returning NULL Devicemode!\n"));
3879 /********************************************************************
3880 ********************************************************************/
3882 static bool snum_is_shared_printer(int snum
)
3884 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
3887 /********************************************************************
3888 Spoolss_enumprinters.
3889 ********************************************************************/
3891 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
3894 union spoolss_PrinterInfo
**info_p
,
3898 int n_services
= lp_numservices();
3899 union spoolss_PrinterInfo
*info
= NULL
;
3901 WERROR result
= WERR_OK
;
3906 for (snum
= 0; snum
< n_services
; snum
++) {
3908 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
3910 if (!snum_is_shared_printer(snum
)) {
3914 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
3915 lp_servicename(snum
), snum
));
3917 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
3918 union spoolss_PrinterInfo
,
3921 result
= WERR_NOMEM
;
3925 result
= get_a_printer(NULL
, &ntprinter
, 2,
3926 lp_const_servicename(snum
));
3927 if (!W_ERROR_IS_OK(result
)) {
3933 result
= construct_printer_info0(info
, ntprinter
,
3934 &info
[count
].info0
, snum
);
3937 result
= construct_printer_info1(info
, ntprinter
, flags
,
3938 &info
[count
].info1
, snum
);
3941 result
= construct_printer_info2(info
, ntprinter
,
3942 &info
[count
].info2
, snum
);
3945 result
= construct_printer_info4(info
, ntprinter
,
3946 &info
[count
].info4
, snum
);
3949 result
= construct_printer_info5(info
, ntprinter
,
3950 &info
[count
].info5
, snum
);
3954 result
= WERR_UNKNOWN_LEVEL
;
3955 free_a_printer(&ntprinter
, 2);
3959 free_a_printer(&ntprinter
, 2);
3960 if (!W_ERROR_IS_OK(result
)) {
3971 if (!W_ERROR_IS_OK(result
)) {
3981 /********************************************************************
3982 * handle enumeration of printers at level 0
3983 ********************************************************************/
3985 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
3987 const char *servername
,
3988 union spoolss_PrinterInfo
**info
,
3991 DEBUG(4,("enum_all_printers_info_0\n"));
3993 return enum_all_printers_info_level(mem_ctx
, 0, flags
, info
, count
);
3997 /********************************************************************
3998 ********************************************************************/
4000 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4002 union spoolss_PrinterInfo
**info
,
4005 DEBUG(4,("enum_all_printers_info_1\n"));
4007 return enum_all_printers_info_level(mem_ctx
, 1, flags
, info
, count
);
4010 /********************************************************************
4011 enum_all_printers_info_1_local.
4012 *********************************************************************/
4014 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4015 union spoolss_PrinterInfo
**info
,
4018 DEBUG(4,("enum_all_printers_info_1_local\n"));
4020 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4023 /********************************************************************
4024 enum_all_printers_info_1_name.
4025 *********************************************************************/
4027 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4029 union spoolss_PrinterInfo
**info
,
4032 const char *s
= name
;
4034 DEBUG(4,("enum_all_printers_info_1_name\n"));
4036 if ((name
[0] == '\\') && (name
[1] == '\\')) {
4040 if (!is_myname_or_ipaddr(s
)) {
4041 return WERR_INVALID_NAME
;
4044 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_ICON8
, info
, count
);
4047 /********************************************************************
4048 enum_all_printers_info_1_network.
4049 *********************************************************************/
4051 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4053 union spoolss_PrinterInfo
**info
,
4056 const char *s
= name
;
4058 DEBUG(4,("enum_all_printers_info_1_network\n"));
4060 /* If we respond to a enum_printers level 1 on our name with flags
4061 set to PRINTER_ENUM_REMOTE with a list of printers then these
4062 printers incorrectly appear in the APW browse list.
4063 Specifically the printers for the server appear at the workgroup
4064 level where all the other servers in the domain are
4065 listed. Windows responds to this call with a
4066 WERR_CAN_NOT_COMPLETE so we should do the same. */
4068 if (name
[0] == '\\' && name
[1] == '\\') {
4072 if (is_myname_or_ipaddr(s
)) {
4073 return WERR_CAN_NOT_COMPLETE
;
4076 return enum_all_printers_info_1(mem_ctx
, PRINTER_ENUM_NAME
, info
, count
);
4079 /********************************************************************
4080 * api_spoolss_enumprinters
4082 * called from api_spoolss_enumprinters (see this to understand)
4083 ********************************************************************/
4085 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4086 union spoolss_PrinterInfo
**info
,
4089 DEBUG(4,("enum_all_printers_info_2\n"));
4091 return enum_all_printers_info_level(mem_ctx
, 2, 0, info
, count
);
4094 /********************************************************************
4095 * handle enumeration of printers at level 1
4096 ********************************************************************/
4098 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4101 union spoolss_PrinterInfo
**info
,
4104 /* Not all the flags are equals */
4106 if (flags
& PRINTER_ENUM_LOCAL
) {
4107 return enum_all_printers_info_1_local(mem_ctx
, info
, count
);
4110 if (flags
& PRINTER_ENUM_NAME
) {
4111 return enum_all_printers_info_1_name(mem_ctx
, name
, info
, count
);
4114 if (flags
& PRINTER_ENUM_NETWORK
) {
4115 return enum_all_printers_info_1_network(mem_ctx
, name
, info
, count
);
4118 return WERR_OK
; /* NT4sp5 does that */
4121 /********************************************************************
4122 * handle enumeration of printers at level 2
4123 ********************************************************************/
4125 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4127 const char *servername
,
4128 union spoolss_PrinterInfo
**info
,
4131 if (flags
& PRINTER_ENUM_LOCAL
) {
4132 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4135 if (flags
& PRINTER_ENUM_NAME
) {
4136 if (!is_myname_or_ipaddr(canon_servername(servername
))) {
4137 return WERR_INVALID_NAME
;
4140 return enum_all_printers_info_2(mem_ctx
, info
, count
);
4143 if (flags
& PRINTER_ENUM_REMOTE
) {
4144 return WERR_UNKNOWN_LEVEL
;
4150 /********************************************************************
4151 * handle enumeration of printers at level 4
4152 ********************************************************************/
4154 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4156 const char *servername
,
4157 union spoolss_PrinterInfo
**info
,
4160 DEBUG(4,("enum_all_printers_info_4\n"));
4162 return enum_all_printers_info_level(mem_ctx
, 4, flags
, info
, count
);
4166 /********************************************************************
4167 * handle enumeration of printers at level 5
4168 ********************************************************************/
4170 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4172 const char *servername
,
4173 union spoolss_PrinterInfo
**info
,
4176 DEBUG(4,("enum_all_printers_info_5\n"));
4178 return enum_all_printers_info_level(mem_ctx
, 5, flags
, info
, count
);
4181 /****************************************************************
4182 _spoolss_EnumPrinters
4183 ****************************************************************/
4185 WERROR
_spoolss_EnumPrinters(pipes_struct
*p
,
4186 struct spoolss_EnumPrinters
*r
)
4188 const char *name
= NULL
;
4191 /* that's an [in out] buffer */
4193 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4194 return WERR_INVALID_PARAM
;
4197 DEBUG(4,("_spoolss_EnumPrinters\n"));
4201 *r
->out
.info
= NULL
;
4205 * flags==PRINTER_ENUM_NAME
4206 * if name=="" then enumerates all printers
4207 * if name!="" then enumerate the printer
4208 * flags==PRINTER_ENUM_REMOTE
4209 * name is NULL, enumerate printers
4210 * Level 2: name!="" enumerates printers, name can't be NULL
4211 * Level 3: doesn't exist
4212 * Level 4: does a local registry lookup
4213 * Level 5: same as Level 2
4217 name
= talloc_strdup_upper(p
->mem_ctx
, r
->in
.server
);
4218 W_ERROR_HAVE_NO_MEMORY(name
);
4221 switch (r
->in
.level
) {
4223 result
= enumprinters_level0(p
->mem_ctx
, r
->in
.flags
, name
,
4224 r
->out
.info
, r
->out
.count
);
4227 result
= enumprinters_level1(p
->mem_ctx
, r
->in
.flags
, name
,
4228 r
->out
.info
, r
->out
.count
);
4231 result
= enumprinters_level2(p
->mem_ctx
, r
->in
.flags
, name
,
4232 r
->out
.info
, r
->out
.count
);
4235 result
= enumprinters_level4(p
->mem_ctx
, r
->in
.flags
, name
,
4236 r
->out
.info
, r
->out
.count
);
4239 result
= enumprinters_level5(p
->mem_ctx
, r
->in
.flags
, name
,
4240 r
->out
.info
, r
->out
.count
);
4243 return WERR_UNKNOWN_LEVEL
;
4246 if (!W_ERROR_IS_OK(result
)) {
4250 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4251 spoolss_EnumPrinters
,
4252 *r
->out
.info
, r
->in
.level
,
4254 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4255 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4257 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4260 /****************************************************************
4262 ****************************************************************/
4264 WERROR
_spoolss_GetPrinter(pipes_struct
*p
,
4265 struct spoolss_GetPrinter
*r
)
4267 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4268 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
4269 WERROR result
= WERR_OK
;
4273 /* that's an [in out] buffer */
4275 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4276 return WERR_INVALID_PARAM
;
4281 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4285 result
= get_a_printer(Printer
, &ntprinter
, 2,
4286 lp_const_servicename(snum
));
4287 if (!W_ERROR_IS_OK(result
)) {
4291 switch (r
->in
.level
) {
4293 result
= construct_printer_info0(p
->mem_ctx
, ntprinter
,
4294 &r
->out
.info
->info0
, snum
);
4297 result
= construct_printer_info1(p
->mem_ctx
, ntprinter
,
4299 &r
->out
.info
->info1
, snum
);
4302 result
= construct_printer_info2(p
->mem_ctx
, ntprinter
,
4303 &r
->out
.info
->info2
, snum
);
4306 result
= construct_printer_info3(p
->mem_ctx
, ntprinter
,
4307 &r
->out
.info
->info3
, snum
);
4310 result
= construct_printer_info4(p
->mem_ctx
, ntprinter
,
4311 &r
->out
.info
->info4
, snum
);
4314 result
= construct_printer_info5(p
->mem_ctx
, ntprinter
,
4315 &r
->out
.info
->info5
, snum
);
4318 result
= construct_printer_info6(p
->mem_ctx
, ntprinter
,
4319 &r
->out
.info
->info6
, snum
);
4322 result
= construct_printer_info7(p
->mem_ctx
, Printer
,
4323 &r
->out
.info
->info7
, snum
);
4326 result
= construct_printer_info8(p
->mem_ctx
, ntprinter
,
4327 &r
->out
.info
->info8
, snum
);
4330 result
= WERR_UNKNOWN_LEVEL
;
4334 free_a_printer(&ntprinter
, 2);
4336 if (!W_ERROR_IS_OK(result
)) {
4337 TALLOC_FREE(r
->out
.info
);
4341 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
,
4342 r
->out
.info
, r
->in
.level
);
4343 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4345 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4348 /********************************************************************
4349 ********************************************************************/
4351 static const char **string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4352 const char **string_array
,
4353 const char *cservername
)
4355 int i
, num_strings
= 0;
4356 const char **array
= NULL
;
4358 if (!string_array
) {
4362 for (i
=0; string_array
[i
] && string_array
[i
][0] != '\0'; i
++) {
4364 const char *str
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4365 cservername
, string_array
[i
]);
4372 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4379 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4380 &array
, &num_strings
);
4386 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4388 if (in && strlen(in)) { \
4389 out = talloc_strdup(mem_ctx, in); \
4390 W_ERROR_HAVE_NO_MEMORY(out); \
4396 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, in, out) \
4398 if (in && strlen(in)) { \
4399 out = talloc_asprintf(mem_ctx, "\\\\%s%s", server, in); \
4401 out = talloc_strdup(mem_ctx, ""); \
4403 W_ERROR_HAVE_NO_MEMORY(out); \
4406 /********************************************************************
4407 * fill a spoolss_DriverInfo1 struct
4408 ********************************************************************/
4410 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4411 struct spoolss_DriverInfo1
*r
,
4412 const struct spoolss_DriverInfo8
*driver
,
4413 const char *servername
)
4415 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4416 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4421 /********************************************************************
4422 * fill a spoolss_DriverInfo2 struct
4423 ********************************************************************/
4425 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4426 struct spoolss_DriverInfo2
*r
,
4427 const struct spoolss_DriverInfo8
*driver
,
4428 const char *servername
)
4431 const char *cservername
= canon_servername(servername
);
4433 r
->version
= driver
->version
;
4435 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4436 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4437 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4438 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4440 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4441 driver
->driver_path
,
4444 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4448 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4449 driver
->config_file
,
4455 /********************************************************************
4456 * fill a spoolss_DriverInfo3 struct
4457 ********************************************************************/
4459 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4460 struct spoolss_DriverInfo3
*r
,
4461 const struct spoolss_DriverInfo8
*driver
,
4462 const char *servername
)
4464 const char *cservername
= canon_servername(servername
);
4466 r
->version
= driver
->version
;
4468 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4469 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4470 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4471 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4473 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4474 driver
->driver_path
,
4477 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4481 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4482 driver
->config_file
,
4485 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4489 FILL_DRIVER_STRING(mem_ctx
,
4490 driver
->monitor_name
,
4493 FILL_DRIVER_STRING(mem_ctx
,
4494 driver
->default_datatype
,
4495 r
->default_datatype
);
4497 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4498 driver
->dependent_files
,
4503 /********************************************************************
4504 * fill a spoolss_DriverInfo4 struct
4505 ********************************************************************/
4507 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
4508 struct spoolss_DriverInfo4
*r
,
4509 const struct spoolss_DriverInfo8
*driver
,
4510 const char *servername
)
4512 const char *cservername
= canon_servername(servername
);
4514 r
->version
= driver
->version
;
4516 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4517 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4518 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4519 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4521 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4522 driver
->driver_path
,
4525 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4529 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4530 driver
->config_file
,
4533 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4537 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4538 driver
->dependent_files
,
4541 FILL_DRIVER_STRING(mem_ctx
,
4542 driver
->monitor_name
,
4545 FILL_DRIVER_STRING(mem_ctx
,
4546 driver
->default_datatype
,
4547 r
->default_datatype
);
4549 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4550 driver
->previous_names
,
4556 /********************************************************************
4557 * fill a spoolss_DriverInfo5 struct
4558 ********************************************************************/
4560 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
4561 struct spoolss_DriverInfo5
*r
,
4562 const struct spoolss_DriverInfo8
*driver
,
4563 const char *servername
)
4565 const char *cservername
= canon_servername(servername
);
4567 r
->version
= driver
->version
;
4569 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4570 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4571 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4572 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4574 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4575 driver
->driver_path
,
4578 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4582 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4583 driver
->config_file
,
4586 r
->driver_attributes
= 0;
4587 r
->config_version
= 0;
4588 r
->driver_version
= 0;
4592 /********************************************************************
4593 * fill a spoolss_DriverInfo6 struct
4594 ********************************************************************/
4596 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
4597 struct spoolss_DriverInfo6
*r
,
4598 const struct spoolss_DriverInfo8
*driver
,
4599 const char *servername
)
4601 const char *cservername
= canon_servername(servername
);
4603 r
->version
= driver
->version
;
4605 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4606 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4607 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4608 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4610 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4611 driver
->driver_path
,
4614 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4618 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4619 driver
->config_file
,
4622 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4626 FILL_DRIVER_STRING(mem_ctx
,
4627 driver
->monitor_name
,
4630 FILL_DRIVER_STRING(mem_ctx
,
4631 driver
->default_datatype
,
4632 r
->default_datatype
);
4634 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4635 driver
->dependent_files
,
4637 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4638 driver
->previous_names
,
4641 r
->driver_date
= driver
->driver_date
;
4642 r
->driver_version
= driver
->driver_version
;
4644 FILL_DRIVER_STRING(mem_ctx
,
4645 driver
->manufacturer_name
,
4646 r
->manufacturer_name
);
4647 FILL_DRIVER_STRING(mem_ctx
,
4648 driver
->manufacturer_url
,
4649 r
->manufacturer_url
);
4650 FILL_DRIVER_STRING(mem_ctx
,
4651 driver
->hardware_id
,
4653 FILL_DRIVER_STRING(mem_ctx
,
4660 /********************************************************************
4661 * fill a spoolss_DriverInfo8 struct
4662 ********************************************************************/
4664 static WERROR
fill_printer_driver_info8(TALLOC_CTX
*mem_ctx
,
4665 struct spoolss_DriverInfo8
*r
,
4666 const struct spoolss_DriverInfo8
*driver
,
4667 const char *servername
)
4669 const char *cservername
= canon_servername(servername
);
4671 r
->version
= driver
->version
;
4673 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4674 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4675 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4676 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4678 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4679 driver
->driver_path
,
4682 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4686 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4687 driver
->config_file
,
4690 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4694 FILL_DRIVER_STRING(mem_ctx
,
4695 driver
->monitor_name
,
4698 FILL_DRIVER_STRING(mem_ctx
,
4699 driver
->default_datatype
,
4700 r
->default_datatype
);
4702 r
->dependent_files
= string_array_from_driver_info(mem_ctx
,
4703 driver
->dependent_files
,
4705 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4706 driver
->previous_names
,
4709 r
->driver_date
= driver
->driver_date
;
4710 r
->driver_version
= driver
->driver_version
;
4712 FILL_DRIVER_STRING(mem_ctx
,
4713 driver
->manufacturer_name
,
4714 r
->manufacturer_name
);
4715 FILL_DRIVER_STRING(mem_ctx
,
4716 driver
->manufacturer_url
,
4717 r
->manufacturer_url
);
4718 FILL_DRIVER_STRING(mem_ctx
,
4719 driver
->hardware_id
,
4721 FILL_DRIVER_STRING(mem_ctx
,
4725 FILL_DRIVER_STRING(mem_ctx
,
4726 driver
->print_processor
,
4727 r
->print_processor
);
4728 FILL_DRIVER_STRING(mem_ctx
,
4729 driver
->vendor_setup
,
4732 r
->color_profiles
= string_array_from_driver_info(mem_ctx
,
4733 driver
->color_profiles
,
4736 FILL_DRIVER_STRING(mem_ctx
,
4740 r
->printer_driver_attributes
= driver
->printer_driver_attributes
;
4742 r
->core_driver_dependencies
= string_array_from_driver_info(mem_ctx
,
4743 driver
->core_driver_dependencies
,
4746 r
->min_inbox_driver_ver_date
= driver
->min_inbox_driver_ver_date
;
4747 r
->min_inbox_driver_ver_version
= driver
->min_inbox_driver_ver_version
;
4752 #if 0 /* disabled until marshalling issues are resolved - gd */
4753 /********************************************************************
4754 ********************************************************************/
4756 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
4757 struct spoolss_DriverFileInfo
*r
,
4758 const char *cservername
,
4759 const char *file_name
,
4760 enum spoolss_DriverFileType file_type
,
4761 uint32_t file_version
)
4763 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
4764 cservername
, file_name
);
4765 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
4766 r
->file_type
= file_type
;
4767 r
->file_version
= file_version
;
4772 /********************************************************************
4773 ********************************************************************/
4775 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
4776 const struct spoolss_DriverInfo8
*driver
,
4777 const char *cservername
,
4778 struct spoolss_DriverFileInfo
**info_p
,
4781 struct spoolss_DriverFileInfo
*info
= NULL
;
4789 if (strlen(driver
->driver_path
)) {
4790 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4791 struct spoolss_DriverFileInfo
,
4793 W_ERROR_HAVE_NO_MEMORY(info
);
4794 result
= fill_spoolss_DriverFileInfo(info
,
4797 driver
->driver_path
,
4798 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
4800 W_ERROR_NOT_OK_RETURN(result
);
4804 if (strlen(driver
->config_file
)) {
4805 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4806 struct spoolss_DriverFileInfo
,
4808 W_ERROR_HAVE_NO_MEMORY(info
);
4809 result
= fill_spoolss_DriverFileInfo(info
,
4812 driver
->config_file
,
4813 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
4815 W_ERROR_NOT_OK_RETURN(result
);
4819 if (strlen(driver
->data_file
)) {
4820 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4821 struct spoolss_DriverFileInfo
,
4823 W_ERROR_HAVE_NO_MEMORY(info
);
4824 result
= fill_spoolss_DriverFileInfo(info
,
4828 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
4830 W_ERROR_NOT_OK_RETURN(result
);
4834 if (strlen(driver
->help_file
)) {
4835 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4836 struct spoolss_DriverFileInfo
,
4838 W_ERROR_HAVE_NO_MEMORY(info
);
4839 result
= fill_spoolss_DriverFileInfo(info
,
4843 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
4845 W_ERROR_NOT_OK_RETURN(result
);
4849 for (i
=0; driver
->dependent_files
[i
] && driver
->dependent_files
[i
][0] != '\0'; i
++) {
4850 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4851 struct spoolss_DriverFileInfo
,
4853 W_ERROR_HAVE_NO_MEMORY(info
);
4854 result
= fill_spoolss_DriverFileInfo(info
,
4857 driver
->dependent_files
[i
],
4858 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
4860 W_ERROR_NOT_OK_RETURN(result
);
4870 /********************************************************************
4871 * fill a spoolss_DriverInfo101 struct
4872 ********************************************************************/
4874 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
4875 struct spoolss_DriverInfo101
*r
,
4876 const struct spoolss_DriverInfo8
*driver
,
4877 const char *servername
)
4879 const char *cservername
= canon_servername(servername
);
4882 r
->version
= driver
->version
;
4884 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4885 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4886 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4887 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4889 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
4893 if (!W_ERROR_IS_OK(result
)) {
4897 FILL_DRIVER_STRING(mem_ctx
,
4898 driver
->monitor_name
,
4901 FILL_DRIVER_STRING(mem_ctx
,
4902 driver
->default_datatype
,
4903 r
->default_datatype
);
4905 r
->previous_names
= string_array_from_driver_info(mem_ctx
,
4906 driver
->previous_names
,
4908 r
->driver_date
= driver
->driver_date
;
4909 r
->driver_version
= driver
->driver_version
;
4911 FILL_DRIVER_STRING(mem_ctx
,
4912 driver
->manufacturer_name
,
4913 r
->manufacturer_name
);
4914 FILL_DRIVER_STRING(mem_ctx
,
4915 driver
->manufacturer_url
,
4916 r
->manufacturer_url
);
4917 FILL_DRIVER_STRING(mem_ctx
,
4918 driver
->hardware_id
,
4920 FILL_DRIVER_STRING(mem_ctx
,
4927 /********************************************************************
4928 ********************************************************************/
4930 static WERROR
construct_printer_driver_info_level(TALLOC_CTX
*mem_ctx
,
4932 union spoolss_DriverInfo
*r
,
4934 const char *servername
,
4935 const char *architecture
,
4938 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
4939 struct spoolss_DriverInfo8
*driver
;
4942 result
= get_a_printer(NULL
, &printer
, 2, lp_const_servicename(snum
));
4944 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4945 win_errstr(result
)));
4947 if (!W_ERROR_IS_OK(result
)) {
4948 return WERR_INVALID_PRINTER_NAME
;
4951 result
= get_a_printer_driver(mem_ctx
, &driver
, printer
->info_2
->drivername
,
4952 architecture
, version
);
4954 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
4955 win_errstr(result
)));
4957 if (!W_ERROR_IS_OK(result
)) {
4959 * Is this a W2k client ?
4963 free_a_printer(&printer
, 2);
4964 return WERR_UNKNOWN_PRINTER_DRIVER
;
4967 /* Yes - try again with a WinNT driver. */
4969 result
= get_a_printer_driver(mem_ctx
, &driver
, printer
->info_2
->drivername
,
4970 architecture
, version
);
4971 DEBUG(8,("construct_printer_driver_level: status: %s\n",
4972 win_errstr(result
)));
4973 if (!W_ERROR_IS_OK(result
)) {
4974 free_a_printer(&printer
, 2);
4975 return WERR_UNKNOWN_PRINTER_DRIVER
;
4981 result
= fill_printer_driver_info1(mem_ctx
, &r
->info1
, driver
, servername
);
4984 result
= fill_printer_driver_info2(mem_ctx
, &r
->info2
, driver
, servername
);
4987 result
= fill_printer_driver_info3(mem_ctx
, &r
->info3
, driver
, servername
);
4990 result
= fill_printer_driver_info4(mem_ctx
, &r
->info4
, driver
, servername
);
4993 result
= fill_printer_driver_info5(mem_ctx
, &r
->info5
, driver
, servername
);
4996 result
= fill_printer_driver_info6(mem_ctx
, &r
->info6
, driver
, servername
);
4999 result
= fill_printer_driver_info8(mem_ctx
, &r
->info8
, driver
, servername
);
5001 #if 0 /* disabled until marshalling issues are resolved - gd */
5003 result
= fill_printer_driver_info101(mem_ctx
, &r
->info101
, driver
, servername
);
5007 result
= WERR_UNKNOWN_LEVEL
;
5011 free_a_printer(&printer
, 2);
5012 free_a_printer_driver(driver
);
5017 /****************************************************************
5018 _spoolss_GetPrinterDriver2
5019 ****************************************************************/
5021 WERROR
_spoolss_GetPrinterDriver2(pipes_struct
*p
,
5022 struct spoolss_GetPrinterDriver2
*r
)
5024 Printer_entry
*printer
;
5027 const char *servername
;
5030 /* that's an [in out] buffer */
5032 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5033 return WERR_INVALID_PARAM
;
5036 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5038 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5039 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5040 return WERR_INVALID_PRINTER_NAME
;
5044 *r
->out
.server_major_version
= 0;
5045 *r
->out
.server_minor_version
= 0;
5047 servername
= get_server_name(printer
);
5049 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5053 result
= construct_printer_driver_info_level(p
->mem_ctx
, r
->in
.level
,
5057 r
->in
.client_major_version
);
5058 if (!W_ERROR_IS_OK(result
)) {
5059 TALLOC_FREE(r
->out
.info
);
5063 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
,
5064 r
->out
.info
, r
->in
.level
);
5065 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5067 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5071 /****************************************************************
5072 _spoolss_StartPagePrinter
5073 ****************************************************************/
5075 WERROR
_spoolss_StartPagePrinter(pipes_struct
*p
,
5076 struct spoolss_StartPagePrinter
*r
)
5078 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5081 DEBUG(3,("_spoolss_StartPagePrinter: "
5082 "Error in startpageprinter printer handle\n"));
5086 Printer
->page_started
= true;
5090 /****************************************************************
5091 _spoolss_EndPagePrinter
5092 ****************************************************************/
5094 WERROR
_spoolss_EndPagePrinter(pipes_struct
*p
,
5095 struct spoolss_EndPagePrinter
*r
)
5099 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5102 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5103 OUR_HANDLE(r
->in
.handle
)));
5107 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5110 Printer
->page_started
= false;
5111 print_job_endpage(snum
, Printer
->jobid
);
5116 /****************************************************************
5117 _spoolss_StartDocPrinter
5118 ****************************************************************/
5120 WERROR
_spoolss_StartDocPrinter(pipes_struct
*p
,
5121 struct spoolss_StartDocPrinter
*r
)
5123 struct spoolss_DocumentInfo1
*info_1
;
5125 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5128 DEBUG(2,("_spoolss_StartDocPrinter: "
5129 "Invalid handle (%s:%u:%u)\n",
5130 OUR_HANDLE(r
->in
.handle
)));
5134 if (r
->in
.level
!= 1) {
5135 return WERR_UNKNOWN_LEVEL
;
5138 info_1
= r
->in
.info
.info1
;
5141 * a nice thing with NT is it doesn't listen to what you tell it.
5142 * when asked to send _only_ RAW datas, it tries to send datas
5145 * So I add checks like in NT Server ...
5148 if (info_1
->datatype
) {
5149 if (strcmp(info_1
->datatype
, "RAW") != 0) {
5151 return WERR_INVALID_DATATYPE
;
5155 /* get the share number of the printer */
5156 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5160 Printer
->jobid
= print_job_start(p
->server_info
, snum
,
5161 info_1
->document_name
,
5162 Printer
->nt_devmode
);
5164 /* An error occured in print_job_start() so return an appropriate
5167 if (Printer
->jobid
== -1) {
5168 return map_werror_from_unix(errno
);
5171 Printer
->document_started
= true;
5172 *r
->out
.job_id
= Printer
->jobid
;
5177 /****************************************************************
5178 _spoolss_EndDocPrinter
5179 ****************************************************************/
5181 WERROR
_spoolss_EndDocPrinter(pipes_struct
*p
,
5182 struct spoolss_EndDocPrinter
*r
)
5184 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5188 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5189 OUR_HANDLE(r
->in
.handle
)));
5193 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5197 Printer
->document_started
= false;
5198 print_job_end(snum
, Printer
->jobid
, NORMAL_CLOSE
);
5199 /* error codes unhandled so far ... */
5204 /****************************************************************
5205 _spoolss_WritePrinter
5206 ****************************************************************/
5208 WERROR
_spoolss_WritePrinter(pipes_struct
*p
,
5209 struct spoolss_WritePrinter
*r
)
5211 ssize_t buffer_written
;
5213 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5216 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5217 OUR_HANDLE(r
->in
.handle
)));
5218 *r
->out
.num_written
= r
->in
._data_size
;
5222 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5225 buffer_written
= print_job_write(snum
, Printer
->jobid
,
5226 (const char *)r
->in
.data
.data
,
5228 (size_t)r
->in
._data_size
);
5229 if (buffer_written
== (ssize_t
)-1) {
5230 *r
->out
.num_written
= 0;
5231 if (errno
== ENOSPC
)
5232 return WERR_NO_SPOOL_SPACE
;
5234 return WERR_ACCESS_DENIED
;
5237 *r
->out
.num_written
= r
->in
._data_size
;
5242 /********************************************************************
5243 * api_spoolss_getprinter
5244 * called from the spoolss dispatcher
5246 ********************************************************************/
5248 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5252 WERROR errcode
= WERR_BADFUNC
;
5253 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5256 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5257 OUR_HANDLE(handle
)));
5261 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5265 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5266 errcode
= print_queue_pause(p
->server_info
, snum
);
5268 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5269 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5270 errcode
= print_queue_resume(p
->server_info
, snum
);
5272 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5273 errcode
= print_queue_purge(p
->server_info
, snum
);
5276 return WERR_UNKNOWN_LEVEL
;
5283 /****************************************************************
5284 _spoolss_AbortPrinter
5285 * From MSDN: "Deletes printer's spool file if printer is configured
5287 ****************************************************************/
5289 WERROR
_spoolss_AbortPrinter(pipes_struct
*p
,
5290 struct spoolss_AbortPrinter
*r
)
5292 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5294 WERROR errcode
= WERR_OK
;
5297 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5298 OUR_HANDLE(r
->in
.handle
)));
5302 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5305 print_job_delete(p
->server_info
, snum
, Printer
->jobid
, &errcode
);
5310 /********************************************************************
5311 * called by spoolss_api_setprinter
5312 * when updating a printer description
5313 ********************************************************************/
5315 static WERROR
update_printer_sec(struct policy_handle
*handle
,
5316 pipes_struct
*p
, struct sec_desc_buf
*secdesc_ctr
)
5318 struct sec_desc_buf
*new_secdesc_ctr
= NULL
, *old_secdesc_ctr
= NULL
;
5322 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5324 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5325 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5326 OUR_HANDLE(handle
)));
5328 result
= WERR_BADFID
;
5333 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5334 result
= WERR_INVALID_PARAM
;
5338 /* Check the user has permissions to change the security
5339 descriptor. By experimentation with two NT machines, the user
5340 requires Full Access to the printer to change security
5343 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5344 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5345 result
= WERR_ACCESS_DENIED
;
5349 /* NT seems to like setting the security descriptor even though
5350 nothing may have actually changed. */
5352 if ( !nt_printing_getsec(p
->mem_ctx
, Printer
->sharename
, &old_secdesc_ctr
)) {
5353 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
5354 result
= WERR_BADFID
;
5358 if (DEBUGLEVEL
>= 10) {
5359 struct security_acl
*the_acl
;
5362 the_acl
= old_secdesc_ctr
->sd
->dacl
;
5363 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5364 PRINTERNAME(snum
), the_acl
->num_aces
));
5366 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5367 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5368 &the_acl
->aces
[i
].trustee
),
5369 the_acl
->aces
[i
].access_mask
));
5372 the_acl
= secdesc_ctr
->sd
->dacl
;
5375 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
5376 PRINTERNAME(snum
), the_acl
->num_aces
));
5378 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
5379 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5380 &the_acl
->aces
[i
].trustee
),
5381 the_acl
->aces
[i
].access_mask
));
5384 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
5388 new_secdesc_ctr
= sec_desc_merge_buf(p
->mem_ctx
, secdesc_ctr
, old_secdesc_ctr
);
5389 if (!new_secdesc_ctr
) {
5390 result
= WERR_NOMEM
;
5394 if (security_descriptor_equal(new_secdesc_ctr
->sd
, old_secdesc_ctr
->sd
)) {
5399 result
= nt_printing_setsec(Printer
->sharename
, new_secdesc_ctr
);
5406 /********************************************************************
5407 Canonicalize printer info from a client
5409 ATTN: It does not matter what we set the servername to hear
5410 since we do the necessary work in get_a_printer() to set it to
5411 the correct value based on what the client sent in the
5412 _spoolss_open_printer_ex().
5413 ********************************************************************/
5415 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2
*info
, int snum
)
5417 fstring printername
;
5420 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
5421 "portname=%s drivername=%s comment=%s location=%s\n",
5422 info
->servername
, info
->printername
, info
->sharename
,
5423 info
->portname
, info
->drivername
, info
->comment
, info
->location
));
5425 /* we force some elements to "correct" values */
5426 slprintf(info
->servername
, sizeof(info
->servername
)-1, "\\\\%s", global_myname());
5427 fstrcpy(info
->sharename
, lp_servicename(snum
));
5429 /* check to see if we allow printername != sharename */
5431 if ( lp_force_printername(snum
) ) {
5432 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5433 global_myname(), info
->sharename
);
5436 /* make sure printername is in \\server\printername format */
5438 fstrcpy( printername
, info
->printername
);
5440 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
5441 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
5445 slprintf(info
->printername
, sizeof(info
->printername
)-1, "\\\\%s\\%s",
5446 global_myname(), p
);
5449 info
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
5450 info
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
5457 /****************************************************************************
5458 ****************************************************************************/
5460 static WERROR
add_port_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, const char *portname
, const char *uri
)
5462 char *cmd
= lp_addport_cmd();
5463 char *command
= NULL
;
5465 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5466 bool is_print_op
= false;
5469 return WERR_ACCESS_DENIED
;
5472 command
= talloc_asprintf(ctx
,
5473 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
5479 is_print_op
= user_has_privileges( token
, &se_printop
);
5481 DEBUG(10,("Running [%s]\n", command
));
5483 /********* BEGIN SePrintOperatorPrivilege **********/
5488 ret
= smbrun(command
, NULL
);
5493 /********* END SePrintOperatorPrivilege **********/
5495 DEBUGADD(10,("returned [%d]\n", ret
));
5497 TALLOC_FREE(command
);
5500 return WERR_ACCESS_DENIED
;
5506 /****************************************************************************
5507 ****************************************************************************/
5509 bool add_printer_hook(TALLOC_CTX
*ctx
, NT_USER_TOKEN
*token
, NT_PRINTER_INFO_LEVEL
*printer
)
5511 char *cmd
= lp_addprinter_cmd();
5513 char *command
= NULL
;
5517 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
5518 bool is_print_op
= false;
5519 char *remote_machine
= talloc_strdup(ctx
, "%m");
5521 if (!remote_machine
) {
5524 remote_machine
= talloc_sub_basic(ctx
,
5525 current_user_info
.smb_name
,
5526 current_user_info
.domain
,
5528 if (!remote_machine
) {
5532 command
= talloc_asprintf(ctx
,
5533 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
5534 cmd
, printer
->info_2
->printername
, printer
->info_2
->sharename
,
5535 printer
->info_2
->portname
, printer
->info_2
->drivername
,
5536 printer
->info_2
->location
, printer
->info_2
->comment
, remote_machine
);
5542 is_print_op
= user_has_privileges( token
, &se_printop
);
5544 DEBUG(10,("Running [%s]\n", command
));
5546 /********* BEGIN SePrintOperatorPrivilege **********/
5551 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
5552 /* Tell everyone we updated smb.conf. */
5553 message_send_all(smbd_messaging_context(),
5554 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
5560 /********* END SePrintOperatorPrivilege **********/
5562 DEBUGADD(10,("returned [%d]\n", ret
));
5564 TALLOC_FREE(command
);
5565 TALLOC_FREE(remote_machine
);
5573 /* reload our services immediately */
5575 reload_services(false);
5579 /* Get lines and convert them back to dos-codepage */
5580 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
5581 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
5584 /* Set the portname to what the script says the portname should be. */
5585 /* but don't require anything to be return from the script exit a good error code */
5588 /* Set the portname to what the script says the portname should be. */
5589 strncpy(printer
->info_2
->portname
, qlines
[0], sizeof(printer
->info_2
->portname
));
5590 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
5593 TALLOC_FREE(qlines
);
5598 /********************************************************************
5599 * Called by spoolss_api_setprinter
5600 * when updating a printer description.
5601 ********************************************************************/
5603 static WERROR
update_printer(pipes_struct
*p
, struct policy_handle
*handle
,
5604 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
5605 struct spoolss_DeviceMode
*devmode
)
5608 NT_PRINTER_INFO_LEVEL
*printer
= NULL
, *old_printer
= NULL
;
5609 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5614 DEBUG(8,("update_printer\n"));
5619 result
= WERR_BADFID
;
5623 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
5624 result
= WERR_BADFID
;
5628 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
))) ||
5629 (!W_ERROR_IS_OK(get_a_printer(Printer
, &old_printer
, 2, lp_const_servicename(snum
))))) {
5630 result
= WERR_BADFID
;
5634 DEBUGADD(8,("Converting info_2 struct\n"));
5637 * convert_printer_info converts the incoming
5638 * info from the client and overwrites the info
5639 * just read from the tdb in the pointer 'printer'.
5642 if (!convert_printer_info(info_ctr
, printer
)) {
5643 result
= WERR_NOMEM
;
5648 /* we have a valid devmode
5649 convert it and link it*/
5651 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5652 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5653 &printer
->info_2
->devmode
)) {
5654 result
= WERR_NOMEM
;
5659 /* Do sanity check on the requested changes for Samba */
5661 if (!check_printer_ok(printer
->info_2
, snum
)) {
5662 result
= WERR_INVALID_PARAM
;
5666 /* FIXME!!! If the driver has changed we really should verify that
5667 it is installed before doing much else --jerry */
5669 /* Check calling user has permission to update printer description */
5671 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5672 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5673 result
= WERR_ACCESS_DENIED
;
5677 /* Call addprinter hook */
5678 /* Check changes to see if this is really needed */
5680 if ( *lp_addprinter_cmd()
5681 && (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
)
5682 || !strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)
5683 || !strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)
5684 || !strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) )
5686 /* add_printer_hook() will call reload_services() */
5688 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
5690 result
= WERR_ACCESS_DENIED
;
5696 * When a *new* driver is bound to a printer, the drivername is used to
5697 * lookup previously saved driver initialization info, which is then
5698 * bound to the printer, simulating what happens in the Windows arch.
5700 if (!strequal(printer
->info_2
->drivername
, old_printer
->info_2
->drivername
))
5702 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
5703 printer
->info_2
->drivername
));
5705 notify_printer_driver(snum
, printer
->info_2
->drivername
);
5709 * flag which changes actually occured. This is a small subset of
5710 * all the possible changes. We also have to update things in the
5714 if (!strequal(printer
->info_2
->comment
, old_printer
->info_2
->comment
)) {
5715 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->comment
);
5716 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "description",
5717 REG_SZ
, buffer
.data
, buffer
.length
);
5719 notify_printer_comment(snum
, printer
->info_2
->comment
);
5722 if (!strequal(printer
->info_2
->sharename
, old_printer
->info_2
->sharename
)) {
5723 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->sharename
);
5724 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shareName",
5725 REG_SZ
, buffer
.data
, buffer
.length
);
5727 notify_printer_sharename(snum
, printer
->info_2
->sharename
);
5730 if (!strequal(printer
->info_2
->printername
, old_printer
->info_2
->printername
)) {
5733 if ( (pname
= strchr_m( printer
->info_2
->printername
+2, '\\' )) != NULL
)
5736 pname
= printer
->info_2
->printername
;
5739 push_reg_sz(talloc_tos(), &buffer
, pname
);
5740 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "printerName",
5741 REG_SZ
, buffer
.data
, buffer
.length
);
5743 notify_printer_printername( snum
, pname
);
5746 if (!strequal(printer
->info_2
->portname
, old_printer
->info_2
->portname
)) {
5747 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->portname
);
5748 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "portName",
5749 REG_SZ
, buffer
.data
, buffer
.length
);
5751 notify_printer_port(snum
, printer
->info_2
->portname
);
5754 if (!strequal(printer
->info_2
->location
, old_printer
->info_2
->location
)) {
5755 push_reg_sz(talloc_tos(), &buffer
, printer
->info_2
->location
);
5756 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "location",
5757 REG_SZ
, buffer
.data
, buffer
.length
);
5759 notify_printer_location(snum
, printer
->info_2
->location
);
5762 /* here we need to update some more DsSpooler keys */
5763 /* uNCName, serverName, shortServerName */
5765 push_reg_sz(talloc_tos(), &buffer
, global_myname());
5766 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "serverName",
5767 REG_SZ
, buffer
.data
, buffer
.length
);
5768 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "shortServerName",
5769 REG_SZ
, buffer
.data
, buffer
.length
);
5771 slprintf( asc_buffer
, sizeof(asc_buffer
)-1, "\\\\%s\\%s",
5772 global_myname(), printer
->info_2
->sharename
);
5773 push_reg_sz(talloc_tos(), &buffer
, asc_buffer
);
5774 set_printer_dataex( printer
, SPOOL_DSSPOOLER_KEY
, "uNCName",
5775 REG_SZ
, buffer
.data
, buffer
.length
);
5777 /* Update printer info */
5778 result
= mod_a_printer(printer
, 2);
5781 free_a_printer(&printer
, 2);
5782 free_a_printer(&old_printer
, 2);
5788 /****************************************************************************
5789 ****************************************************************************/
5790 static WERROR
publish_or_unpublish_printer(pipes_struct
*p
,
5791 struct policy_handle
*handle
,
5792 struct spoolss_SetPrinterInfo7
*info7
)
5796 Printer_entry
*Printer
;
5798 if ( lp_security() != SEC_ADS
) {
5799 return WERR_UNKNOWN_LEVEL
;
5802 Printer
= find_printer_index_by_hnd(p
, handle
);
5804 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
5809 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5812 nt_printer_publish(Printer
, snum
, info7
->action
);
5816 return WERR_UNKNOWN_LEVEL
;
5820 /********************************************************************
5821 ********************************************************************/
5823 static WERROR
update_printer_devmode(pipes_struct
*p
, struct policy_handle
*handle
,
5824 struct spoolss_DeviceMode
*devmode
)
5827 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
5828 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, handle
);
5831 DEBUG(8,("update_printer_devmode\n"));
5836 result
= WERR_BADFID
;
5840 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
5841 result
= WERR_BADFID
;
5845 if (!W_ERROR_IS_OK(get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
)))) {
5846 result
= WERR_BADFID
;
5851 /* we have a valid devmode
5852 convert it and link it*/
5854 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
5855 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
5856 &printer
->info_2
->devmode
)) {
5857 result
= WERR_NOMEM
;
5862 /* Check calling user has permission to update printer description */
5864 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5865 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
5866 result
= WERR_ACCESS_DENIED
;
5871 /* Update printer info */
5872 result
= mod_a_printer(printer
, 2);
5875 free_a_printer(&printer
, 2);
5881 /****************************************************************
5883 ****************************************************************/
5885 WERROR
_spoolss_SetPrinter(pipes_struct
*p
,
5886 struct spoolss_SetPrinter
*r
)
5890 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5893 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
5894 OUR_HANDLE(r
->in
.handle
)));
5898 /* check the level */
5899 switch (r
->in
.info_ctr
->level
) {
5901 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
5903 result
= update_printer(p
, r
->in
.handle
,
5905 r
->in
.devmode_ctr
->devmode
);
5906 if (!W_ERROR_IS_OK(result
))
5908 if (r
->in
.secdesc_ctr
->sd
)
5909 result
= update_printer_sec(r
->in
.handle
, p
,
5913 return update_printer_sec(r
->in
.handle
, p
,
5916 return publish_or_unpublish_printer(p
, r
->in
.handle
,
5917 r
->in
.info_ctr
->info
.info7
);
5919 return update_printer_devmode(p
, r
->in
.handle
,
5920 r
->in
.devmode_ctr
->devmode
);
5922 return WERR_UNKNOWN_LEVEL
;
5926 /****************************************************************
5927 _spoolss_FindClosePrinterNotify
5928 ****************************************************************/
5930 WERROR
_spoolss_FindClosePrinterNotify(pipes_struct
*p
,
5931 struct spoolss_FindClosePrinterNotify
*r
)
5933 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5936 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
5937 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
5941 if (Printer
->notify
.client_connected
== true) {
5944 if ( Printer
->printer_type
== SPLHND_SERVER
)
5946 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
5947 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
5950 srv_spoolss_replycloseprinter(snum
, &Printer
->notify
.client_hnd
);
5953 Printer
->notify
.flags
=0;
5954 Printer
->notify
.options
=0;
5955 Printer
->notify
.localmachine
[0]='\0';
5956 Printer
->notify
.printerlocal
=0;
5957 TALLOC_FREE(Printer
->notify
.option
);
5958 Printer
->notify
.client_connected
= false;
5963 /****************************************************************
5965 ****************************************************************/
5967 WERROR
_spoolss_AddJob(pipes_struct
*p
,
5968 struct spoolss_AddJob
*r
)
5970 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5971 return WERR_INVALID_PARAM
;
5974 /* this is what a NT server returns for AddJob. AddJob must fail on
5975 * non-local printers */
5977 if (r
->in
.level
!= 1) {
5978 return WERR_UNKNOWN_LEVEL
;
5981 return WERR_INVALID_PARAM
;
5984 /****************************************************************************
5986 ****************************************************************************/
5988 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
5989 struct spoolss_JobInfo1
*r
,
5990 const print_queue_struct
*queue
,
5991 int position
, int snum
,
5992 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
5996 t
= gmtime(&queue
->time
);
5998 r
->job_id
= queue
->job
;
6000 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6001 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6002 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6003 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6004 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6005 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6006 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6007 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6008 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6009 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6010 r
->text_status
= talloc_strdup(mem_ctx
, "");
6011 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6013 r
->status
= nt_printj_status(queue
->status
);
6014 r
->priority
= queue
->priority
;
6015 r
->position
= position
;
6016 r
->total_pages
= queue
->page_count
;
6017 r
->pages_printed
= 0; /* ??? */
6019 init_systemtime(&r
->submitted
, t
);
6024 /****************************************************************************
6026 ****************************************************************************/
6028 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6029 struct spoolss_JobInfo2
*r
,
6030 const print_queue_struct
*queue
,
6031 int position
, int snum
,
6032 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6033 struct spoolss_DeviceMode
*devmode
)
6037 t
= gmtime(&queue
->time
);
6039 r
->job_id
= queue
->job
;
6041 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6042 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6043 r
->server_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->servername
);
6044 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6045 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6046 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6047 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6048 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6049 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6050 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6051 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6052 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6053 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6054 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6055 r
->parameters
= talloc_strdup(mem_ctx
, "");
6056 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6057 r
->driver_name
= talloc_strdup(mem_ctx
, ntprinter
->info_2
->drivername
);
6058 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6060 r
->devmode
= devmode
;
6062 r
->text_status
= talloc_strdup(mem_ctx
, "");
6063 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6067 r
->status
= nt_printj_status(queue
->status
);
6068 r
->priority
= queue
->priority
;
6069 r
->position
= position
;
6072 r
->total_pages
= queue
->page_count
;
6073 r
->size
= queue
->size
;
6074 init_systemtime(&r
->submitted
, t
);
6076 r
->pages_printed
= 0; /* ??? */
6081 /****************************************************************************
6083 ****************************************************************************/
6085 static WERROR
fill_job_info3(TALLOC_CTX
*mem_ctx
,
6086 struct spoolss_JobInfo3
*r
,
6087 const print_queue_struct
*queue
,
6088 const print_queue_struct
*next_queue
,
6089 int position
, int snum
,
6090 const NT_PRINTER_INFO_LEVEL
*ntprinter
)
6092 r
->job_id
= queue
->job
;
6095 r
->next_job_id
= next_queue
->job
;
6102 /****************************************************************************
6103 Enumjobs at level 1.
6104 ****************************************************************************/
6106 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6107 const print_queue_struct
*queue
,
6108 uint32_t num_queues
, int snum
,
6109 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6110 union spoolss_JobInfo
**info_p
,
6113 union spoolss_JobInfo
*info
;
6115 WERROR result
= WERR_OK
;
6117 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6118 W_ERROR_HAVE_NO_MEMORY(info
);
6120 *count
= num_queues
;
6122 for (i
=0; i
<*count
; i
++) {
6123 result
= fill_job_info1(info
,
6129 if (!W_ERROR_IS_OK(result
)) {
6135 if (!W_ERROR_IS_OK(result
)) {
6146 /****************************************************************************
6147 Enumjobs at level 2.
6148 ****************************************************************************/
6150 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6151 const print_queue_struct
*queue
,
6152 uint32_t num_queues
, int snum
,
6153 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6154 union spoolss_JobInfo
**info_p
,
6157 union spoolss_JobInfo
*info
;
6159 WERROR result
= WERR_OK
;
6161 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6162 W_ERROR_HAVE_NO_MEMORY(info
);
6164 *count
= num_queues
;
6166 for (i
=0; i
<*count
; i
++) {
6168 struct spoolss_DeviceMode
*devmode
;
6170 devmode
= construct_dev_mode(info
, lp_const_servicename(snum
));
6172 result
= WERR_NOMEM
;
6176 result
= fill_job_info2(info
,
6183 if (!W_ERROR_IS_OK(result
)) {
6189 if (!W_ERROR_IS_OK(result
)) {
6200 /****************************************************************************
6201 Enumjobs at level 3.
6202 ****************************************************************************/
6204 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
6205 const print_queue_struct
*queue
,
6206 uint32_t num_queues
, int snum
,
6207 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
6208 union spoolss_JobInfo
**info_p
,
6211 union spoolss_JobInfo
*info
;
6213 WERROR result
= WERR_OK
;
6215 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6216 W_ERROR_HAVE_NO_MEMORY(info
);
6218 *count
= num_queues
;
6220 for (i
=0; i
<*count
; i
++) {
6221 const print_queue_struct
*next_queue
= NULL
;
6224 next_queue
= &queue
[i
+1];
6227 result
= fill_job_info3(info
,
6234 if (!W_ERROR_IS_OK(result
)) {
6240 if (!W_ERROR_IS_OK(result
)) {
6251 /****************************************************************
6253 ****************************************************************/
6255 WERROR
_spoolss_EnumJobs(pipes_struct
*p
,
6256 struct spoolss_EnumJobs
*r
)
6259 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
6261 print_status_struct prt_status
;
6262 print_queue_struct
*queue
= NULL
;
6265 /* that's an [in out] buffer */
6267 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6268 return WERR_INVALID_PARAM
;
6271 DEBUG(4,("_spoolss_EnumJobs\n"));
6275 *r
->out
.info
= NULL
;
6277 /* lookup the printer snum and tdb entry */
6279 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6283 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
6284 if (!W_ERROR_IS_OK(result
)) {
6288 count
= print_queue_status(snum
, &queue
, &prt_status
);
6289 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
6290 count
, prt_status
.status
, prt_status
.message
));
6294 free_a_printer(&ntprinter
, 2);
6298 switch (r
->in
.level
) {
6300 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
6301 ntprinter
, r
->out
.info
, r
->out
.count
);
6304 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
6305 ntprinter
, r
->out
.info
, r
->out
.count
);
6308 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
6309 ntprinter
, r
->out
.info
, r
->out
.count
);
6312 result
= WERR_UNKNOWN_LEVEL
;
6317 free_a_printer(&ntprinter
, 2);
6319 if (!W_ERROR_IS_OK(result
)) {
6323 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6325 *r
->out
.info
, r
->in
.level
,
6327 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6328 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6330 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6333 /****************************************************************
6334 _spoolss_ScheduleJob
6335 ****************************************************************/
6337 WERROR
_spoolss_ScheduleJob(pipes_struct
*p
,
6338 struct spoolss_ScheduleJob
*r
)
6343 /****************************************************************
6344 ****************************************************************/
6346 static WERROR
spoolss_setjob_1(TALLOC_CTX
*mem_ctx
,
6347 const char *printer_name
,
6349 struct spoolss_SetJobInfo1
*r
)
6353 if (!print_job_get_name(mem_ctx
, printer_name
, job_id
, &old_doc_name
)) {
6357 if (strequal(old_doc_name
, r
->document_name
)) {
6361 if (!print_job_set_name(printer_name
, job_id
, r
->document_name
)) {
6368 /****************************************************************
6370 ****************************************************************/
6372 WERROR
_spoolss_SetJob(pipes_struct
*p
,
6373 struct spoolss_SetJob
*r
)
6376 WERROR errcode
= WERR_BADFUNC
;
6378 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6382 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
6383 return WERR_INVALID_PRINTER_NAME
;
6386 switch (r
->in
.command
) {
6387 case SPOOLSS_JOB_CONTROL_CANCEL
:
6388 case SPOOLSS_JOB_CONTROL_DELETE
:
6389 if (print_job_delete(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6393 case SPOOLSS_JOB_CONTROL_PAUSE
:
6394 if (print_job_pause(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6398 case SPOOLSS_JOB_CONTROL_RESTART
:
6399 case SPOOLSS_JOB_CONTROL_RESUME
:
6400 if (print_job_resume(p
->server_info
, snum
, r
->in
.job_id
, &errcode
)) {
6408 return WERR_UNKNOWN_LEVEL
;
6411 if (!W_ERROR_IS_OK(errcode
)) {
6415 if (r
->in
.ctr
== NULL
) {
6419 switch (r
->in
.ctr
->level
) {
6421 errcode
= spoolss_setjob_1(p
->mem_ctx
, lp_const_servicename(snum
),
6423 r
->in
.ctr
->info
.info1
);
6429 return WERR_UNKNOWN_LEVEL
;
6435 /****************************************************************************
6436 Enumerates all printer drivers by level and architecture.
6437 ****************************************************************************/
6439 static WERROR
enumprinterdrivers_level_by_architecture(TALLOC_CTX
*mem_ctx
,
6440 const char *servername
,
6441 const char *architecture
,
6443 union spoolss_DriverInfo
**info_p
,
6449 fstring
*list
= NULL
;
6450 struct spoolss_DriverInfo8
*driver
;
6451 union spoolss_DriverInfo
*info
= NULL
;
6453 WERROR result
= WERR_OK
;
6458 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
6460 ndrivers
= get_ntdrivers(&list
, architecture
, version
);
6461 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
6462 ndrivers
, architecture
, version
));
6464 if (ndrivers
== -1) {
6465 result
= WERR_NOMEM
;
6469 if (ndrivers
!= 0) {
6470 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
6471 union spoolss_DriverInfo
,
6474 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
6475 "failed to enlarge driver info buffer!\n"));
6476 result
= WERR_NOMEM
;
6481 for (i
=0; i
<ndrivers
; i
++) {
6482 DEBUGADD(5,("\tdriver: [%s]\n", list
[i
]));
6483 ZERO_STRUCT(driver
);
6484 result
= get_a_printer_driver(mem_ctx
, &driver
, list
[i
],
6485 architecture
, version
);
6486 if (!W_ERROR_IS_OK(result
)) {
6492 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
6493 driver
, servername
);
6496 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
6497 driver
, servername
);
6500 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
6501 driver
, servername
);
6504 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
6505 driver
, servername
);
6508 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
6509 driver
, servername
);
6512 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
6513 driver
, servername
);
6516 result
= fill_printer_driver_info8(info
, &info
[count
+i
].info8
,
6517 driver
, servername
);
6520 result
= WERR_UNKNOWN_LEVEL
;
6524 free_a_printer_driver(driver
);
6526 if (!W_ERROR_IS_OK(result
)) {
6538 if (!W_ERROR_IS_OK(result
)) {
6549 /****************************************************************************
6550 Enumerates all printer drivers by level.
6551 ****************************************************************************/
6553 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
6554 const char *servername
,
6555 const char *architecture
,
6557 union spoolss_DriverInfo
**info_p
,
6561 WERROR result
= WERR_OK
;
6563 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_ALL
)) {
6565 for (a
=0; archi_table
[a
].long_archi
!= NULL
; a
++) {
6567 union spoolss_DriverInfo
*info
= NULL
;
6570 result
= enumprinterdrivers_level_by_architecture(mem_ctx
,
6572 archi_table
[a
].long_archi
,
6576 if (!W_ERROR_IS_OK(result
)) {
6580 for (i
=0; i
< count
; i
++) {
6581 ADD_TO_ARRAY(mem_ctx
, union spoolss_DriverInfo
,
6582 info
[i
], info_p
, count_p
);
6589 return enumprinterdrivers_level_by_architecture(mem_ctx
,
6597 /****************************************************************
6598 _spoolss_EnumPrinterDrivers
6599 ****************************************************************/
6601 WERROR
_spoolss_EnumPrinterDrivers(pipes_struct
*p
,
6602 struct spoolss_EnumPrinterDrivers
*r
)
6604 const char *cservername
;
6607 /* that's an [in out] buffer */
6609 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6610 return WERR_INVALID_PARAM
;
6613 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
6617 *r
->out
.info
= NULL
;
6619 cservername
= canon_servername(r
->in
.server
);
6621 if (!is_myname_or_ipaddr(cservername
)) {
6622 return WERR_UNKNOWN_PRINTER_DRIVER
;
6625 result
= enumprinterdrivers_level(p
->mem_ctx
, cservername
,
6630 if (!W_ERROR_IS_OK(result
)) {
6634 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6635 spoolss_EnumPrinterDrivers
,
6636 *r
->out
.info
, r
->in
.level
,
6638 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6639 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6641 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6644 /****************************************************************************
6645 ****************************************************************************/
6647 static WERROR
fill_form_info_1(TALLOC_CTX
*mem_ctx
,
6648 struct spoolss_FormInfo1
*r
,
6649 const nt_forms_struct
*form
)
6651 r
->form_name
= talloc_strdup(mem_ctx
, form
->name
);
6652 W_ERROR_HAVE_NO_MEMORY(r
->form_name
);
6654 r
->flags
= form
->flag
;
6655 r
->size
.width
= form
->width
;
6656 r
->size
.height
= form
->length
;
6657 r
->area
.left
= form
->left
;
6658 r
->area
.top
= form
->top
;
6659 r
->area
.right
= form
->right
;
6660 r
->area
.bottom
= form
->bottom
;
6665 /****************************************************************
6666 spoolss_enumforms_level1
6667 ****************************************************************/
6669 static WERROR
spoolss_enumforms_level1(TALLOC_CTX
*mem_ctx
,
6670 const nt_forms_struct
*builtin_forms
,
6671 uint32_t num_builtin_forms
,
6672 const nt_forms_struct
*user_forms
,
6673 uint32_t num_user_forms
,
6674 union spoolss_FormInfo
**info_p
,
6677 union spoolss_FormInfo
*info
;
6678 WERROR result
= WERR_OK
;
6681 *count
= num_builtin_forms
+ num_user_forms
;
6683 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_FormInfo
, *count
);
6684 W_ERROR_HAVE_NO_MEMORY(info
);
6686 /* construct the list of form structures */
6687 for (i
=0; i
<num_builtin_forms
; i
++) {
6688 DEBUGADD(6,("Filling builtin form number [%d]\n",i
));
6689 result
= fill_form_info_1(info
, &info
[i
].info1
,
6691 if (!W_ERROR_IS_OK(result
)) {
6696 for (i
=0; i
<num_user_forms
; i
++) {
6697 DEBUGADD(6,("Filling user form number [%d]\n",i
));
6698 result
= fill_form_info_1(info
, &info
[i
+num_builtin_forms
].info1
,
6700 if (!W_ERROR_IS_OK(result
)) {
6706 if (!W_ERROR_IS_OK(result
)) {
6717 /****************************************************************
6719 ****************************************************************/
6721 WERROR
_spoolss_EnumForms(pipes_struct
*p
,
6722 struct spoolss_EnumForms
*r
)
6725 nt_forms_struct
*user_forms
= NULL
;
6726 nt_forms_struct
*builtin_forms
= NULL
;
6727 uint32_t num_user_forms
;
6728 uint32_t num_builtin_forms
;
6732 *r
->out
.info
= NULL
;
6734 /* that's an [in out] buffer */
6736 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
6737 return WERR_INVALID_PARAM
;
6740 DEBUG(4,("_spoolss_EnumForms\n"));
6741 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
6742 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
6744 num_builtin_forms
= get_builtin_ntforms(&builtin_forms
);
6745 DEBUGADD(5,("Number of builtin forms [%d]\n", num_builtin_forms
));
6746 num_user_forms
= get_ntforms(&user_forms
);
6747 DEBUGADD(5,("Number of user forms [%d]\n", num_user_forms
));
6749 if (num_user_forms
+ num_builtin_forms
== 0) {
6750 SAFE_FREE(builtin_forms
);
6751 SAFE_FREE(user_forms
);
6752 return WERR_NO_MORE_ITEMS
;
6755 switch (r
->in
.level
) {
6757 result
= spoolss_enumforms_level1(p
->mem_ctx
,
6766 result
= WERR_UNKNOWN_LEVEL
;
6770 SAFE_FREE(user_forms
);
6771 SAFE_FREE(builtin_forms
);
6773 if (!W_ERROR_IS_OK(result
)) {
6777 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
6779 *r
->out
.info
, r
->in
.level
,
6781 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
6782 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
6784 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6787 /****************************************************************
6788 ****************************************************************/
6790 static WERROR
find_form_byname(const char *name
,
6791 nt_forms_struct
*form
)
6793 nt_forms_struct
*list
= NULL
;
6794 int num_forms
= 0, i
= 0;
6796 if (get_a_builtin_ntform_by_string(name
, form
)) {
6800 num_forms
= get_ntforms(&list
);
6801 DEBUGADD(5,("Number of forms [%d]\n", num_forms
));
6803 if (num_forms
== 0) {
6807 /* Check if the requested name is in the list of form structures */
6808 for (i
= 0; i
< num_forms
; i
++) {
6810 DEBUG(4,("checking form %s (want %s)\n", list
[i
].name
, name
));
6812 if (strequal(name
, list
[i
].name
)) {
6813 DEBUGADD(6,("Found form %s number [%d]\n", name
, i
));
6825 /****************************************************************
6827 ****************************************************************/
6829 WERROR
_spoolss_GetForm(pipes_struct
*p
,
6830 struct spoolss_GetForm
*r
)
6833 nt_forms_struct form
;
6835 /* that's an [in out] buffer */
6837 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6838 return WERR_INVALID_PARAM
;
6841 DEBUG(4,("_spoolss_GetForm\n"));
6842 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
6843 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
6845 result
= find_form_byname(r
->in
.form_name
, &form
);
6846 if (!W_ERROR_IS_OK(result
)) {
6847 TALLOC_FREE(r
->out
.info
);
6851 switch (r
->in
.level
) {
6853 result
= fill_form_info_1(p
->mem_ctx
,
6854 &r
->out
.info
->info1
,
6859 result
= WERR_UNKNOWN_LEVEL
;
6863 if (!W_ERROR_IS_OK(result
)) {
6864 TALLOC_FREE(r
->out
.info
);
6868 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
,
6869 r
->out
.info
, r
->in
.level
);
6870 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
6872 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
6875 /****************************************************************************
6876 ****************************************************************************/
6878 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
6879 struct spoolss_PortInfo1
*r
,
6882 r
->port_name
= talloc_strdup(mem_ctx
, name
);
6883 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
6888 /****************************************************************************
6889 TODO: This probably needs distinguish between TCP/IP and Local ports
6891 ****************************************************************************/
6893 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
6894 struct spoolss_PortInfo2
*r
,
6897 r
->port_name
= talloc_strdup(mem_ctx
, name
);
6898 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
6900 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
6901 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
6903 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
6904 W_ERROR_HAVE_NO_MEMORY(r
->description
);
6906 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
6913 /****************************************************************************
6914 wrapper around the enumer ports command
6915 ****************************************************************************/
6917 static WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
6919 char *cmd
= lp_enumports_cmd();
6920 char **qlines
= NULL
;
6921 char *command
= NULL
;
6929 /* if no hook then just fill in the default port */
6932 if (!(qlines
= TALLOC_ARRAY( NULL
, char*, 2 ))) {
6935 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
6936 TALLOC_FREE(qlines
);
6943 /* we have a valid enumport command */
6945 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
6950 DEBUG(10,("Running [%s]\n", command
));
6951 ret
= smbrun(command
, &fd
);
6952 DEBUG(10,("Returned [%d]\n", ret
));
6953 TALLOC_FREE(command
);
6958 return WERR_ACCESS_DENIED
;
6962 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
6963 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6973 /****************************************************************************
6975 ****************************************************************************/
6977 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
6978 union spoolss_PortInfo
**info_p
,
6981 union spoolss_PortInfo
*info
= NULL
;
6983 WERROR result
= WERR_OK
;
6984 char **qlines
= NULL
;
6987 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
6988 if (!W_ERROR_IS_OK(result
)) {
6993 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
6995 DEBUG(10,("Returning WERR_NOMEM\n"));
6996 result
= WERR_NOMEM
;
7000 for (i
=0; i
<numlines
; i
++) {
7001 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7002 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7003 if (!W_ERROR_IS_OK(result
)) {
7008 TALLOC_FREE(qlines
);
7011 if (!W_ERROR_IS_OK(result
)) {
7013 TALLOC_FREE(qlines
);
7025 /****************************************************************************
7027 ****************************************************************************/
7029 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7030 union spoolss_PortInfo
**info_p
,
7033 union spoolss_PortInfo
*info
= NULL
;
7035 WERROR result
= WERR_OK
;
7036 char **qlines
= NULL
;
7039 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7040 if (!W_ERROR_IS_OK(result
)) {
7045 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7047 DEBUG(10,("Returning WERR_NOMEM\n"));
7048 result
= WERR_NOMEM
;
7052 for (i
=0; i
<numlines
; i
++) {
7053 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7054 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7055 if (!W_ERROR_IS_OK(result
)) {
7060 TALLOC_FREE(qlines
);
7063 if (!W_ERROR_IS_OK(result
)) {
7065 TALLOC_FREE(qlines
);
7077 /****************************************************************
7079 ****************************************************************/
7081 WERROR
_spoolss_EnumPorts(pipes_struct
*p
,
7082 struct spoolss_EnumPorts
*r
)
7086 /* that's an [in out] buffer */
7088 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7089 return WERR_INVALID_PARAM
;
7092 DEBUG(4,("_spoolss_EnumPorts\n"));
7096 *r
->out
.info
= NULL
;
7098 switch (r
->in
.level
) {
7100 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7104 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7108 return WERR_UNKNOWN_LEVEL
;
7111 if (!W_ERROR_IS_OK(result
)) {
7115 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7117 *r
->out
.info
, r
->in
.level
,
7119 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7120 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7122 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7125 /****************************************************************************
7126 ****************************************************************************/
7128 static WERROR
spoolss_addprinterex_level_2(pipes_struct
*p
,
7130 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7131 struct spoolss_DeviceMode
*devmode
,
7132 struct security_descriptor
*sec_desc
,
7133 struct spoolss_UserLevelCtr
*user_ctr
,
7134 struct policy_handle
*handle
)
7136 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7139 WERROR err
= WERR_OK
;
7141 if ( !(printer
= TALLOC_ZERO_P(NULL
, NT_PRINTER_INFO_LEVEL
)) ) {
7142 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7146 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7147 if (!convert_printer_info(info_ctr
, printer
)) {
7148 free_a_printer(&printer
, 2);
7152 /* samba does not have a concept of local, non-shared printers yet, so
7153 * make sure we always setup sharename - gd */
7154 if ((printer
->info_2
->sharename
[0] == '\0') && (printer
->info_2
->printername
!= '\0')) {
7155 DEBUG(5, ("spoolss_addprinterex_level_2: "
7156 "no sharename has been set, setting printername %s as sharename\n",
7157 printer
->info_2
->printername
));
7158 fstrcpy(printer
->info_2
->sharename
, printer
->info_2
->printername
);
7161 /* check to see if the printer already exists */
7163 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) != -1) {
7164 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7165 printer
->info_2
->sharename
));
7166 free_a_printer(&printer
, 2);
7167 return WERR_PRINTER_ALREADY_EXISTS
;
7170 if (!lp_force_printername(GLOBAL_SECTION_SNUM
)) {
7171 if ((snum
= print_queue_snum(printer
->info_2
->printername
)) != -1) {
7172 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7173 printer
->info_2
->printername
));
7174 free_a_printer(&printer
, 2);
7175 return WERR_PRINTER_ALREADY_EXISTS
;
7179 /* validate printer info struct */
7180 if (!info_ctr
->info
.info2
->printername
||
7181 strlen(info_ctr
->info
.info2
->printername
) == 0) {
7182 free_a_printer(&printer
,2);
7183 return WERR_INVALID_PRINTER_NAME
;
7185 if (!info_ctr
->info
.info2
->portname
||
7186 strlen(info_ctr
->info
.info2
->portname
) == 0) {
7187 free_a_printer(&printer
,2);
7188 return WERR_UNKNOWN_PORT
;
7190 if (!info_ctr
->info
.info2
->drivername
||
7191 strlen(info_ctr
->info
.info2
->drivername
) == 0) {
7192 free_a_printer(&printer
,2);
7193 return WERR_UNKNOWN_PRINTER_DRIVER
;
7195 if (!info_ctr
->info
.info2
->printprocessor
||
7196 strlen(info_ctr
->info
.info2
->printprocessor
) == 0) {
7197 free_a_printer(&printer
,2);
7198 return WERR_UNKNOWN_PRINTPROCESSOR
;
7201 /* FIXME!!! smbd should check to see if the driver is installed before
7202 trying to add a printer like this --jerry */
7204 if (*lp_addprinter_cmd() ) {
7205 if ( !add_printer_hook(p
->mem_ctx
, p
->server_info
->ptok
,
7207 free_a_printer(&printer
,2);
7208 return WERR_ACCESS_DENIED
;
7211 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7212 "smb.conf parameter \"addprinter command\" is defined. This"
7213 "parameter must exist for this call to succeed\n",
7214 printer
->info_2
->sharename
));
7217 /* use our primary netbios name since get_a_printer() will convert
7218 it to what the client expects on a case by case basis */
7220 slprintf(name
, sizeof(name
)-1, "\\\\%s\\%s", global_myname(),
7221 printer
->info_2
->sharename
);
7224 if ((snum
= print_queue_snum(printer
->info_2
->sharename
)) == -1) {
7225 free_a_printer(&printer
,2);
7226 return WERR_ACCESS_DENIED
;
7229 /* you must be a printer admin to add a new printer */
7230 if (!print_access_check(p
->server_info
, snum
, PRINTER_ACCESS_ADMINISTER
)) {
7231 free_a_printer(&printer
,2);
7232 return WERR_ACCESS_DENIED
;
7236 * Do sanity check on the requested changes for Samba.
7239 if (!check_printer_ok(printer
->info_2
, snum
)) {
7240 free_a_printer(&printer
,2);
7241 return WERR_INVALID_PARAM
;
7245 * When a printer is created, the drivername bound to the printer is used
7246 * to lookup previously saved driver initialization info, which is then
7247 * bound to the new printer, simulating what happens in the Windows arch.
7252 /* A valid devmode was included, convert and link it
7254 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7256 if (!convert_devicemode(printer
->info_2
->printername
, devmode
,
7257 &printer
->info_2
->devmode
)) {
7262 /* write the ASCII on disk */
7263 err
= mod_a_printer(printer
, 2);
7264 if (!W_ERROR_IS_OK(err
)) {
7265 free_a_printer(&printer
,2);
7269 if (!open_printer_hnd(p
, handle
, name
, PRINTER_ACCESS_ADMINISTER
)) {
7270 /* Handle open failed - remove addition. */
7271 del_a_printer(printer
->info_2
->sharename
);
7272 free_a_printer(&printer
,2);
7273 ZERO_STRUCTP(handle
);
7274 return WERR_ACCESS_DENIED
;
7277 update_c_setprinter(false);
7278 free_a_printer(&printer
,2);
7283 /****************************************************************
7284 _spoolss_AddPrinterEx
7285 ****************************************************************/
7287 WERROR
_spoolss_AddPrinterEx(pipes_struct
*p
,
7288 struct spoolss_AddPrinterEx
*r
)
7290 switch (r
->in
.info_ctr
->level
) {
7292 /* we don't handle yet */
7293 /* but I know what to do ... */
7294 return WERR_UNKNOWN_LEVEL
;
7296 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
7298 r
->in
.devmode_ctr
->devmode
,
7299 r
->in
.secdesc_ctr
->sd
,
7300 r
->in
.userlevel_ctr
,
7303 return WERR_UNKNOWN_LEVEL
;
7307 /****************************************************************
7309 ****************************************************************/
7311 WERROR
_spoolss_AddPrinter(pipes_struct
*p
,
7312 struct spoolss_AddPrinter
*r
)
7314 struct spoolss_AddPrinterEx a
;
7315 struct spoolss_UserLevelCtr userlevel_ctr
;
7317 ZERO_STRUCT(userlevel_ctr
);
7319 userlevel_ctr
.level
= 1;
7321 a
.in
.server
= r
->in
.server
;
7322 a
.in
.info_ctr
= r
->in
.info_ctr
;
7323 a
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
7324 a
.in
.secdesc_ctr
= r
->in
.secdesc_ctr
;
7325 a
.in
.userlevel_ctr
= &userlevel_ctr
;
7326 a
.out
.handle
= r
->out
.handle
;
7328 return _spoolss_AddPrinterEx(p
, &a
);
7331 /****************************************************************
7332 _spoolss_AddPrinterDriverEx
7333 ****************************************************************/
7335 WERROR
_spoolss_AddPrinterDriverEx(pipes_struct
*p
,
7336 struct spoolss_AddPrinterDriverEx
*r
)
7338 WERROR err
= WERR_OK
;
7339 char *driver_name
= NULL
;
7343 switch (p
->hdr_req
.opnum
) {
7344 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
7345 fn
= "_spoolss_AddPrinterDriver";
7347 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
7348 fn
= "_spoolss_AddPrinterDriverEx";
7351 return WERR_INVALID_PARAM
;
7355 * we only support the semantics of AddPrinterDriver()
7356 * i.e. only copy files that are newer than existing ones
7359 if (r
->in
.flags
== 0) {
7360 return WERR_INVALID_PARAM
;
7363 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
7364 return WERR_ACCESS_DENIED
;
7368 if (r
->in
.info_ctr
->level
!= 3 && r
->in
.info_ctr
->level
!= 6) {
7369 /* Clever hack from Martin Zielinski <mz@seh.de>
7370 * to allow downgrade from level 8 (Vista).
7372 DEBUG(0,("%s: level %d not yet implemented\n", fn
,
7373 r
->in
.info_ctr
->level
));
7374 return WERR_UNKNOWN_LEVEL
;
7377 DEBUG(5,("Cleaning driver's information\n"));
7378 err
= clean_up_driver_struct(p
, r
->in
.info_ctr
);
7379 if (!W_ERROR_IS_OK(err
))
7382 DEBUG(5,("Moving driver to final destination\n"));
7383 if( !W_ERROR_IS_OK(err
= move_driver_to_download_area(p
, r
->in
.info_ctr
,
7388 if (add_a_printer_driver(p
->mem_ctx
, r
->in
.info_ctr
, &driver_name
, &version
)!=0) {
7389 err
= WERR_ACCESS_DENIED
;
7394 * I think this is where he DrvUpgradePrinter() hook would be
7395 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7396 * server. Right now, we just need to send ourselves a message
7397 * to update each printer bound to this driver. --jerry
7400 if (!srv_spoolss_drv_upgrade_printer(driver_name
)) {
7401 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
7409 /****************************************************************
7410 _spoolss_AddPrinterDriver
7411 ****************************************************************/
7413 WERROR
_spoolss_AddPrinterDriver(pipes_struct
*p
,
7414 struct spoolss_AddPrinterDriver
*r
)
7416 struct spoolss_AddPrinterDriverEx a
;
7418 switch (r
->in
.info_ctr
->level
) {
7425 return WERR_UNKNOWN_LEVEL
;
7428 a
.in
.servername
= r
->in
.servername
;
7429 a
.in
.info_ctr
= r
->in
.info_ctr
;
7430 a
.in
.flags
= APD_COPY_NEW_FILES
;
7432 return _spoolss_AddPrinterDriverEx(p
, &a
);
7435 /****************************************************************************
7436 ****************************************************************************/
7438 struct _spoolss_paths
{
7444 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
7446 static const struct _spoolss_paths spoolss_paths
[]= {
7447 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
7448 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
7451 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
7452 const char *servername
,
7453 const char *environment
,
7457 const char *pservername
= NULL
;
7458 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
7459 const char *short_archi
;
7463 /* environment may be empty */
7464 if (environment
&& strlen(environment
)) {
7465 long_archi
= environment
;
7468 /* servername may be empty */
7469 if (servername
&& strlen(servername
)) {
7470 pservername
= canon_servername(servername
);
7472 if (!is_myname_or_ipaddr(pservername
)) {
7473 return WERR_INVALID_PARAM
;
7477 if (!(short_archi
= get_short_archi(long_archi
))) {
7478 return WERR_INVALID_ENVIRONMENT
;
7481 switch (component
) {
7482 case SPOOLSS_PRTPROCS_PATH
:
7483 case SPOOLSS_DRIVER_PATH
:
7485 *path
= talloc_asprintf(mem_ctx
,
7488 spoolss_paths
[component
].share
,
7491 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
7492 SPOOLSS_DEFAULT_SERVER_PATH
,
7493 spoolss_paths
[component
].dir
,
7498 return WERR_INVALID_PARAM
;
7508 /****************************************************************************
7509 ****************************************************************************/
7511 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
7512 const char *servername
,
7513 const char *environment
,
7514 struct spoolss_DriverDirectoryInfo1
*r
)
7519 werr
= compose_spoolss_server_path(mem_ctx
,
7522 SPOOLSS_DRIVER_PATH
,
7524 if (!W_ERROR_IS_OK(werr
)) {
7528 DEBUG(4,("printer driver directory: [%s]\n", path
));
7530 r
->directory_name
= path
;
7535 /****************************************************************
7536 _spoolss_GetPrinterDriverDirectory
7537 ****************************************************************/
7539 WERROR
_spoolss_GetPrinterDriverDirectory(pipes_struct
*p
,
7540 struct spoolss_GetPrinterDriverDirectory
*r
)
7544 /* that's an [in out] buffer */
7546 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7547 return WERR_INVALID_PARAM
;
7550 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
7555 /* r->in.level is ignored */
7557 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
7560 &r
->out
.info
->info1
);
7561 if (!W_ERROR_IS_OK(werror
)) {
7562 TALLOC_FREE(r
->out
.info
);
7566 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
,
7567 r
->out
.info
, r
->in
.level
);
7568 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7570 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7573 /****************************************************************
7574 _spoolss_EnumPrinterData
7575 ****************************************************************/
7577 WERROR
_spoolss_EnumPrinterData(pipes_struct
*p
,
7578 struct spoolss_EnumPrinterData
*r
)
7581 struct spoolss_EnumPrinterDataEx r2
;
7583 struct spoolss_PrinterEnumValues
*info
, *val
= NULL
;
7586 r2
.in
.handle
= r
->in
.handle
;
7587 r2
.in
.key_name
= "PrinterDriverData";
7589 r2
.out
.count
= &count
;
7590 r2
.out
.info
= &info
;
7591 r2
.out
.needed
= &needed
;
7593 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
7594 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
7595 r2
.in
.offered
= needed
;
7596 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
7598 if (!W_ERROR_IS_OK(result
)) {
7603 * The NT machine wants to know the biggest size of value and data
7605 * cf: MSDN EnumPrinterData remark section
7608 if (!r
->in
.value_offered
&& !r
->in
.data_offered
) {
7609 uint32_t biggest_valuesize
= 0;
7610 uint32_t biggest_datasize
= 0;
7613 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
7615 for (i
=0; i
<count
; i
++) {
7617 name_length
= strlen(info
[i
].value_name
);
7618 if (strlen(info
[i
].value_name
) > biggest_valuesize
) {
7619 biggest_valuesize
= name_length
;
7622 if (info
[i
].data_length
> biggest_datasize
) {
7623 biggest_datasize
= info
[i
].data_length
;
7626 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
7630 /* the value is an UNICODE string but real_value_size is the length
7631 in bytes including the trailing 0 */
7633 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
7634 *r
->out
.data_needed
= biggest_datasize
;
7636 DEBUG(6,("final values: [%d], [%d]\n",
7637 *r
->out
.value_needed
, *r
->out
.data_needed
));
7642 if (r
->in
.enum_index
< count
) {
7643 val
= &info
[r
->in
.enum_index
];
7647 /* out_value should default to "" or else NT4 has
7648 problems unmarshalling the response */
7650 if (r
->in
.value_offered
) {
7651 *r
->out
.value_needed
= 1;
7652 r
->out
.value_name
= talloc_strdup(r
, "");
7653 if (!r
->out
.value_name
) {
7657 r
->out
.value_name
= NULL
;
7658 *r
->out
.value_needed
= 0;
7661 /* the data is counted in bytes */
7663 *r
->out
.data_needed
= r
->in
.data_offered
;
7665 result
= WERR_NO_MORE_ITEMS
;
7669 * - counted in bytes in the request
7670 * - counted in UNICODE chars in the max reply
7671 * - counted in bytes in the real size
7673 * take a pause *before* coding not *during* coding
7677 if (r
->in
.value_offered
) {
7678 r
->out
.value_name
= talloc_strdup(r
, val
->value_name
);
7679 if (!r
->out
.value_name
) {
7682 *r
->out
.value_needed
= val
->value_name_len
;
7684 r
->out
.value_name
= NULL
;
7685 *r
->out
.value_needed
= 0;
7690 *r
->out
.type
= val
->type
;
7692 /* data - counted in bytes */
7695 * See the section "Dynamically Typed Query Parameters"
7699 if (r
->out
.data
&& val
->data
&& val
->data
->data
&&
7700 val
->data_length
&& r
->in
.data_offered
) {
7701 memcpy(r
->out
.data
, val
->data
->data
,
7702 MIN(val
->data_length
,r
->in
.data_offered
));
7705 *r
->out
.data_needed
= val
->data_length
;
7713 /****************************************************************
7714 _spoolss_SetPrinterData
7715 ****************************************************************/
7717 WERROR
_spoolss_SetPrinterData(pipes_struct
*p
,
7718 struct spoolss_SetPrinterData
*r
)
7720 struct spoolss_SetPrinterDataEx r2
;
7722 r2
.in
.handle
= r
->in
.handle
;
7723 r2
.in
.key_name
= "PrinterDriverData";
7724 r2
.in
.value_name
= r
->in
.value_name
;
7725 r2
.in
.type
= r
->in
.type
;
7726 r2
.in
.data
= r
->in
.data
;
7727 r2
.in
.offered
= r
->in
.offered
;
7729 return _spoolss_SetPrinterDataEx(p
, &r2
);
7732 /****************************************************************
7733 _spoolss_ResetPrinter
7734 ****************************************************************/
7736 WERROR
_spoolss_ResetPrinter(pipes_struct
*p
,
7737 struct spoolss_ResetPrinter
*r
)
7739 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7742 DEBUG(5,("_spoolss_ResetPrinter\n"));
7745 * All we do is to check to see if the handle and queue is valid.
7746 * This call really doesn't mean anything to us because we only
7747 * support RAW printing. --jerry
7751 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
7752 OUR_HANDLE(r
->in
.handle
)));
7756 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7760 /* blindly return success */
7764 /****************************************************************
7765 _spoolss_DeletePrinterData
7766 ****************************************************************/
7768 WERROR
_spoolss_DeletePrinterData(pipes_struct
*p
,
7769 struct spoolss_DeletePrinterData
*r
)
7771 struct spoolss_DeletePrinterDataEx r2
;
7773 r2
.in
.handle
= r
->in
.handle
;
7774 r2
.in
.key_name
= "PrinterDriverData";
7775 r2
.in
.value_name
= r
->in
.value_name
;
7777 return _spoolss_DeletePrinterDataEx(p
, &r2
);
7780 /****************************************************************
7782 ****************************************************************/
7784 WERROR
_spoolss_AddForm(pipes_struct
*p
,
7785 struct spoolss_AddForm
*r
)
7787 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
7788 nt_forms_struct tmpForm
;
7790 WERROR status
= WERR_OK
;
7791 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7792 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7795 nt_forms_struct
*list
=NULL
;
7796 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7799 DEBUG(5,("_spoolss_AddForm\n"));
7802 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
7803 OUR_HANDLE(r
->in
.handle
)));
7808 /* forms can be added on printer or on the print server handle */
7810 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7812 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7815 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7816 if (!W_ERROR_IS_OK(status
))
7820 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
7821 and not a printer admin, then fail */
7823 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
7824 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
7825 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
7827 p
->server_info
->ptok
,
7828 lp_printer_admin(snum
))) {
7829 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
7830 status
= WERR_ACCESS_DENIED
;
7834 switch (form
->flags
) {
7835 case SPOOLSS_FORM_USER
:
7836 case SPOOLSS_FORM_BUILTIN
:
7837 case SPOOLSS_FORM_PRINTER
:
7840 status
= WERR_INVALID_PARAM
;
7844 /* can't add if builtin */
7846 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
7847 status
= WERR_FILE_EXISTS
;
7851 count
= get_ntforms(&list
);
7853 for (i
=0; i
< count
; i
++) {
7854 if (strequal(form
->form_name
, list
[i
].name
)) {
7855 status
= WERR_FILE_EXISTS
;
7860 if(!add_a_form(&list
, form
, &count
)) {
7861 status
= WERR_NOMEM
;
7866 write_ntforms(&list
, count
);
7870 * ChangeID must always be set if this is a printer
7873 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7874 status
= mod_a_printer(printer
, 2);
7878 free_a_printer(&printer
, 2);
7884 /****************************************************************
7886 ****************************************************************/
7888 WERROR
_spoolss_DeleteForm(pipes_struct
*p
,
7889 struct spoolss_DeleteForm
*r
)
7891 const char *form_name
= r
->in
.form_name
;
7892 nt_forms_struct tmpForm
;
7894 nt_forms_struct
*list
=NULL
;
7895 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7897 WERROR status
= WERR_OK
;
7898 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7899 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7902 DEBUG(5,("_spoolss_DeleteForm\n"));
7905 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
7906 OUR_HANDLE(r
->in
.handle
)));
7910 /* forms can be deleted on printer of on the print server handle */
7912 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7914 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7917 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7918 if (!W_ERROR_IS_OK(status
))
7922 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
7923 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
7924 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
7926 p
->server_info
->ptok
,
7927 lp_printer_admin(snum
))) {
7928 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
7929 return WERR_ACCESS_DENIED
;
7933 /* can't delete if builtin */
7935 if (get_a_builtin_ntform_by_string(form_name
,&tmpForm
)) {
7936 status
= WERR_INVALID_PARAM
;
7940 count
= get_ntforms(&list
);
7943 ret
= delete_a_form(&list
, form_name
, &count
, &status
);
7950 * ChangeID must always be set if this is a printer
7953 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7954 status
= mod_a_printer(printer
, 2);
7958 free_a_printer(&printer
, 2);
7964 /****************************************************************
7966 ****************************************************************/
7968 WERROR
_spoolss_SetForm(pipes_struct
*p
,
7969 struct spoolss_SetForm
*r
)
7971 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
7972 nt_forms_struct tmpForm
;
7974 WERROR status
= WERR_OK
;
7975 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
7976 SE_PRIV se_printop
= SE_PRINT_OPERATOR
;
7979 nt_forms_struct
*list
=NULL
;
7980 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7982 DEBUG(5,("_spoolss_SetForm\n"));
7985 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
7986 OUR_HANDLE(r
->in
.handle
)));
7990 /* forms can be modified on printer of on the print server handle */
7992 if ( Printer
->printer_type
== SPLHND_PRINTER
)
7994 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
7997 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
7998 if (!W_ERROR_IS_OK(status
))
8002 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8003 and not a printer admin, then fail */
8005 if ((p
->server_info
->utok
.uid
!= sec_initial_uid()) &&
8006 !user_has_privileges(p
->server_info
->ptok
, &se_printop
) &&
8007 !token_contains_name_in_list(uidtoname(p
->server_info
->utok
.uid
),
8009 p
->server_info
->ptok
,
8010 lp_printer_admin(snum
))) {
8011 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8012 status
= WERR_ACCESS_DENIED
;
8016 /* can't set if builtin */
8017 if (get_a_builtin_ntform_by_string(form
->form_name
, &tmpForm
)) {
8018 status
= WERR_INVALID_PARAM
;
8022 count
= get_ntforms(&list
);
8023 update_a_form(&list
, form
, count
);
8025 write_ntforms(&list
, count
);
8029 * ChangeID must always be set if this is a printer
8032 if ( Printer
->printer_type
== SPLHND_PRINTER
)
8033 status
= mod_a_printer(printer
, 2);
8038 free_a_printer(&printer
, 2);
8044 /****************************************************************************
8045 fill_print_processor1
8046 ****************************************************************************/
8048 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8049 struct spoolss_PrintProcessorInfo1
*r
,
8050 const char *print_processor_name
)
8052 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8053 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8058 /****************************************************************************
8059 enumprintprocessors level 1.
8060 ****************************************************************************/
8062 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8063 union spoolss_PrintProcessorInfo
**info_p
,
8066 union spoolss_PrintProcessorInfo
*info
;
8069 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8070 W_ERROR_HAVE_NO_MEMORY(info
);
8074 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8075 if (!W_ERROR_IS_OK(result
)) {
8080 if (!W_ERROR_IS_OK(result
)) {
8091 /****************************************************************
8092 _spoolss_EnumPrintProcessors
8093 ****************************************************************/
8095 WERROR
_spoolss_EnumPrintProcessors(pipes_struct
*p
,
8096 struct spoolss_EnumPrintProcessors
*r
)
8100 /* that's an [in out] buffer */
8102 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8103 return WERR_INVALID_PARAM
;
8106 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8109 * Enumerate the print processors ...
8111 * Just reply with "winprint", to keep NT happy
8112 * and I can use my nice printer checker.
8117 *r
->out
.info
= NULL
;
8119 switch (r
->in
.level
) {
8121 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8125 return WERR_UNKNOWN_LEVEL
;
8128 if (!W_ERROR_IS_OK(result
)) {
8132 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8133 spoolss_EnumPrintProcessors
,
8134 *r
->out
.info
, r
->in
.level
,
8136 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8137 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8139 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8142 /****************************************************************************
8143 fill_printprocdatatype1
8144 ****************************************************************************/
8146 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8147 struct spoolss_PrintProcDataTypesInfo1
*r
,
8148 const char *name_array
)
8150 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8151 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8156 /****************************************************************************
8157 enumprintprocdatatypes level 1.
8158 ****************************************************************************/
8160 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8161 union spoolss_PrintProcDataTypesInfo
**info_p
,
8165 union spoolss_PrintProcDataTypesInfo
*info
;
8167 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8168 W_ERROR_HAVE_NO_MEMORY(info
);
8172 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8173 if (!W_ERROR_IS_OK(result
)) {
8178 if (!W_ERROR_IS_OK(result
)) {
8189 /****************************************************************
8190 _spoolss_EnumPrintProcDataTypes
8191 ****************************************************************/
8193 WERROR
_spoolss_EnumPrintProcDataTypes(pipes_struct
*p
,
8194 struct spoolss_EnumPrintProcDataTypes
*r
)
8198 /* that's an [in out] buffer */
8200 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8201 return WERR_INVALID_PARAM
;
8204 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8208 *r
->out
.info
= NULL
;
8210 switch (r
->in
.level
) {
8212 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8216 return WERR_UNKNOWN_LEVEL
;
8219 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8220 spoolss_EnumPrintProcDataTypes
,
8221 *r
->out
.info
, r
->in
.level
,
8223 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8224 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8226 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8229 /****************************************************************************
8231 ****************************************************************************/
8233 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8234 struct spoolss_MonitorInfo1
*r
,
8235 const char *monitor_name
)
8237 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8238 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8243 /****************************************************************************
8245 ****************************************************************************/
8247 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8248 struct spoolss_MonitorInfo2
*r
,
8249 const char *monitor_name
,
8250 const char *environment
,
8251 const char *dll_name
)
8253 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8254 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8255 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8256 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8257 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8258 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8263 /****************************************************************************
8264 enumprintmonitors level 1.
8265 ****************************************************************************/
8267 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8268 union spoolss_MonitorInfo
**info_p
,
8271 union spoolss_MonitorInfo
*info
;
8272 WERROR result
= WERR_OK
;
8274 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8275 W_ERROR_HAVE_NO_MEMORY(info
);
8279 result
= fill_monitor_1(info
, &info
[0].info1
,
8281 if (!W_ERROR_IS_OK(result
)) {
8285 result
= fill_monitor_1(info
, &info
[1].info1
,
8287 if (!W_ERROR_IS_OK(result
)) {
8292 if (!W_ERROR_IS_OK(result
)) {
8303 /****************************************************************************
8304 enumprintmonitors level 2.
8305 ****************************************************************************/
8307 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
8308 union spoolss_MonitorInfo
**info_p
,
8311 union spoolss_MonitorInfo
*info
;
8312 WERROR result
= WERR_OK
;
8314 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8315 W_ERROR_HAVE_NO_MEMORY(info
);
8319 result
= fill_monitor_2(info
, &info
[0].info2
,
8321 "Windows NT X86", /* FIXME */
8323 if (!W_ERROR_IS_OK(result
)) {
8327 result
= fill_monitor_2(info
, &info
[1].info2
,
8329 "Windows NT X86", /* FIXME */
8331 if (!W_ERROR_IS_OK(result
)) {
8336 if (!W_ERROR_IS_OK(result
)) {
8347 /****************************************************************
8348 _spoolss_EnumMonitors
8349 ****************************************************************/
8351 WERROR
_spoolss_EnumMonitors(pipes_struct
*p
,
8352 struct spoolss_EnumMonitors
*r
)
8356 /* that's an [in out] buffer */
8358 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8359 return WERR_INVALID_PARAM
;
8362 DEBUG(5,("_spoolss_EnumMonitors\n"));
8365 * Enumerate the print monitors ...
8367 * Just reply with "Local Port", to keep NT happy
8368 * and I can use my nice printer checker.
8373 *r
->out
.info
= NULL
;
8375 switch (r
->in
.level
) {
8377 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
8381 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
8385 return WERR_UNKNOWN_LEVEL
;
8388 if (!W_ERROR_IS_OK(result
)) {
8392 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8393 spoolss_EnumMonitors
,
8394 *r
->out
.info
, r
->in
.level
,
8396 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8397 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8399 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8402 /****************************************************************************
8403 ****************************************************************************/
8405 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
8406 const print_queue_struct
*queue
,
8407 int count
, int snum
,
8408 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8410 struct spoolss_JobInfo1
*r
)
8415 for (i
=0; i
<count
; i
++) {
8416 if (queue
[i
].job
== (int)jobid
) {
8422 if (found
== false) {
8423 /* NT treats not found as bad param... yet another bad choice */
8424 return WERR_INVALID_PARAM
;
8427 return fill_job_info1(mem_ctx
,
8435 /****************************************************************************
8436 ****************************************************************************/
8438 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
8439 const print_queue_struct
*queue
,
8440 int count
, int snum
,
8441 const NT_PRINTER_INFO_LEVEL
*ntprinter
,
8443 struct spoolss_JobInfo2
*r
)
8447 struct spoolss_DeviceMode
*devmode
;
8448 NT_DEVICEMODE
*nt_devmode
;
8451 for (i
=0; i
<count
; i
++) {
8452 if (queue
[i
].job
== (int)jobid
) {
8458 if (found
== false) {
8459 /* NT treats not found as bad param... yet another bad
8461 return WERR_INVALID_PARAM
;
8465 * if the print job does not have a DEVMODE associated with it,
8466 * just use the one for the printer. A NULL devicemode is not
8467 * a failure condition
8470 nt_devmode
= print_job_devmode(lp_const_servicename(snum
), jobid
);
8472 devmode
= TALLOC_ZERO_P(mem_ctx
, struct spoolss_DeviceMode
);
8473 W_ERROR_HAVE_NO_MEMORY(devmode
);
8474 result
= convert_nt_devicemode(devmode
, devmode
, nt_devmode
);
8475 if (!W_ERROR_IS_OK(result
)) {
8479 devmode
= construct_dev_mode(mem_ctx
, lp_const_servicename(snum
));
8480 W_ERROR_HAVE_NO_MEMORY(devmode
);
8483 return fill_job_info2(mem_ctx
,
8492 /****************************************************************
8494 ****************************************************************/
8496 WERROR
_spoolss_GetJob(pipes_struct
*p
,
8497 struct spoolss_GetJob
*r
)
8499 WERROR result
= WERR_OK
;
8500 NT_PRINTER_INFO_LEVEL
*ntprinter
= NULL
;
8503 print_queue_struct
*queue
= NULL
;
8504 print_status_struct prt_status
;
8506 /* that's an [in out] buffer */
8508 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8509 return WERR_INVALID_PARAM
;
8512 DEBUG(5,("_spoolss_GetJob\n"));
8516 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8520 result
= get_a_printer(NULL
, &ntprinter
, 2, lp_servicename(snum
));
8521 if (!W_ERROR_IS_OK(result
)) {
8525 count
= print_queue_status(snum
, &queue
, &prt_status
);
8527 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
8528 count
, prt_status
.status
, prt_status
.message
));
8530 switch (r
->in
.level
) {
8532 result
= getjob_level_1(p
->mem_ctx
,
8533 queue
, count
, snum
, ntprinter
,
8534 r
->in
.job_id
, &r
->out
.info
->info1
);
8537 result
= getjob_level_2(p
->mem_ctx
,
8538 queue
, count
, snum
, ntprinter
,
8539 r
->in
.job_id
, &r
->out
.info
->info2
);
8542 result
= WERR_UNKNOWN_LEVEL
;
8547 free_a_printer(&ntprinter
, 2);
8549 if (!W_ERROR_IS_OK(result
)) {
8550 TALLOC_FREE(r
->out
.info
);
8554 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, r
->out
.info
,
8556 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8558 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8561 /****************************************************************
8562 _spoolss_GetPrinterDataEx
8563 ****************************************************************/
8565 WERROR
_spoolss_GetPrinterDataEx(pipes_struct
*p
,
8566 struct spoolss_GetPrinterDataEx
*r
)
8569 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8570 struct regval_blob
*val
= NULL
;
8571 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8573 WERROR result
= WERR_OK
;
8576 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
8578 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
8579 r
->in
.key_name
, r
->in
.value_name
));
8581 /* in case of problem, return some default values */
8584 *r
->out
.type
= REG_NONE
;
8587 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8588 OUR_HANDLE(r
->in
.handle
)));
8589 result
= WERR_BADFID
;
8593 /* Is the handle to a printer or to the server? */
8595 if (Printer
->printer_type
== SPLHND_SERVER
) {
8597 union spoolss_PrinterData data
;
8599 result
= getprinterdata_printer_server(p
->mem_ctx
,
8603 if (!W_ERROR_IS_OK(result
)) {
8607 result
= push_spoolss_PrinterData(p
->mem_ctx
, &blob
,
8608 *r
->out
.type
, &data
);
8609 if (!W_ERROR_IS_OK(result
)) {
8613 *r
->out
.needed
= blob
.length
;
8615 if (r
->in
.offered
>= *r
->out
.needed
) {
8616 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
8619 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8622 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8623 result
= WERR_BADFID
;
8627 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8628 if (!W_ERROR_IS_OK(result
)) {
8632 /* check to see if the keyname is valid */
8633 if (!strlen(r
->in
.key_name
)) {
8634 result
= WERR_INVALID_PARAM
;
8638 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
8640 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
8641 strequal(r
->in
.value_name
, "ChangeId")) {
8642 *r
->out
.type
= REG_DWORD
;
8644 if (r
->in
.offered
>= *r
->out
.needed
) {
8645 SIVAL(r
->out
.data
, 0, printer
->info_2
->changeid
);
8651 if (lookup_printerkey(printer
->info_2
->data
, r
->in
.key_name
) == -1) {
8652 DEBUG(4,("_spoolss_GetPrinterDataEx: "
8653 "Invalid keyname [%s]\n", r
->in
.key_name
));
8654 result
= WERR_BADFILE
;
8658 val
= get_printer_data(printer
->info_2
,
8659 r
->in
.key_name
, r
->in
.value_name
);
8661 result
= WERR_BADFILE
;
8665 *r
->out
.needed
= regval_size(val
);
8666 *r
->out
.type
= regval_type(val
);
8668 if (r
->in
.offered
>= *r
->out
.needed
) {
8669 memcpy(r
->out
.data
, regval_data_p(val
), regval_size(val
));
8673 free_a_printer(&printer
, 2);
8676 if (!W_ERROR_IS_OK(result
)) {
8680 *r
->out
.type
= SPOOLSS_BUFFER_OK(*r
->out
.type
, REG_NONE
);
8681 r
->out
.data
= SPOOLSS_BUFFER_OK(r
->out
.data
, r
->out
.data
);
8683 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
8686 /****************************************************************
8687 _spoolss_SetPrinterDataEx
8688 ****************************************************************/
8690 WERROR
_spoolss_SetPrinterDataEx(pipes_struct
*p
,
8691 struct spoolss_SetPrinterDataEx
*r
)
8693 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8695 WERROR result
= WERR_OK
;
8696 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8699 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
8701 /* From MSDN documentation of SetPrinterDataEx: pass request to
8702 SetPrinterData if key is "PrinterDriverData" */
8705 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
8706 OUR_HANDLE(r
->in
.handle
)));
8710 if (Printer
->printer_type
== SPLHND_SERVER
) {
8711 DEBUG(10,("_spoolss_SetPrinterDataEx: "
8712 "Not implemented for server handles yet\n"));
8713 return WERR_INVALID_PARAM
;
8716 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8721 * Access check : NT returns "access denied" if you make a
8722 * SetPrinterData call without the necessary privildge.
8723 * we were originally returning OK if nothing changed
8724 * which made Win2k issue **a lot** of SetPrinterData
8725 * when connecting to a printer --jerry
8728 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8729 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
8730 "change denied by handle access permissions\n"));
8731 return WERR_ACCESS_DENIED
;
8734 result
= get_a_printer(Printer
, &printer
, 2, lp_servicename(snum
));
8735 if (!W_ERROR_IS_OK(result
)) {
8739 /* check for OID in valuename */
8741 oid_string
= strchr(r
->in
.value_name
, ',');
8747 /* save the registry data */
8749 result
= set_printer_dataex(printer
, r
->in
.key_name
, r
->in
.value_name
,
8750 r
->in
.type
, r
->in
.data
, r
->in
.offered
);
8752 if (W_ERROR_IS_OK(result
)) {
8753 /* save the OID if one was specified */
8755 char *str
= talloc_asprintf(p
->mem_ctx
, "%s\\%s",
8756 r
->in
.key_name
, SPOOL_OID_KEY
);
8758 result
= WERR_NOMEM
;
8763 * I'm not checking the status here on purpose. Don't know
8764 * if this is right, but I'm returning the status from the
8765 * previous set_printer_dataex() call. I have no idea if
8766 * this is right. --jerry
8769 set_printer_dataex(printer
, str
, r
->in
.value_name
,
8770 REG_SZ
, (uint8_t *)oid_string
,
8771 strlen(oid_string
)+1);
8774 result
= mod_a_printer(printer
, 2);
8778 free_a_printer(&printer
, 2);
8783 /****************************************************************
8784 _spoolss_DeletePrinterDataEx
8785 ****************************************************************/
8787 WERROR
_spoolss_DeletePrinterDataEx(pipes_struct
*p
,
8788 struct spoolss_DeletePrinterDataEx
*r
)
8790 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8792 WERROR status
= WERR_OK
;
8793 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8795 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
8798 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
8799 "Invalid handle (%s:%u:%u).\n",
8800 OUR_HANDLE(r
->in
.handle
)));
8804 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8807 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8808 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
8809 "printer properties change denied by handle\n"));
8810 return WERR_ACCESS_DENIED
;
8813 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
8817 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8818 if (!W_ERROR_IS_OK(status
))
8821 status
= delete_printer_dataex( printer
, r
->in
.key_name
, r
->in
.value_name
);
8823 if ( W_ERROR_IS_OK(status
) )
8824 mod_a_printer( printer
, 2 );
8826 free_a_printer(&printer
, 2);
8831 /****************************************************************
8832 _spoolss_EnumPrinterKey
8833 ****************************************************************/
8835 WERROR
_spoolss_EnumPrinterKey(pipes_struct
*p
,
8836 struct spoolss_EnumPrinterKey
*r
)
8838 fstring
*keynames
= NULL
;
8840 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8841 NT_PRINTER_DATA
*data
;
8842 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8844 WERROR result
= WERR_BADFILE
;
8846 const char **array
= NULL
;
8849 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
8852 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
8853 OUR_HANDLE(r
->in
.handle
)));
8857 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8861 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8862 if (!W_ERROR_IS_OK(result
)) {
8866 /* get the list of subkey names */
8868 data
= printer
->info_2
->data
;
8870 num_keys
= get_printer_subkeys(data
, r
->in
.key_name
, &keynames
);
8871 if (num_keys
== -1) {
8872 result
= WERR_BADFILE
;
8876 array
= talloc_zero_array(r
->out
.key_buffer
, const char *, num_keys
+ 2);
8878 result
= WERR_NOMEM
;
8883 array
[0] = talloc_strdup(array
, "");
8885 result
= WERR_NOMEM
;
8890 for (i
=0; i
< num_keys
; i
++) {
8892 DEBUG(10,("_spoolss_EnumPrinterKey: adding keyname: %s\n",
8895 array
[i
] = talloc_strdup(array
, keynames
[i
]);
8897 result
= WERR_NOMEM
;
8902 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
8903 result
= WERR_NOMEM
;
8907 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
8908 *r
->out
.needed
= blob
.length
;
8910 if (r
->in
.offered
< *r
->out
.needed
) {
8911 result
= WERR_MORE_DATA
;
8914 r
->out
.key_buffer
->string_array
= array
;
8918 if (!W_ERROR_IS_OK(result
)) {
8920 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
8925 free_a_printer(&printer
, 2);
8926 SAFE_FREE(keynames
);
8931 /****************************************************************
8932 _spoolss_DeletePrinterKey
8933 ****************************************************************/
8935 WERROR
_spoolss_DeletePrinterKey(pipes_struct
*p
,
8936 struct spoolss_DeletePrinterKey
*r
)
8938 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8939 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
8943 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
8946 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
8947 OUR_HANDLE(r
->in
.handle
)));
8951 /* if keyname == NULL, return error */
8953 if ( !r
->in
.key_name
)
8954 return WERR_INVALID_PARAM
;
8956 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8959 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
8960 DEBUG(3, ("_spoolss_DeletePrinterKey: "
8961 "printer properties change denied by handle\n"));
8962 return WERR_ACCESS_DENIED
;
8965 status
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
8966 if (!W_ERROR_IS_OK(status
))
8969 /* delete the key and all subneys */
8971 status
= delete_all_printer_data( printer
->info_2
, r
->in
.key_name
);
8973 if ( W_ERROR_IS_OK(status
) )
8974 status
= mod_a_printer(printer
, 2);
8976 free_a_printer( &printer
, 2 );
8981 /****************************************************************
8982 ****************************************************************/
8984 static WERROR
registry_value_to_printer_enum_value(TALLOC_CTX
*mem_ctx
,
8985 struct regval_blob
*v
,
8986 struct spoolss_PrinterEnumValues
*r
)
8988 r
->data
= TALLOC_ZERO_P(mem_ctx
, DATA_BLOB
);
8989 W_ERROR_HAVE_NO_MEMORY(r
->data
);
8991 r
->value_name
= talloc_strdup(mem_ctx
, regval_name(v
));
8992 W_ERROR_HAVE_NO_MEMORY(r
->value_name
);
8994 r
->value_name_len
= strlen_m_term(regval_name(v
)) * 2;
8996 r
->type
= regval_type(v
);
8997 r
->data_length
= regval_size(v
);
8999 if (r
->data_length
) {
9000 *r
->data
= data_blob_talloc(r
->data
, regval_data_p(v
), regval_size(v
));
9006 /****************************************************************
9007 _spoolss_EnumPrinterDataEx
9008 ****************************************************************/
9010 WERROR
_spoolss_EnumPrinterDataEx(pipes_struct
*p
,
9011 struct spoolss_EnumPrinterDataEx
*r
)
9014 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
9015 struct spoolss_PrinterEnumValues
*info
= NULL
;
9016 NT_PRINTER_DATA
*p_data
;
9017 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9023 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9027 *r
->out
.info
= NULL
;
9030 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9031 OUR_HANDLE(r
->in
.handle
)));
9036 * first check for a keyname of NULL or "". Win2k seems to send
9037 * this a lot and we should send back WERR_INVALID_PARAM
9038 * no need to spend time looking up the printer in this case.
9042 if (!strlen(r
->in
.key_name
)) {
9043 result
= WERR_INVALID_PARAM
;
9047 /* get the printer off of disk */
9049 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9053 ZERO_STRUCT(printer
);
9054 result
= get_a_printer(Printer
, &printer
, 2, lp_const_servicename(snum
));
9055 if (!W_ERROR_IS_OK(result
)) {
9059 /* now look for a match on the key name */
9061 p_data
= printer
->info_2
->data
;
9063 key_index
= lookup_printerkey(p_data
, r
->in
.key_name
);
9064 if (key_index
== -1) {
9065 DEBUG(10,("_spoolss_EnumPrinterDataEx: Unknown keyname [%s]\n",
9067 result
= WERR_INVALID_PARAM
;
9071 /* allocate the memory for the array of pointers -- if necessary */
9073 count
= regval_ctr_numvals(p_data
->keys
[key_index
].values
);
9075 result
= WERR_OK
; /* ??? */
9079 info
= TALLOC_ZERO_ARRAY(p
->mem_ctx
,
9080 struct spoolss_PrinterEnumValues
,
9083 DEBUG(0,("_spoolss_EnumPrinterDataEx: talloc() failed\n"));
9084 result
= WERR_NOMEM
;
9089 * loop through all params and build the array to pass
9090 * back to the client
9093 for (i
=0; i
< count
; i
++) {
9095 struct regval_blob
*val
;
9097 /* lookup the registry value */
9099 val
= regval_ctr_specific_value(p_data
->keys
[key_index
].values
, i
);
9101 DEBUG(10,("retrieved value number [%d] [%s]\n", i
, regval_name(val
)));
9105 result
= registry_value_to_printer_enum_value(info
, val
, &info
[i
]);
9106 if (!W_ERROR_IS_OK(result
)) {
9111 #if 0 /* FIXME - gd */
9112 /* housekeeping information in the reply */
9114 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9115 * the hand marshalled container size is a multiple
9116 * of 4 bytes for RPC alignment.
9120 needed
+= 4-(needed
% 4);
9123 *r
->out
.count
= count
;
9124 *r
->out
.info
= info
;
9129 free_a_printer(&printer
, 2);
9132 if (!W_ERROR_IS_OK(result
)) {
9136 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
9137 spoolss_EnumPrinterDataEx
,
9140 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9141 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
9143 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9146 /****************************************************************************
9147 ****************************************************************************/
9149 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
9150 const char *servername
,
9151 const char *environment
,
9152 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
9157 werr
= compose_spoolss_server_path(mem_ctx
,
9160 SPOOLSS_PRTPROCS_PATH
,
9162 if (!W_ERROR_IS_OK(werr
)) {
9166 DEBUG(4,("print processor directory: [%s]\n", path
));
9168 r
->directory_name
= path
;
9173 /****************************************************************
9174 _spoolss_GetPrintProcessorDirectory
9175 ****************************************************************/
9177 WERROR
_spoolss_GetPrintProcessorDirectory(pipes_struct
*p
,
9178 struct spoolss_GetPrintProcessorDirectory
*r
)
9182 /* that's an [in out] buffer */
9184 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9185 return WERR_INVALID_PARAM
;
9188 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9193 /* r->in.level is ignored */
9195 /* We always should reply with a local print processor directory so that
9196 * users are not forced to have a [prnproc$] share on the Samba spoolss
9197 * server - Guenther */
9199 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9200 NULL
, /* r->in.server */
9202 &r
->out
.info
->info1
);
9203 if (!W_ERROR_IS_OK(result
)) {
9204 TALLOC_FREE(r
->out
.info
);
9208 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
,
9209 r
->out
.info
, r
->in
.level
);
9210 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9212 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9215 /*******************************************************************
9216 ********************************************************************/
9218 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9219 const char *dllname
)
9221 enum ndr_err_code ndr_err
;
9222 struct spoolss_MonitorUi ui
;
9224 ui
.dll_name
= dllname
;
9226 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, &ui
,
9227 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9228 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9229 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9231 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9234 /*******************************************************************
9235 Streams the monitor UI DLL name in UNICODE
9236 *******************************************************************/
9238 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9239 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9240 DATA_BLOB
*out
, uint32_t *needed
)
9242 const char *dllname
= "tcpmonui.dll";
9244 *needed
= (strlen(dllname
)+1) * 2;
9246 if (out
->length
< *needed
) {
9247 return WERR_INSUFFICIENT_BUFFER
;
9250 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9257 /*******************************************************************
9258 ********************************************************************/
9260 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9261 struct spoolss_PortData1
*port1
,
9262 const DATA_BLOB
*buf
)
9264 enum ndr_err_code ndr_err
;
9265 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port1
,
9266 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9267 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9268 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9270 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9273 /*******************************************************************
9274 ********************************************************************/
9276 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9277 struct spoolss_PortData2
*port2
,
9278 const DATA_BLOB
*buf
)
9280 enum ndr_err_code ndr_err
;
9281 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port2
,
9282 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9283 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9284 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9286 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9289 /*******************************************************************
9290 Create a new TCP/IP port
9291 *******************************************************************/
9293 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9294 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9295 DATA_BLOB
*out
, uint32_t *needed
)
9297 struct spoolss_PortData1 port1
;
9298 struct spoolss_PortData2 port2
;
9299 char *device_uri
= NULL
;
9302 const char *portname
;
9303 const char *hostaddress
;
9305 uint32_t port_number
;
9308 /* peek for spoolss_PortData version */
9310 if (!in
|| (in
->length
< (128 + 4))) {
9311 return WERR_GENERAL_FAILURE
;
9314 version
= IVAL(in
->data
, 128);
9320 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9324 portname
= port1
.portname
;
9325 hostaddress
= port1
.hostaddress
;
9326 queue
= port1
.queue
;
9327 protocol
= port1
.protocol
;
9328 port_number
= port1
.port_number
;
9334 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9338 portname
= port2
.portname
;
9339 hostaddress
= port2
.hostaddress
;
9340 queue
= port2
.queue
;
9341 protocol
= port2
.protocol
;
9342 port_number
= port2
.port_number
;
9346 DEBUG(1,("xcvtcp_addport: "
9347 "unknown version of port_data: %d\n", version
));
9348 return WERR_UNKNOWN_PORT
;
9351 /* create the device URI and call the add_port_hook() */
9354 case PROTOCOL_RAWTCP_TYPE
:
9355 device_uri
= talloc_asprintf(mem_ctx
,
9356 "socket://%s:%d/", hostaddress
,
9360 case PROTOCOL_LPR_TYPE
:
9361 device_uri
= talloc_asprintf(mem_ctx
,
9362 "lpr://%s/%s", hostaddress
, queue
);
9366 return WERR_UNKNOWN_PORT
;
9373 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
9376 /*******************************************************************
9377 *******************************************************************/
9379 struct xcv_api_table xcvtcp_cmds
[] = {
9380 { "MonitorUI", xcvtcp_monitorui
},
9381 { "AddPort", xcvtcp_addport
},
9385 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
9386 NT_USER_TOKEN
*token
, const char *command
,
9393 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9395 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9396 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9397 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9400 return WERR_BADFUNC
;
9403 /*******************************************************************
9404 *******************************************************************/
9405 #if 0 /* don't support management using the "Local Port" monitor */
9407 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
9408 NT_USER_TOKEN
*token
, DATA_BLOB
*in
,
9409 DATA_BLOB
*out
, uint32_t *needed
)
9411 const char *dllname
= "localui.dll";
9413 *needed
= (strlen(dllname
)+1) * 2;
9415 if (out
->length
< *needed
) {
9416 return WERR_INSUFFICIENT_BUFFER
;
9419 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9426 /*******************************************************************
9427 *******************************************************************/
9429 struct xcv_api_table xcvlocal_cmds
[] = {
9430 { "MonitorUI", xcvlocal_monitorui
},
9434 struct xcv_api_table xcvlocal_cmds
[] = {
9441 /*******************************************************************
9442 *******************************************************************/
9444 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
9445 NT_USER_TOKEN
*token
, const char *command
,
9446 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
9451 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
9453 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
9454 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
9455 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9457 return WERR_BADFUNC
;
9460 /****************************************************************
9462 ****************************************************************/
9464 WERROR
_spoolss_XcvData(pipes_struct
*p
,
9465 struct spoolss_XcvData
*r
)
9467 Printer_entry
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9468 DATA_BLOB out_data
= data_blob_null
;
9472 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
9473 OUR_HANDLE(r
->in
.handle
)));
9477 /* Has to be a handle to the TCP/IP port monitor */
9479 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
9480 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
9484 /* requires administrative access to the server */
9486 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
9487 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
9488 return WERR_ACCESS_DENIED
;
9491 /* Allocate the outgoing buffer */
9493 if (r
->in
.out_data_size
) {
9494 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
9495 if (out_data
.data
== NULL
) {
9500 switch ( Printer
->printer_type
) {
9501 case SPLHND_PORTMON_TCP
:
9502 werror
= process_xcvtcp_command(p
->mem_ctx
,
9503 p
->server_info
->ptok
,
9504 r
->in
.function_name
,
9505 &r
->in
.in_data
, &out_data
,
9508 case SPLHND_PORTMON_LOCAL
:
9509 werror
= process_xcvlocal_command(p
->mem_ctx
,
9510 p
->server_info
->ptok
,
9511 r
->in
.function_name
,
9512 &r
->in
.in_data
, &out_data
,
9516 werror
= WERR_INVALID_PRINT_MONITOR
;
9519 if (!W_ERROR_IS_OK(werror
)) {
9523 *r
->out
.status_code
= 0;
9525 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
9526 memcpy(r
->out
.out_data
, out_data
.data
,
9527 MIN(r
->in
.out_data_size
, out_data
.length
));
9533 /****************************************************************
9534 _spoolss_AddPrintProcessor
9535 ****************************************************************/
9537 WERROR
_spoolss_AddPrintProcessor(pipes_struct
*p
,
9538 struct spoolss_AddPrintProcessor
*r
)
9540 /* for now, just indicate success and ignore the add. We'll
9541 automatically set the winprint processor for printer
9542 entries later. Used to debug the LexMark Optra S 1855 PCL
9548 /****************************************************************
9550 ****************************************************************/
9552 WERROR
_spoolss_AddPort(pipes_struct
*p
,
9553 struct spoolss_AddPort
*r
)
9555 /* do what w2k3 does */
9557 return WERR_NOT_SUPPORTED
;
9560 /****************************************************************
9561 _spoolss_GetPrinterDriver
9562 ****************************************************************/
9564 WERROR
_spoolss_GetPrinterDriver(pipes_struct
*p
,
9565 struct spoolss_GetPrinterDriver
*r
)
9567 p
->rng_fault_state
= true;
9568 return WERR_NOT_SUPPORTED
;
9571 /****************************************************************
9572 _spoolss_ReadPrinter
9573 ****************************************************************/
9575 WERROR
_spoolss_ReadPrinter(pipes_struct
*p
,
9576 struct spoolss_ReadPrinter
*r
)
9578 p
->rng_fault_state
= true;
9579 return WERR_NOT_SUPPORTED
;
9582 /****************************************************************
9583 _spoolss_WaitForPrinterChange
9584 ****************************************************************/
9586 WERROR
_spoolss_WaitForPrinterChange(pipes_struct
*p
,
9587 struct spoolss_WaitForPrinterChange
*r
)
9589 p
->rng_fault_state
= true;
9590 return WERR_NOT_SUPPORTED
;
9593 /****************************************************************
9594 _spoolss_ConfigurePort
9595 ****************************************************************/
9597 WERROR
_spoolss_ConfigurePort(pipes_struct
*p
,
9598 struct spoolss_ConfigurePort
*r
)
9600 p
->rng_fault_state
= true;
9601 return WERR_NOT_SUPPORTED
;
9604 /****************************************************************
9606 ****************************************************************/
9608 WERROR
_spoolss_DeletePort(pipes_struct
*p
,
9609 struct spoolss_DeletePort
*r
)
9611 p
->rng_fault_state
= true;
9612 return WERR_NOT_SUPPORTED
;
9615 /****************************************************************
9616 _spoolss_CreatePrinterIC
9617 ****************************************************************/
9619 WERROR
_spoolss_CreatePrinterIC(pipes_struct
*p
,
9620 struct spoolss_CreatePrinterIC
*r
)
9622 p
->rng_fault_state
= true;
9623 return WERR_NOT_SUPPORTED
;
9626 /****************************************************************
9627 _spoolss_PlayGDIScriptOnPrinterIC
9628 ****************************************************************/
9630 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(pipes_struct
*p
,
9631 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
9633 p
->rng_fault_state
= true;
9634 return WERR_NOT_SUPPORTED
;
9637 /****************************************************************
9638 _spoolss_DeletePrinterIC
9639 ****************************************************************/
9641 WERROR
_spoolss_DeletePrinterIC(pipes_struct
*p
,
9642 struct spoolss_DeletePrinterIC
*r
)
9644 p
->rng_fault_state
= true;
9645 return WERR_NOT_SUPPORTED
;
9648 /****************************************************************
9649 _spoolss_AddPrinterConnection
9650 ****************************************************************/
9652 WERROR
_spoolss_AddPrinterConnection(pipes_struct
*p
,
9653 struct spoolss_AddPrinterConnection
*r
)
9655 p
->rng_fault_state
= true;
9656 return WERR_NOT_SUPPORTED
;
9659 /****************************************************************
9660 _spoolss_DeletePrinterConnection
9661 ****************************************************************/
9663 WERROR
_spoolss_DeletePrinterConnection(pipes_struct
*p
,
9664 struct spoolss_DeletePrinterConnection
*r
)
9666 p
->rng_fault_state
= true;
9667 return WERR_NOT_SUPPORTED
;
9670 /****************************************************************
9671 _spoolss_PrinterMessageBox
9672 ****************************************************************/
9674 WERROR
_spoolss_PrinterMessageBox(pipes_struct
*p
,
9675 struct spoolss_PrinterMessageBox
*r
)
9677 p
->rng_fault_state
= true;
9678 return WERR_NOT_SUPPORTED
;
9681 /****************************************************************
9683 ****************************************************************/
9685 WERROR
_spoolss_AddMonitor(pipes_struct
*p
,
9686 struct spoolss_AddMonitor
*r
)
9688 p
->rng_fault_state
= true;
9689 return WERR_NOT_SUPPORTED
;
9692 /****************************************************************
9693 _spoolss_DeleteMonitor
9694 ****************************************************************/
9696 WERROR
_spoolss_DeleteMonitor(pipes_struct
*p
,
9697 struct spoolss_DeleteMonitor
*r
)
9699 p
->rng_fault_state
= true;
9700 return WERR_NOT_SUPPORTED
;
9703 /****************************************************************
9704 _spoolss_DeletePrintProcessor
9705 ****************************************************************/
9707 WERROR
_spoolss_DeletePrintProcessor(pipes_struct
*p
,
9708 struct spoolss_DeletePrintProcessor
*r
)
9710 p
->rng_fault_state
= true;
9711 return WERR_NOT_SUPPORTED
;
9714 /****************************************************************
9715 _spoolss_AddPrintProvidor
9716 ****************************************************************/
9718 WERROR
_spoolss_AddPrintProvidor(pipes_struct
*p
,
9719 struct spoolss_AddPrintProvidor
*r
)
9721 p
->rng_fault_state
= true;
9722 return WERR_NOT_SUPPORTED
;
9725 /****************************************************************
9726 _spoolss_DeletePrintProvidor
9727 ****************************************************************/
9729 WERROR
_spoolss_DeletePrintProvidor(pipes_struct
*p
,
9730 struct spoolss_DeletePrintProvidor
*r
)
9732 p
->rng_fault_state
= true;
9733 return WERR_NOT_SUPPORTED
;
9736 /****************************************************************
9737 _spoolss_FindFirstPrinterChangeNotification
9738 ****************************************************************/
9740 WERROR
_spoolss_FindFirstPrinterChangeNotification(pipes_struct
*p
,
9741 struct spoolss_FindFirstPrinterChangeNotification
*r
)
9743 p
->rng_fault_state
= true;
9744 return WERR_NOT_SUPPORTED
;
9747 /****************************************************************
9748 _spoolss_FindNextPrinterChangeNotification
9749 ****************************************************************/
9751 WERROR
_spoolss_FindNextPrinterChangeNotification(pipes_struct
*p
,
9752 struct spoolss_FindNextPrinterChangeNotification
*r
)
9754 p
->rng_fault_state
= true;
9755 return WERR_NOT_SUPPORTED
;
9758 /****************************************************************
9759 _spoolss_RouterFindFirstPrinterChangeNotificationOld
9760 ****************************************************************/
9762 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(pipes_struct
*p
,
9763 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
9765 p
->rng_fault_state
= true;
9766 return WERR_NOT_SUPPORTED
;
9769 /****************************************************************
9770 _spoolss_ReplyOpenPrinter
9771 ****************************************************************/
9773 WERROR
_spoolss_ReplyOpenPrinter(pipes_struct
*p
,
9774 struct spoolss_ReplyOpenPrinter
*r
)
9776 p
->rng_fault_state
= true;
9777 return WERR_NOT_SUPPORTED
;
9780 /****************************************************************
9781 _spoolss_RouterReplyPrinter
9782 ****************************************************************/
9784 WERROR
_spoolss_RouterReplyPrinter(pipes_struct
*p
,
9785 struct spoolss_RouterReplyPrinter
*r
)
9787 p
->rng_fault_state
= true;
9788 return WERR_NOT_SUPPORTED
;
9791 /****************************************************************
9792 _spoolss_ReplyClosePrinter
9793 ****************************************************************/
9795 WERROR
_spoolss_ReplyClosePrinter(pipes_struct
*p
,
9796 struct spoolss_ReplyClosePrinter
*r
)
9798 p
->rng_fault_state
= true;
9799 return WERR_NOT_SUPPORTED
;
9802 /****************************************************************
9804 ****************************************************************/
9806 WERROR
_spoolss_AddPortEx(pipes_struct
*p
,
9807 struct spoolss_AddPortEx
*r
)
9809 p
->rng_fault_state
= true;
9810 return WERR_NOT_SUPPORTED
;
9813 /****************************************************************
9814 _spoolss_RouterFindFirstPrinterChangeNotification
9815 ****************************************************************/
9817 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(pipes_struct
*p
,
9818 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
9820 p
->rng_fault_state
= true;
9821 return WERR_NOT_SUPPORTED
;
9824 /****************************************************************
9825 _spoolss_SpoolerInit
9826 ****************************************************************/
9828 WERROR
_spoolss_SpoolerInit(pipes_struct
*p
,
9829 struct spoolss_SpoolerInit
*r
)
9831 p
->rng_fault_state
= true;
9832 return WERR_NOT_SUPPORTED
;
9835 /****************************************************************
9836 _spoolss_ResetPrinterEx
9837 ****************************************************************/
9839 WERROR
_spoolss_ResetPrinterEx(pipes_struct
*p
,
9840 struct spoolss_ResetPrinterEx
*r
)
9842 p
->rng_fault_state
= true;
9843 return WERR_NOT_SUPPORTED
;
9846 /****************************************************************
9847 _spoolss_RouterReplyPrinterEx
9848 ****************************************************************/
9850 WERROR
_spoolss_RouterReplyPrinterEx(pipes_struct
*p
,
9851 struct spoolss_RouterReplyPrinterEx
*r
)
9853 p
->rng_fault_state
= true;
9854 return WERR_NOT_SUPPORTED
;
9857 /****************************************************************
9859 ****************************************************************/
9861 WERROR
_spoolss_44(pipes_struct
*p
,
9862 struct spoolss_44
*r
)
9864 p
->rng_fault_state
= true;
9865 return WERR_NOT_SUPPORTED
;
9868 /****************************************************************
9870 ****************************************************************/
9872 WERROR
_spoolss_47(pipes_struct
*p
,
9873 struct spoolss_47
*r
)
9875 p
->rng_fault_state
= true;
9876 return WERR_NOT_SUPPORTED
;
9879 /****************************************************************
9881 ****************************************************************/
9883 WERROR
_spoolss_4a(pipes_struct
*p
,
9884 struct spoolss_4a
*r
)
9886 p
->rng_fault_state
= true;
9887 return WERR_NOT_SUPPORTED
;
9890 /****************************************************************
9892 ****************************************************************/
9894 WERROR
_spoolss_4b(pipes_struct
*p
,
9895 struct spoolss_4b
*r
)
9897 p
->rng_fault_state
= true;
9898 return WERR_NOT_SUPPORTED
;
9901 /****************************************************************
9903 ****************************************************************/
9905 WERROR
_spoolss_4c(pipes_struct
*p
,
9906 struct spoolss_4c
*r
)
9908 p
->rng_fault_state
= true;
9909 return WERR_NOT_SUPPORTED
;
9912 /****************************************************************
9914 ****************************************************************/
9916 WERROR
_spoolss_53(pipes_struct
*p
,
9917 struct spoolss_53
*r
)
9919 p
->rng_fault_state
= true;
9920 return WERR_NOT_SUPPORTED
;
9923 /****************************************************************
9925 ****************************************************************/
9927 WERROR
_spoolss_55(pipes_struct
*p
,
9928 struct spoolss_55
*r
)
9930 p
->rng_fault_state
= true;
9931 return WERR_NOT_SUPPORTED
;
9934 /****************************************************************
9936 ****************************************************************/
9938 WERROR
_spoolss_56(pipes_struct
*p
,
9939 struct spoolss_56
*r
)
9941 p
->rng_fault_state
= true;
9942 return WERR_NOT_SUPPORTED
;
9945 /****************************************************************
9947 ****************************************************************/
9949 WERROR
_spoolss_57(pipes_struct
*p
,
9950 struct spoolss_57
*r
)
9952 p
->rng_fault_state
= true;
9953 return WERR_NOT_SUPPORTED
;
9956 /****************************************************************
9958 ****************************************************************/
9960 WERROR
_spoolss_5a(pipes_struct
*p
,
9961 struct spoolss_5a
*r
)
9963 p
->rng_fault_state
= true;
9964 return WERR_NOT_SUPPORTED
;
9967 /****************************************************************
9969 ****************************************************************/
9971 WERROR
_spoolss_5b(pipes_struct
*p
,
9972 struct spoolss_5b
*r
)
9974 p
->rng_fault_state
= true;
9975 return WERR_NOT_SUPPORTED
;
9978 /****************************************************************
9980 ****************************************************************/
9982 WERROR
_spoolss_5c(pipes_struct
*p
,
9983 struct spoolss_5c
*r
)
9985 p
->rng_fault_state
= true;
9986 return WERR_NOT_SUPPORTED
;
9989 /****************************************************************
9991 ****************************************************************/
9993 WERROR
_spoolss_5d(pipes_struct
*p
,
9994 struct spoolss_5d
*r
)
9996 p
->rng_fault_state
= true;
9997 return WERR_NOT_SUPPORTED
;
10000 /****************************************************************
10002 ****************************************************************/
10004 WERROR
_spoolss_5e(pipes_struct
*p
,
10005 struct spoolss_5e
*r
)
10007 p
->rng_fault_state
= true;
10008 return WERR_NOT_SUPPORTED
;
10011 /****************************************************************
10013 ****************************************************************/
10015 WERROR
_spoolss_5f(pipes_struct
*p
,
10016 struct spoolss_5f
*r
)
10018 p
->rng_fault_state
= true;
10019 return WERR_NOT_SUPPORTED
;
10022 /****************************************************************
10024 ****************************************************************/
10026 WERROR
_spoolss_60(pipes_struct
*p
,
10027 struct spoolss_60
*r
)
10029 p
->rng_fault_state
= true;
10030 return WERR_NOT_SUPPORTED
;
10033 /****************************************************************
10035 ****************************************************************/
10037 WERROR
_spoolss_61(pipes_struct
*p
,
10038 struct spoolss_61
*r
)
10040 p
->rng_fault_state
= true;
10041 return WERR_NOT_SUPPORTED
;
10044 /****************************************************************
10046 ****************************************************************/
10048 WERROR
_spoolss_62(pipes_struct
*p
,
10049 struct spoolss_62
*r
)
10051 p
->rng_fault_state
= true;
10052 return WERR_NOT_SUPPORTED
;
10055 /****************************************************************
10057 ****************************************************************/
10059 WERROR
_spoolss_63(pipes_struct
*p
,
10060 struct spoolss_63
*r
)
10062 p
->rng_fault_state
= true;
10063 return WERR_NOT_SUPPORTED
;
10066 /****************************************************************
10068 ****************************************************************/
10070 WERROR
_spoolss_64(pipes_struct
*p
,
10071 struct spoolss_64
*r
)
10073 p
->rng_fault_state
= true;
10074 return WERR_NOT_SUPPORTED
;
10077 /****************************************************************
10079 ****************************************************************/
10081 WERROR
_spoolss_65(pipes_struct
*p
,
10082 struct spoolss_65
*r
)
10084 p
->rng_fault_state
= true;
10085 return WERR_NOT_SUPPORTED
;
10088 /****************************************************************
10089 _spoolss_GetCorePrinterDrivers
10090 ****************************************************************/
10092 WERROR
_spoolss_GetCorePrinterDrivers(pipes_struct
*p
,
10093 struct spoolss_GetCorePrinterDrivers
*r
)
10095 p
->rng_fault_state
= true;
10096 return WERR_NOT_SUPPORTED
;
10099 /****************************************************************
10101 ****************************************************************/
10103 WERROR
_spoolss_67(pipes_struct
*p
,
10104 struct spoolss_67
*r
)
10106 p
->rng_fault_state
= true;
10107 return WERR_NOT_SUPPORTED
;
10110 /****************************************************************
10111 _spoolss_GetPrinterDriverPackagePath
10112 ****************************************************************/
10114 WERROR
_spoolss_GetPrinterDriverPackagePath(pipes_struct
*p
,
10115 struct spoolss_GetPrinterDriverPackagePath
*r
)
10117 p
->rng_fault_state
= true;
10118 return WERR_NOT_SUPPORTED
;
10121 /****************************************************************
10123 ****************************************************************/
10125 WERROR
_spoolss_69(pipes_struct
*p
,
10126 struct spoolss_69
*r
)
10128 p
->rng_fault_state
= true;
10129 return WERR_NOT_SUPPORTED
;
10132 /****************************************************************
10134 ****************************************************************/
10136 WERROR
_spoolss_6a(pipes_struct
*p
,
10137 struct spoolss_6a
*r
)
10139 p
->rng_fault_state
= true;
10140 return WERR_NOT_SUPPORTED
;
10143 /****************************************************************
10145 ****************************************************************/
10147 WERROR
_spoolss_6b(pipes_struct
*p
,
10148 struct spoolss_6b
*r
)
10150 p
->rng_fault_state
= true;
10151 return WERR_NOT_SUPPORTED
;
10154 /****************************************************************
10156 ****************************************************************/
10158 WERROR
_spoolss_6c(pipes_struct
*p
,
10159 struct spoolss_6c
*r
)
10161 p
->rng_fault_state
= true;
10162 return WERR_NOT_SUPPORTED
;
10165 /****************************************************************
10167 ****************************************************************/
10169 WERROR
_spoolss_6d(pipes_struct
*p
,
10170 struct spoolss_6d
*r
)
10172 p
->rng_fault_state
= true;
10173 return WERR_NOT_SUPPORTED
;