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.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
44 #include "../librpc/gen_ndr/netlogon.h"
46 #include "printing/notify.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "rpc_client/cli_winreg_spoolss.h"
58 /* macros stolen from s4 spoolss server */
59 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
60 ((info)?ndr_size_##fn(info, level, 0):0)
62 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
63 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
65 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
66 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
68 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
71 #define DBGC_CLASS DBGC_RPC_SRV
73 #ifndef MAX_OPEN_PRINTER_EXS
74 #define MAX_OPEN_PRINTER_EXS 50
77 struct notify_back_channel
;
79 /* structure to store the printer handles */
80 /* and a reference to what it's pointing to */
81 /* and the notify info asked about */
82 /* that's the central struct */
83 struct printer_handle
{
84 struct printer_handle
*prev
, *next
;
85 bool document_started
;
87 uint32 jobid
; /* jobid in printing backend */
89 const char *servername
;
92 uint32 access_granted
;
98 struct spoolss_NotifyOption
*option
;
99 struct policy_handle cli_hnd
;
100 struct notify_back_channel
*cli_chan
;
102 /* are we in a FindNextPrinterChangeNotify() call? */
104 struct messaging_context
*msg_ctx
;
111 /* devmode sent in the OpenPrinter() call */
112 struct spoolss_DeviceMode
*devmode
;
114 /* TODO cache the printer info2 structure */
115 struct spoolss_PrinterInfo2
*info2
;
119 static struct printer_handle
*printers_list
;
121 struct printer_session_counter
{
122 struct printer_session_counter
*next
;
123 struct printer_session_counter
*prev
;
129 static struct printer_session_counter
*counter_list
;
131 struct notify_back_channel
{
132 struct notify_back_channel
*prev
, *next
;
134 /* associated client */
135 struct sockaddr_storage client_address
;
137 /* print notify back-channel pipe handle*/
138 struct rpc_pipe_client
*cli_pipe
;
139 struct dcerpc_binding_handle
*binding_handle
;
140 uint32_t active_connections
;
143 static struct notify_back_channel
*back_channels
;
145 /* Map generic permissions to printer object specific permissions */
147 const struct standard_mapping printer_std_mapping
= {
154 /* Map generic permissions to print server object specific permissions */
156 const struct standard_mapping printserver_std_mapping
= {
163 /* API table for Xcv Monitor functions */
165 struct xcv_api_table
{
167 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, struct security_token
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
170 static void prune_printername_cache(void);
172 /********************************************************************
173 * Canonicalize servername.
174 ********************************************************************/
176 static const char *canon_servername(const char *servername
)
178 const char *pservername
= servername
;
179 while (*pservername
== '\\') {
185 /* translate between internal status numbers and NT status numbers */
186 static int nt_printj_status(int v
)
192 return JOB_STATUS_PAUSED
;
194 return JOB_STATUS_SPOOLING
;
196 return JOB_STATUS_PRINTING
;
198 return JOB_STATUS_ERROR
;
200 return JOB_STATUS_DELETING
;
202 return JOB_STATUS_OFFLINE
;
204 return JOB_STATUS_PAPEROUT
;
206 return JOB_STATUS_PRINTED
;
208 return JOB_STATUS_DELETED
;
210 return JOB_STATUS_BLOCKED_DEVQ
;
211 case LPQ_USER_INTERVENTION
:
212 return JOB_STATUS_USER_INTERVENTION
;
217 static int nt_printq_status(int v
)
221 return PRINTER_STATUS_PAUSED
;
230 /***************************************************************************
231 Disconnect from the client
232 ****************************************************************************/
234 static void srv_spoolss_replycloseprinter(int snum
,
235 struct printer_handle
*prn_hnd
)
241 * Tell the specific printing tdb we no longer want messages for this printer
242 * by deregistering our PID.
245 if (!print_notify_deregister_pid(snum
)) {
246 DEBUG(0, ("Failed to register our pid for printer %s\n",
247 lp_const_servicename(snum
)));
250 /* weird if the test succeeds !!! */
251 if (prn_hnd
->notify
.cli_chan
== NULL
||
252 prn_hnd
->notify
.cli_chan
->active_connections
== 0) {
253 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
254 DLIST_REMOVE(back_channels
, prn_hnd
->notify
.cli_chan
);
255 TALLOC_FREE(prn_hnd
->notify
.cli_chan
);
259 status
= dcerpc_spoolss_ReplyClosePrinter(
260 prn_hnd
->notify
.cli_chan
->binding_handle
,
262 &prn_hnd
->notify
.cli_hnd
,
264 if (!NT_STATUS_IS_OK(status
)) {
265 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
267 result
= ntstatus_to_werror(status
);
268 } else if (!W_ERROR_IS_OK(result
)) {
269 DEBUG(0, ("reply_close_printer failed [%s].\n",
270 win_errstr(result
)));
273 /* if it's the last connection, deconnect the IPC$ share */
274 if (prn_hnd
->notify
.cli_chan
->active_connections
== 1) {
276 prn_hnd
->notify
.cli_chan
->binding_handle
= NULL
;
277 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd
->notify
.cli_chan
->cli_pipe
));
278 DLIST_REMOVE(back_channels
, prn_hnd
->notify
.cli_chan
);
279 TALLOC_FREE(prn_hnd
->notify
.cli_chan
);
281 if (prn_hnd
->notify
.msg_ctx
!= NULL
) {
282 messaging_deregister(prn_hnd
->notify
.msg_ctx
,
283 MSG_PRINTER_NOTIFY2
, NULL
);
286 * Tell the serverid.tdb we're no longer
287 * interested in printer notify messages.
290 serverid_register_msg_flags(
291 messaging_server_id(prn_hnd
->notify
.msg_ctx
),
292 false, FLAG_MSG_PRINT_NOTIFY
);
296 if (prn_hnd
->notify
.cli_chan
) {
297 prn_hnd
->notify
.cli_chan
->active_connections
--;
298 prn_hnd
->notify
.cli_chan
= NULL
;
302 /****************************************************************************
303 Functions to free a printer entry datastruct.
304 ****************************************************************************/
306 static int printer_entry_destructor(struct printer_handle
*Printer
)
308 if (Printer
->notify
.cli_chan
!= NULL
&&
309 Printer
->notify
.cli_chan
->active_connections
> 0) {
312 switch(Printer
->printer_type
) {
314 srv_spoolss_replycloseprinter(snum
, Printer
);
318 snum
= print_queue_snum(Printer
->sharename
);
320 srv_spoolss_replycloseprinter(snum
, Printer
);
328 Printer
->notify
.flags
=0;
329 Printer
->notify
.options
=0;
330 Printer
->notify
.localmachine
[0]='\0';
331 Printer
->notify
.printerlocal
=0;
332 TALLOC_FREE(Printer
->notify
.option
);
333 TALLOC_FREE(Printer
->devmode
);
335 /* Remove from the internal list. */
336 DLIST_REMOVE(printers_list
, Printer
);
340 /****************************************************************************
341 find printer index by handle
342 ****************************************************************************/
344 static struct printer_handle
*find_printer_index_by_hnd(struct pipes_struct
*p
,
345 struct policy_handle
*hnd
)
347 struct printer_handle
*find_printer
= NULL
;
349 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
350 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
357 /****************************************************************************
358 Close printer index by handle.
359 ****************************************************************************/
361 static bool close_printer_handle(struct pipes_struct
*p
, struct policy_handle
*hnd
)
363 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
366 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
371 close_policy_hnd(p
, hnd
);
376 /****************************************************************************
377 Delete a printer given a handle.
378 ****************************************************************************/
380 static WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, struct security_token
*token
,
381 const char *sharename
,
382 struct messaging_context
*msg_ctx
)
384 char *cmd
= lp_deleteprinter_cmd();
385 char *command
= NULL
;
387 bool is_print_op
= false;
389 /* can't fail if we don't try */
394 command
= talloc_asprintf(ctx
,
401 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
403 DEBUG(10,("Running [%s]\n", command
));
405 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
410 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
411 /* Tell everyone we updated smb.conf. */
412 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
418 /********** END SePrintOperatorPrivlege BLOCK **********/
420 DEBUGADD(10,("returned [%d]\n", ret
));
422 TALLOC_FREE(command
);
425 return WERR_BADFID
; /* What to return here? */
427 /* go ahead and re-read the services immediately */
429 reload_services(msg_ctx
, -1, false);
432 if ( lp_servicenumber( sharename
) >= 0 )
433 return WERR_ACCESS_DENIED
;
438 /****************************************************************************
439 Delete a printer given a handle.
440 ****************************************************************************/
442 static WERROR
delete_printer_handle(struct pipes_struct
*p
, struct policy_handle
*hnd
)
444 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
448 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
454 * It turns out that Windows allows delete printer on a handle
455 * opened by an admin user, then used on a pipe handle created
456 * by an anonymous user..... but they're working on security.... riiight !
460 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
461 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
462 return WERR_ACCESS_DENIED
;
465 /* this does not need a become root since the access check has been
466 done on the handle already */
468 result
= winreg_delete_printer_key_internal(p
->mem_ctx
,
469 get_session_info_system(),
473 if (!W_ERROR_IS_OK(result
)) {
474 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
478 result
= delete_printer_hook(p
->mem_ctx
, p
->session_info
->security_token
,
479 Printer
->sharename
, p
->msg_ctx
);
480 if (!W_ERROR_IS_OK(result
)) {
483 prune_printername_cache();
487 /****************************************************************************
488 Return the snum of a printer corresponding to an handle.
489 ****************************************************************************/
491 static bool get_printer_snum(struct pipes_struct
*p
, struct policy_handle
*hnd
,
492 int *number
, struct share_params
**params
)
494 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
497 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
502 switch (Printer
->printer_type
) {
504 DEBUG(4,("short name:%s\n", Printer
->sharename
));
505 *number
= print_queue_snum(Printer
->sharename
);
506 return (*number
!= -1);
514 /****************************************************************************
515 Set printer handle type.
516 Check if it's \\server or \\server\printer
517 ****************************************************************************/
519 static bool set_printer_hnd_printertype(struct printer_handle
*Printer
, const char *handlename
)
521 DEBUG(3,("Setting printer type=%s\n", handlename
));
523 /* it's a print server */
524 if (handlename
&& *handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
525 DEBUGADD(4,("Printer is a print server\n"));
526 Printer
->printer_type
= SPLHND_SERVER
;
528 /* it's a printer (set_printer_hnd_name() will handle port monitors */
530 DEBUGADD(4,("Printer is a printer\n"));
531 Printer
->printer_type
= SPLHND_PRINTER
;
537 static void prune_printername_cache_fn(const char *key
, const char *value
,
538 time_t timeout
, void *private_data
)
543 static void prune_printername_cache(void)
545 gencache_iterate(prune_printername_cache_fn
, NULL
, "PRINTERNAME/*");
548 /****************************************************************************
549 Set printer handle name.. Accept names like \\server, \\server\printer,
550 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
551 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
552 XcvDataPort() interface.
553 ****************************************************************************/
555 static WERROR
set_printer_hnd_name(TALLOC_CTX
*mem_ctx
,
556 const struct auth_serversupplied_info
*session_info
,
557 struct messaging_context
*msg_ctx
,
558 struct printer_handle
*Printer
,
559 const char *handlename
)
562 int n_services
=lp_numservices();
564 const char *printername
;
565 const char *servername
= NULL
;
568 struct spoolss_PrinterInfo2
*info2
= NULL
;
573 * Hopefully nobody names his printers like this. Maybe \ or ,
574 * are illegal in printer names even?
576 const char printer_not_found
[] = "Printer \\, !@#$%^&*( not found";
580 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
,
581 (unsigned long)strlen(handlename
)));
583 aprinter
= CONST_DISCARD(char *, handlename
);
584 if ( *handlename
== '\\' ) {
585 servername
= canon_servername(handlename
);
586 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
590 if (!is_myname_or_ipaddr(servername
)) {
591 return WERR_INVALID_PRINTER_NAME
;
593 Printer
->servername
= talloc_asprintf(Printer
, "\\\\%s", servername
);
594 if (Printer
->servername
== NULL
) {
599 if (Printer
->printer_type
== SPLHND_SERVER
) {
603 if (Printer
->printer_type
!= SPLHND_PRINTER
) {
604 return WERR_INVALID_HANDLE
;
607 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
609 p
= strchr(aprinter
, ',');
616 if (strncmp(p
, "DrvConvert", strlen("DrvConvert")) == 0) {
618 } else if (strncmp(p
, "LocalOnly", strlen("LocalOnly")) == 0) {
624 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter
));
627 /* check for the Port Monitor Interface */
628 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
629 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
630 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
633 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
634 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
635 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
640 * With hundreds of printers, the "for" loop iterating all
641 * shares can be quite expensive, as it is done on every
642 * OpenPrinter. The loop maps "aprinter" to "sname", the
643 * result of which we cache in gencache.
646 cache_key
= talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
648 if ((cache_key
!= NULL
) && gencache_get(cache_key
, &tmp
, NULL
)) {
650 found
= (strcmp(tmp
, printer_not_found
) != 0);
652 DEBUG(4, ("Printer %s not found\n", aprinter
));
654 return WERR_INVALID_PRINTER_NAME
;
660 /* Search all sharenames first as this is easier than pulling
661 the printer_info_2 off of disk. Don't use find_service() since
662 that calls out to map_username() */
664 /* do another loop to look for printernames */
665 for (snum
= 0; !found
&& snum
< n_services
; snum
++) {
666 const char *printer
= lp_const_servicename(snum
);
668 /* no point going on if this is not a printer */
669 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
))) {
673 /* ignore [printers] share */
674 if (strequal(printer
, "printers")) {
678 fstrcpy(sname
, printer
);
679 if (strequal(aprinter
, printer
)) {
684 /* no point looking up the printer object if
685 we aren't allowing printername != sharename */
686 if (lp_force_printername(snum
)) {
690 result
= winreg_get_printer_internal(mem_ctx
,
695 if ( !W_ERROR_IS_OK(result
) ) {
696 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
697 sname
, win_errstr(result
)));
701 printername
= strrchr(info2
->printername
, '\\');
702 if (printername
== NULL
) {
703 printername
= info2
->printername
;
708 if (strequal(printername
, aprinter
)) {
713 DEBUGADD(10, ("printername: %s\n", printername
));
719 if (cache_key
!= NULL
) {
720 gencache_set(cache_key
, printer_not_found
,
722 TALLOC_FREE(cache_key
);
724 DEBUGADD(4,("Printer not found\n"));
725 return WERR_INVALID_PRINTER_NAME
;
728 if (cache_key
!= NULL
) {
729 gencache_set(cache_key
, sname
, time(NULL
)+300);
730 TALLOC_FREE(cache_key
);
733 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
735 fstrcpy(Printer
->sharename
, sname
);
740 /****************************************************************************
741 Find first available printer slot. creates a printer handle for you.
742 ****************************************************************************/
744 static WERROR
open_printer_hnd(struct pipes_struct
*p
,
745 struct policy_handle
*hnd
,
747 uint32_t access_granted
)
749 struct printer_handle
*new_printer
;
752 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
754 new_printer
= talloc_zero(p
->mem_ctx
, struct printer_handle
);
755 if (new_printer
== NULL
) {
758 talloc_set_destructor(new_printer
, printer_entry_destructor
);
760 /* This also steals the printer_handle on the policy_handle */
761 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
762 TALLOC_FREE(new_printer
);
763 return WERR_INVALID_HANDLE
;
766 /* Add to the internal list. */
767 DLIST_ADD(printers_list
, new_printer
);
769 new_printer
->notify
.option
=NULL
;
771 if (!set_printer_hnd_printertype(new_printer
, name
)) {
772 close_printer_handle(p
, hnd
);
773 return WERR_INVALID_HANDLE
;
776 result
= set_printer_hnd_name(p
->mem_ctx
,
777 get_session_info_system(),
780 if (!W_ERROR_IS_OK(result
)) {
781 close_printer_handle(p
, hnd
);
785 new_printer
->access_granted
= access_granted
;
787 DEBUG(5, ("%d printer handles active\n",
788 (int)num_pipe_handles(p
)));
793 /***************************************************************************
794 check to see if the client motify handle is monitoring the notification
795 given by (notify_type, notify_field).
796 **************************************************************************/
798 static bool is_monitoring_event_flags(uint32_t flags
, uint16_t notify_type
,
799 uint16_t notify_field
)
804 static bool is_monitoring_event(struct printer_handle
*p
, uint16_t notify_type
,
805 uint16_t notify_field
)
807 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
811 * Flags should always be zero when the change notify
812 * is registered by the client's spooler. A user Win32 app
813 * might use the flags though instead of the NOTIFY_OPTION_INFO
822 return is_monitoring_event_flags(
823 p
->notify
.flags
, notify_type
, notify_field
);
825 for (i
= 0; i
< option
->count
; i
++) {
827 /* Check match for notify_type */
829 if (option
->types
[i
].type
!= notify_type
)
832 /* Check match for field */
834 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
835 if (option
->types
[i
].fields
[j
].field
== notify_field
) {
841 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
842 p
->servername
, p
->sharename
, notify_type
, notify_field
));
847 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
848 _data->data.integer[0] = _integer; \
849 _data->data.integer[1] = 0;
852 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
853 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
854 if (!_data->data.string.string) {\
855 _data->data.string.size = 0; \
857 _data->data.string.size = strlen_m_term(_p) * 2;
859 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
860 _data->data.devmode.devmode = _devmode;
862 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
863 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
864 if (!_data->data.sd.sd) { \
865 _data->data.sd.sd_size = 0; \
867 _data->data.sd.sd_size = \
868 ndr_size_security_descriptor(_data->data.sd.sd, 0);
870 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
875 struct spoolss_Time st
;
879 if (!init_systemtime(&st
, t
)) {
883 p
= talloc_array(mem_ctx
, char, len
);
889 * Systemtime must be linearized as a set of UINT16's.
890 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
893 SSVAL(p
, 0, st
.year
);
894 SSVAL(p
, 2, st
.month
);
895 SSVAL(p
, 4, st
.day_of_week
);
897 SSVAL(p
, 8, st
.hour
);
898 SSVAL(p
, 10, st
.minute
);
899 SSVAL(p
, 12, st
.second
);
900 SSVAL(p
, 14, st
.millisecond
);
906 /* Convert a notification message to a struct spoolss_Notify */
908 static void notify_one_value(struct spoolss_notify_msg
*msg
,
909 struct spoolss_Notify
*data
,
912 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
915 static void notify_string(struct spoolss_notify_msg
*msg
,
916 struct spoolss_Notify
*data
,
919 /* The length of the message includes the trailing \0 */
921 data
->data
.string
.size
= msg
->len
* 2;
922 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
923 if (!data
->data
.string
.string
) {
924 data
->data
.string
.size
= 0;
929 static void notify_system_time(struct spoolss_notify_msg
*msg
,
930 struct spoolss_Notify
*data
,
933 data
->data
.string
.string
= NULL
;
934 data
->data
.string
.size
= 0;
936 if (msg
->len
!= sizeof(time_t)) {
937 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
942 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
943 &data
->data
.string
.string
,
944 &data
->data
.string
.size
);
947 struct notify2_message_table
{
949 void (*fn
)(struct spoolss_notify_msg
*msg
,
950 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
953 static struct notify2_message_table printer_notify_table
[] = {
954 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string
},
955 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string
},
956 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string
},
957 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string
},
958 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string
},
959 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string
},
960 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string
},
961 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL
},
962 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string
},
963 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string
},
964 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL
},
965 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string
},
966 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
967 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value
},
968 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value
},
969 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL
},
970 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL
},
971 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL
},
972 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value
},
975 static struct notify2_message_table job_notify_table
[] = {
976 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL
},
977 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL
},
978 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL
},
979 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string
},
980 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL
},
981 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL
},
982 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL
},
983 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL
},
984 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL
},
985 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL
},
986 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value
},
987 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL
},
988 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
989 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string
},
990 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL
},
991 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL
},
992 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time
},
993 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL
},
994 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL
},
995 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL
},
996 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value
},
997 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL
},
998 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value
},
999 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL
},
1003 /***********************************************************************
1004 Allocate talloc context for container object
1005 **********************************************************************/
1007 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1012 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
1017 /***********************************************************************
1018 release all allocated memory and zero out structure
1019 **********************************************************************/
1021 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1027 talloc_destroy(ctr
->ctx
);
1034 /***********************************************************************
1035 **********************************************************************/
1037 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1045 /***********************************************************************
1046 **********************************************************************/
1048 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
1050 if ( !ctr
|| !ctr
->msg_groups
)
1053 if ( idx
>= ctr
->num_groups
)
1056 return &ctr
->msg_groups
[idx
];
1060 /***********************************************************************
1061 How many groups of change messages do we have ?
1062 **********************************************************************/
1064 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1069 return ctr
->num_groups
;
1072 /***********************************************************************
1073 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1074 **********************************************************************/
1076 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
1078 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
1079 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
1080 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
1086 /* loop over all groups looking for a matching printer name */
1088 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
1089 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
1093 /* add a new group? */
1095 if ( i
== ctr
->num_groups
) {
1098 if ( !(groups
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
1099 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1102 ctr
->msg_groups
= groups
;
1104 /* clear the new entry and set the printer name */
1106 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
1107 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
1110 /* add the change messages; 'i' is the correct index now regardless */
1112 msg_grp
= &ctr
->msg_groups
[i
];
1114 msg_grp
->num_msgs
++;
1116 if ( !(msg_list
= TALLOC_REALLOC_ARRAY( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
1117 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
1120 msg_grp
->msgs
= msg_list
;
1122 new_slot
= msg_grp
->num_msgs
-1;
1123 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
1125 /* need to allocate own copy of data */
1127 if ( msg
->len
!= 0 )
1128 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
1129 TALLOC_MEMDUP( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
1131 return ctr
->num_groups
;
1134 static void construct_info_data(struct spoolss_Notify
*info_data
,
1135 enum spoolss_NotifyType type
,
1136 uint16_t field
, int id
);
1138 /***********************************************************************
1139 Send a change notication message on all handles which have a call
1141 **********************************************************************/
1143 static int build_notify2_messages(TALLOC_CTX
*mem_ctx
,
1144 struct printer_handle
*prn_hnd
,
1145 SPOOLSS_NOTIFY_MSG
*messages
,
1147 struct spoolss_Notify
**_notifies
,
1150 struct spoolss_Notify
*notifies
;
1151 SPOOLSS_NOTIFY_MSG
*msg
;
1156 notifies
= talloc_zero_array(mem_ctx
,
1157 struct spoolss_Notify
, num_msgs
);
1162 for (i
= 0; i
< num_msgs
; i
++) {
1166 /* Are we monitoring this event? */
1168 if (!is_monitoring_event(prn_hnd
, msg
->type
, msg
->field
)) {
1172 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1173 "for printer [%s]\n",
1174 msg
->type
, msg
->field
, prn_hnd
->sharename
));
1177 * if the is a printer notification handle and not a job
1178 * notification type, then set the id to 0.
1179 * Otherwise just use what was specified in the message.
1181 * When registering change notification on a print server
1182 * handle we always need to send back the id (snum) matching
1183 * the printer for which the change took place.
1184 * For change notify registered on a printer handle,
1185 * this does not matter and the id should be 0.
1190 if ((msg
->type
== PRINTER_NOTIFY_TYPE
) &&
1191 (prn_hnd
->printer_type
== SPLHND_PRINTER
)) {
1197 /* Convert unix jobid to smb jobid */
1199 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1200 id
= sysjob_to_jobid(msg
->id
);
1203 DEBUG(3, ("no such unix jobid %d\n",
1209 construct_info_data(¬ifies
[count
],
1210 msg
->type
, msg
->field
, id
);
1213 case PRINTER_NOTIFY_TYPE
:
1214 if (printer_notify_table
[msg
->field
].fn
) {
1215 printer_notify_table
[msg
->field
].fn(msg
,
1216 ¬ifies
[count
], mem_ctx
);
1220 case JOB_NOTIFY_TYPE
:
1221 if (job_notify_table
[msg
->field
].fn
) {
1222 job_notify_table
[msg
->field
].fn(msg
,
1223 ¬ifies
[count
], mem_ctx
);
1228 DEBUG(5, ("Unknown notification type %d\n",
1236 *_notifies
= notifies
;
1242 static int send_notify2_printer(TALLOC_CTX
*mem_ctx
,
1243 struct printer_handle
*prn_hnd
,
1244 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
)
1246 struct spoolss_Notify
*notifies
;
1248 union spoolss_ReplyPrinterInfo info
;
1249 struct spoolss_NotifyInfo info0
;
1250 uint32_t reply_result
;
1255 /* Is there notification on this handle? */
1256 if (prn_hnd
->notify
.cli_chan
== NULL
||
1257 prn_hnd
->notify
.cli_chan
->active_connections
== 0) {
1261 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1262 prn_hnd
->servername
, prn_hnd
->sharename
));
1264 /* For this printer? Print servers always receive notifications. */
1265 if ((prn_hnd
->printer_type
== SPLHND_PRINTER
) &&
1266 (!strequal(msg_group
->printername
, prn_hnd
->sharename
))) {
1270 DEBUG(10,("Our printer\n"));
1272 /* build the array of change notifications */
1273 ret
= build_notify2_messages(mem_ctx
, prn_hnd
,
1275 msg_group
->num_msgs
,
1281 info0
.version
= 0x2;
1282 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1283 info0
.count
= count
;
1284 info0
.notifies
= notifies
;
1286 info
.info0
= &info0
;
1288 status
= dcerpc_spoolss_RouterReplyPrinterEx(
1289 prn_hnd
->notify
.cli_chan
->binding_handle
,
1291 &prn_hnd
->notify
.cli_hnd
,
1292 prn_hnd
->notify
.change
, /* color */
1293 prn_hnd
->notify
.flags
,
1295 0, /* reply_type, must be 0 */
1297 if (!NT_STATUS_IS_OK(status
)) {
1298 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1300 prn_hnd
->notify
.cli_chan
->cli_pipe
->srv_name_slash
,
1301 nt_errstr(status
)));
1302 werr
= ntstatus_to_werror(status
);
1303 } else if (!W_ERROR_IS_OK(werr
)) {
1304 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1306 prn_hnd
->notify
.cli_chan
->cli_pipe
->srv_name_slash
,
1309 switch (reply_result
) {
1312 case PRINTER_NOTIFY_INFO_DISCARDED
:
1313 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1314 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1323 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
1325 struct printer_handle
*p
;
1326 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
1327 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
1331 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1335 if (!msg_group
->msgs
) {
1336 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1340 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
1342 /* loop over all printers */
1344 for (p
= printers_list
; p
; p
= p
->next
) {
1345 ret
= send_notify2_printer(mem_ctx
, p
, msg_group
);
1352 DEBUG(8,("send_notify2_changes: Exit...\n"));
1356 /***********************************************************************
1357 **********************************************************************/
1359 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1362 uint32_t tv_sec
, tv_usec
;
1365 /* Unpack message */
1367 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "f",
1370 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "ddddddd",
1372 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1375 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "dd",
1376 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1378 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "B",
1379 &msg
->len
, &msg
->notify
.data
);
1381 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1382 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1384 tv
->tv_sec
= tv_sec
;
1385 tv
->tv_usec
= tv_usec
;
1388 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1389 msg
->notify
.value
[1]));
1391 dump_data(3, (uint8_t *)msg
->notify
.data
, msg
->len
);
1396 /********************************************************************
1397 Receive a notify2 message list
1398 ********************************************************************/
1400 static void receive_notify2_message_list(struct messaging_context
*msg
,
1403 struct server_id server_id
,
1406 size_t msg_count
, i
;
1407 char *buf
= (char *)data
->data
;
1410 SPOOLSS_NOTIFY_MSG notify
;
1411 SPOOLSS_NOTIFY_MSG_CTR messages
;
1414 if (data
->length
< 4) {
1415 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1419 msg_count
= IVAL(buf
, 0);
1422 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1424 if (msg_count
== 0) {
1425 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1429 /* initialize the container */
1431 ZERO_STRUCT( messages
);
1432 notify_msg_ctr_init( &messages
);
1435 * build message groups for each printer identified
1436 * in a change_notify msg. Remember that a PCN message
1437 * includes the handle returned for the srv_spoolss_replyopenprinter()
1438 * call. Therefore messages are grouped according to printer handle.
1441 for ( i
=0; i
<msg_count
; i
++ ) {
1442 struct timeval msg_tv
;
1444 if (msg_ptr
+ 4 - buf
> data
->length
) {
1445 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1449 msg_len
= IVAL(msg_ptr
,0);
1452 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1453 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1457 /* unpack messages */
1459 ZERO_STRUCT( notify
);
1460 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1463 /* add to correct list in container */
1465 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1467 /* free memory that might have been allocated by notify2_unpack_msg() */
1469 if ( notify
.len
!= 0 )
1470 SAFE_FREE( notify
.notify
.data
);
1473 /* process each group of messages */
1475 num_groups
= notify_msg_ctr_numgroups( &messages
);
1476 for ( i
=0; i
<num_groups
; i
++ )
1477 send_notify2_changes( &messages
, i
);
1482 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1483 (uint32_t)msg_count
));
1485 notify_msg_ctr_destroy( &messages
);
1490 /********************************************************************
1491 Send a message to ourself about new driver being installed
1492 so we can upgrade the information for each printer bound to this
1494 ********************************************************************/
1496 static bool srv_spoolss_drv_upgrade_printer(const char *drivername
,
1497 struct messaging_context
*msg_ctx
)
1499 int len
= strlen(drivername
);
1504 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1507 messaging_send_buf(msg_ctx
, messaging_server_id(msg_ctx
),
1508 MSG_PRINTER_DRVUPGRADE
,
1509 (uint8_t *)drivername
, len
+1);
1514 void srv_spoolss_cleanup(void)
1516 struct printer_session_counter
*session_counter
;
1518 for (session_counter
= counter_list
;
1519 session_counter
!= NULL
;
1520 session_counter
= counter_list
) {
1521 DLIST_REMOVE(counter_list
, session_counter
);
1522 TALLOC_FREE(session_counter
);
1526 /**********************************************************************
1527 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1528 over all printers, upgrading ones as necessary
1529 **********************************************************************/
1531 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1534 struct server_id server_id
,
1537 TALLOC_CTX
*tmp_ctx
;
1538 struct auth_serversupplied_info
*session_info
= NULL
;
1539 struct spoolss_PrinterInfo2
*pinfo2
;
1542 const char *drivername
;
1544 int n_services
= lp_numservices();
1545 struct dcerpc_binding_handle
*b
= NULL
;
1547 tmp_ctx
= talloc_new(NULL
);
1548 if (!tmp_ctx
) return;
1550 status
= make_session_info_system(tmp_ctx
, &session_info
);
1551 if (!NT_STATUS_IS_OK(status
)) {
1552 DEBUG(0, ("do_drv_upgrade_printer: "
1553 "Could not create system session_info\n"));
1557 drivername
= talloc_strndup(tmp_ctx
, (const char *)data
->data
, data
->length
);
1559 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1563 DEBUG(10, ("do_drv_upgrade_printer: "
1564 "Got message for new driver [%s]\n", drivername
));
1566 /* Iterate the printer list */
1568 for (snum
= 0; snum
< n_services
; snum
++) {
1569 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
1573 /* ignore [printers] share */
1574 if (strequal(lp_const_servicename(snum
), "printers")) {
1579 result
= winreg_printer_binding_handle(tmp_ctx
,
1583 if (!W_ERROR_IS_OK(result
)) {
1588 result
= winreg_get_printer(tmp_ctx
, b
,
1589 lp_const_servicename(snum
),
1592 if (!W_ERROR_IS_OK(result
)) {
1596 if (!pinfo2
->drivername
) {
1600 if (strcmp(drivername
, pinfo2
->drivername
) != 0) {
1604 DEBUG(6,("Updating printer [%s]\n", pinfo2
->printername
));
1606 /* all we care about currently is the change_id */
1607 result
= winreg_printer_update_changeid(tmp_ctx
, b
,
1608 pinfo2
->printername
);
1610 if (!W_ERROR_IS_OK(result
)) {
1611 DEBUG(3, ("do_drv_upgrade_printer: "
1612 "Failed to update changeid [%s]\n",
1613 win_errstr(result
)));
1619 talloc_free(tmp_ctx
);
1622 /********************************************************************
1623 Update the cache for all printq's with a registered client
1625 ********************************************************************/
1627 void update_monitored_printq_cache(struct messaging_context
*msg_ctx
)
1629 struct printer_handle
*printer
= printers_list
;
1632 /* loop through all printers and update the cache where
1633 a client is connected */
1635 if ((printer
->printer_type
== SPLHND_PRINTER
) &&
1636 ((printer
->notify
.cli_chan
!= NULL
) &&
1637 (printer
->notify
.cli_chan
->active_connections
> 0))) {
1638 snum
= print_queue_snum(printer
->sharename
);
1639 print_queue_status(msg_ctx
, snum
, NULL
, NULL
);
1642 printer
= printer
->next
;
1648 /****************************************************************
1649 _spoolss_OpenPrinter
1650 ****************************************************************/
1652 WERROR
_spoolss_OpenPrinter(struct pipes_struct
*p
,
1653 struct spoolss_OpenPrinter
*r
)
1655 struct spoolss_OpenPrinterEx e
;
1658 ZERO_STRUCT(e
.in
.userlevel
);
1660 e
.in
.printername
= r
->in
.printername
;
1661 e
.in
.datatype
= r
->in
.datatype
;
1662 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1663 e
.in
.access_mask
= r
->in
.access_mask
;
1666 e
.out
.handle
= r
->out
.handle
;
1668 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1670 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1671 /* OpenPrinterEx returns this for a bad
1672 * printer name. We must return WERR_INVALID_PRINTER_NAME
1675 werr
= WERR_INVALID_PRINTER_NAME
;
1681 static WERROR
copy_devicemode(TALLOC_CTX
*mem_ctx
,
1682 struct spoolss_DeviceMode
*orig
,
1683 struct spoolss_DeviceMode
**dest
)
1685 struct spoolss_DeviceMode
*dm
;
1687 dm
= talloc(mem_ctx
, struct spoolss_DeviceMode
);
1692 /* copy all values, then duplicate strings and structs */
1695 dm
->devicename
= talloc_strdup(dm
, orig
->devicename
);
1696 if (!dm
->devicename
) {
1699 dm
->formname
= talloc_strdup(dm
, orig
->formname
);
1700 if (!dm
->formname
) {
1703 if (orig
->driverextra_data
.data
) {
1704 dm
->driverextra_data
.data
=
1705 (uint8_t *) talloc_memdup(dm
, orig
->driverextra_data
.data
,
1706 orig
->driverextra_data
.length
);
1707 if (!dm
->driverextra_data
.data
) {
1716 /****************************************************************
1717 _spoolss_OpenPrinterEx
1718 ****************************************************************/
1720 WERROR
_spoolss_OpenPrinterEx(struct pipes_struct
*p
,
1721 struct spoolss_OpenPrinterEx
*r
)
1724 struct printer_handle
*Printer
=NULL
;
1727 if (!r
->in
.printername
) {
1728 return WERR_INVALID_PARAM
;
1731 if (r
->in
.level
> 3) {
1732 return WERR_INVALID_PARAM
;
1734 if ((r
->in
.level
== 1 && !r
->in
.userlevel
.level1
) ||
1735 (r
->in
.level
== 2 && !r
->in
.userlevel
.level2
) ||
1736 (r
->in
.level
== 3 && !r
->in
.userlevel
.level3
)) {
1737 return WERR_INVALID_PARAM
;
1740 /* some sanity check because you can open a printer or a print server */
1741 /* aka: \\server\printer or \\server */
1743 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1745 result
= open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0);
1746 if (!W_ERROR_IS_OK(result
)) {
1747 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1748 "for printer %s\n", r
->in
.printername
));
1749 ZERO_STRUCTP(r
->out
.handle
);
1753 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1755 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1756 "handle we created for printer %s\n", r
->in
.printername
));
1757 close_printer_handle(p
, r
->out
.handle
);
1758 ZERO_STRUCTP(r
->out
.handle
);
1759 return WERR_INVALID_PARAM
;
1763 * First case: the user is opening the print server:
1765 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1766 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1768 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1769 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1770 * or if the user is listed in the smb.conf printer admin parameter.
1772 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1773 * client view printer folder, but does not show the MSAPW.
1775 * Note: this test needs code to check access rights here too. Jeremy
1776 * could you look at this?
1778 * Second case: the user is opening a printer:
1779 * NT doesn't let us connect to a printer if the connecting user
1780 * doesn't have print permission.
1782 * Third case: user is opening a Port Monitor
1783 * access checks same as opening a handle to the print server.
1786 switch (Printer
->printer_type
)
1789 case SPLHND_PORTMON_TCP
:
1790 case SPLHND_PORTMON_LOCAL
:
1791 /* Printserver handles use global struct... */
1795 /* Map standard access rights to object specific access rights */
1797 se_map_standard(&r
->in
.access_mask
,
1798 &printserver_std_mapping
);
1800 /* Deny any object specific bits that don't apply to print
1801 servers (i.e printer and job specific bits) */
1803 r
->in
.access_mask
&= SEC_MASK_SPECIFIC
;
1805 if (r
->in
.access_mask
&
1806 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1807 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1808 close_printer_handle(p
, r
->out
.handle
);
1809 ZERO_STRUCTP(r
->out
.handle
);
1810 return WERR_ACCESS_DENIED
;
1813 /* Allow admin access */
1815 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1817 if (!lp_ms_add_printer_wizard()) {
1818 close_printer_handle(p
, r
->out
.handle
);
1819 ZERO_STRUCTP(r
->out
.handle
);
1820 return WERR_ACCESS_DENIED
;
1823 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1824 and not a printer admin, then fail */
1826 if ((p
->session_info
->utok
.uid
!= sec_initial_uid()) &&
1827 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
1828 !nt_token_check_sid(&global_sid_Builtin_Print_Operators
, p
->session_info
->security_token
) &&
1829 !token_contains_name_in_list(
1830 uidtoname(p
->session_info
->utok
.uid
),
1831 p
->session_info
->info3
->base
.domain
.string
,
1833 p
->session_info
->security_token
,
1834 lp_printer_admin(snum
))) {
1835 close_printer_handle(p
, r
->out
.handle
);
1836 ZERO_STRUCTP(r
->out
.handle
);
1837 DEBUG(3,("access DENIED as user is not root, "
1838 "has no printoperator privilege, "
1839 "not a member of the printoperator builtin group and "
1840 "is not in printer admin list"));
1841 return WERR_ACCESS_DENIED
;
1844 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1848 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1851 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1852 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1854 /* We fall through to return WERR_OK */
1857 case SPLHND_PRINTER
:
1858 /* NT doesn't let us connect to a printer if the connecting user
1859 doesn't have print permission. */
1861 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1862 close_printer_handle(p
, r
->out
.handle
);
1863 ZERO_STRUCTP(r
->out
.handle
);
1867 if (r
->in
.access_mask
== SEC_FLAG_MAXIMUM_ALLOWED
) {
1868 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1871 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1873 /* map an empty access mask to the minimum access mask */
1874 if (r
->in
.access_mask
== 0x0)
1875 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1878 * If we are not serving the printer driver for this printer,
1879 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1880 * will keep NT clients happy --jerry
1883 if (lp_use_client_driver(snum
)
1884 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1886 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1889 /* check smb.conf parameters and the the sec_desc */
1891 if (!allow_access(lp_hostsdeny(snum
), lp_hostsallow(snum
),
1892 p
->client_id
->name
, p
->client_id
->addr
)) {
1893 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1894 ZERO_STRUCTP(r
->out
.handle
);
1895 return WERR_ACCESS_DENIED
;
1898 if (!user_ok_token(uidtoname(p
->session_info
->utok
.uid
), NULL
,
1899 p
->session_info
->security_token
, snum
) ||
1900 !print_access_check(p
->session_info
,
1903 r
->in
.access_mask
)) {
1904 DEBUG(3, ("access DENIED for printer open\n"));
1905 close_printer_handle(p
, r
->out
.handle
);
1906 ZERO_STRUCTP(r
->out
.handle
);
1907 return WERR_ACCESS_DENIED
;
1910 if ((r
->in
.access_mask
& SEC_MASK_SPECIFIC
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1911 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912 close_printer_handle(p
, r
->out
.handle
);
1913 ZERO_STRUCTP(r
->out
.handle
);
1914 return WERR_ACCESS_DENIED
;
1917 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1918 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1920 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1922 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1923 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1925 winreg_create_printer_internal(p
->mem_ctx
,
1926 get_session_info_system(),
1928 lp_const_servicename(snum
));
1933 /* sanity check to prevent programmer error */
1934 ZERO_STRUCTP(r
->out
.handle
);
1938 Printer
->access_granted
= r
->in
.access_mask
;
1941 * If the client sent a devmode in the OpenPrinter() call, then
1942 * save it here in case we get a job submission on this handle
1945 if ((Printer
->printer_type
!= SPLHND_SERVER
)
1946 && (r
->in
.devmode_ctr
.devmode
!= NULL
)) {
1947 copy_devicemode(NULL
, r
->in
.devmode_ctr
.devmode
,
1954 /****************************************************************
1955 _spoolss_ClosePrinter
1956 ****************************************************************/
1958 WERROR
_spoolss_ClosePrinter(struct pipes_struct
*p
,
1959 struct spoolss_ClosePrinter
*r
)
1961 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1963 if (Printer
&& Printer
->document_started
) {
1964 struct spoolss_EndDocPrinter e
;
1966 e
.in
.handle
= r
->in
.handle
;
1968 _spoolss_EndDocPrinter(p
, &e
);
1971 if (!close_printer_handle(p
, r
->in
.handle
))
1974 /* clear the returned printer handle. Observed behavior
1975 from Win2k server. Don't think this really matters.
1976 Previous code just copied the value of the closed
1979 ZERO_STRUCTP(r
->out
.handle
);
1984 /****************************************************************
1985 _spoolss_DeletePrinter
1986 ****************************************************************/
1988 WERROR
_spoolss_DeletePrinter(struct pipes_struct
*p
,
1989 struct spoolss_DeletePrinter
*r
)
1991 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1995 if (Printer
&& Printer
->document_started
) {
1996 struct spoolss_EndDocPrinter e
;
1998 e
.in
.handle
= r
->in
.handle
;
2000 _spoolss_EndDocPrinter(p
, &e
);
2003 if (get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
2004 winreg_delete_printer_key_internal(p
->mem_ctx
,
2005 get_session_info_system(),
2007 lp_const_servicename(snum
),
2011 result
= delete_printer_handle(p
, r
->in
.handle
);
2016 /*******************************************************************
2017 * static function to lookup the version id corresponding to an
2018 * long architecture string
2019 ******************************************************************/
2021 static const struct print_architecture_table_node archi_table
[]= {
2023 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
2024 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
2025 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
2026 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
2027 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
2028 {"Windows IA64", SPL_ARCH_IA64
, 3 },
2029 {"Windows x64", SPL_ARCH_X64
, 3 },
2033 static const int drv_cversion
[] = {SPOOLSS_DRIVER_VERSION_9X
,
2034 SPOOLSS_DRIVER_VERSION_NT35
,
2035 SPOOLSS_DRIVER_VERSION_NT4
,
2036 SPOOLSS_DRIVER_VERSION_200X
,
2039 static int get_version_id(const char *arch
)
2043 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
2045 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
2046 return (archi_table
[i
].version
);
2052 /****************************************************************
2053 _spoolss_DeletePrinterDriver
2054 ****************************************************************/
2056 WERROR
_spoolss_DeletePrinterDriver(struct pipes_struct
*p
,
2057 struct spoolss_DeletePrinterDriver
*r
)
2060 struct spoolss_DriverInfo8
*info
= NULL
;
2063 struct dcerpc_binding_handle
*b
;
2064 TALLOC_CTX
*tmp_ctx
= NULL
;
2068 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2069 and not a printer admin, then fail */
2071 if ( (p
->session_info
->utok
.uid
!= sec_initial_uid())
2072 && !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
)
2073 && !token_contains_name_in_list(
2074 uidtoname(p
->session_info
->utok
.uid
),
2075 p
->session_info
->info3
->base
.domain
.string
,
2077 p
->session_info
->security_token
,
2078 lp_printer_admin(-1)) )
2080 return WERR_ACCESS_DENIED
;
2083 /* check that we have a valid driver name first */
2085 if ((version
= get_version_id(r
->in
.architecture
)) == -1)
2086 return WERR_INVALID_ENVIRONMENT
;
2088 tmp_ctx
= talloc_new(p
->mem_ctx
);
2093 status
= winreg_printer_binding_handle(tmp_ctx
,
2094 get_session_info_system(),
2097 if (!W_ERROR_IS_OK(status
)) {
2101 for (found
= false, i
= 0; drv_cversion
[i
] >= 0; i
++) {
2102 status
= winreg_get_driver(tmp_ctx
, b
,
2103 r
->in
.architecture
, r
->in
.driver
,
2104 drv_cversion
[i
], &info
);
2105 if (!W_ERROR_IS_OK(status
)) {
2106 DEBUG(5, ("skipping del of driver with version %d\n",
2112 if (printer_driver_in_use(tmp_ctx
, get_session_info_system(),
2113 p
->msg_ctx
, info
)) {
2114 status
= WERR_PRINTER_DRIVER_IN_USE
;
2118 status
= winreg_del_driver(tmp_ctx
, b
, info
, drv_cversion
[i
]);
2119 if (!W_ERROR_IS_OK(status
)) {
2120 DEBUG(0, ("failed del of driver with version %d\n",
2125 if (found
== false) {
2126 DEBUG(0, ("driver %s not found for deletion\n", r
->in
.driver
));
2127 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2133 talloc_free(tmp_ctx
);
2137 static WERROR
spoolss_dpd_version(TALLOC_CTX
*mem_ctx
,
2138 struct pipes_struct
*p
,
2139 struct spoolss_DeletePrinterDriverEx
*r
,
2140 struct dcerpc_binding_handle
*b
,
2141 struct spoolss_DriverInfo8
*info
)
2146 if (printer_driver_in_use(mem_ctx
, get_session_info_system(),
2147 p
->msg_ctx
, info
)) {
2148 status
= WERR_PRINTER_DRIVER_IN_USE
;
2153 * we have a couple of cases to consider.
2154 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2155 * then the delete should fail if **any** files overlap with
2157 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2158 * non-overlapping files
2159 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2160 * is set, then do not delete any files
2161 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2164 delete_files
= r
->in
.delete_flags
2165 & (DPD_DELETE_ALL_FILES
| DPD_DELETE_UNUSED_FILES
);
2168 bool in_use
= printer_driver_files_in_use(mem_ctx
,
2169 get_session_info_system(),
2172 if (in_use
&& (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
)) {
2173 status
= WERR_PRINTER_DRIVER_IN_USE
;
2177 * printer_driver_files_in_use() has trimmed overlapping files
2178 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2182 status
= winreg_del_driver(mem_ctx
, b
, info
, info
->version
);
2183 if (!W_ERROR_IS_OK(status
)) {
2188 * now delete any associated files if delete_files is
2189 * true. Even if this part failes, we return succes
2190 * because the driver doesn not exist any more
2193 delete_driver_files(get_session_info_system(), info
);
2200 /****************************************************************
2201 _spoolss_DeletePrinterDriverEx
2202 ****************************************************************/
2204 WERROR
_spoolss_DeletePrinterDriverEx(struct pipes_struct
*p
,
2205 struct spoolss_DeletePrinterDriverEx
*r
)
2207 struct spoolss_DriverInfo8
*info
= NULL
;
2209 struct dcerpc_binding_handle
*b
;
2210 TALLOC_CTX
*tmp_ctx
= NULL
;
2214 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2215 and not a printer admin, then fail */
2217 if ( (p
->session_info
->utok
.uid
!= sec_initial_uid())
2218 && !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
)
2219 && !token_contains_name_in_list(
2220 uidtoname(p
->session_info
->utok
.uid
),
2221 p
->session_info
->info3
->base
.domain
.string
,
2223 p
->session_info
->security_token
, lp_printer_admin(-1)) )
2225 return WERR_ACCESS_DENIED
;
2228 /* check that we have a valid driver name first */
2229 if (get_version_id(r
->in
.architecture
) == -1) {
2230 /* this is what NT returns */
2231 return WERR_INVALID_ENVIRONMENT
;
2234 tmp_ctx
= talloc_new(p
->mem_ctx
);
2239 status
= winreg_printer_binding_handle(tmp_ctx
,
2240 get_session_info_system(),
2243 if (!W_ERROR_IS_OK(status
)) {
2247 for (found
= false, i
= 0; drv_cversion
[i
] >= 0; i
++) {
2248 if ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
2249 && (drv_cversion
[i
] != r
->in
.version
)) {
2253 /* check if a driver with this version exists before delete */
2254 status
= winreg_get_driver(tmp_ctx
, b
,
2255 r
->in
.architecture
, r
->in
.driver
,
2256 drv_cversion
[i
], &info
);
2257 if (!W_ERROR_IS_OK(status
)) {
2258 DEBUG(5, ("skipping del of driver with version %d\n",
2264 status
= spoolss_dpd_version(tmp_ctx
, p
, r
, b
, info
);
2265 if (!W_ERROR_IS_OK(status
)) {
2266 DEBUG(0, ("failed to delete driver with version %d\n",
2271 if (found
== false) {
2272 DEBUG(0, ("driver %s not found for deletion\n", r
->in
.driver
));
2273 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2279 talloc_free(tmp_ctx
);
2284 /********************************************************************
2285 GetPrinterData on a printer server Handle.
2286 ********************************************************************/
2288 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2290 enum winreg_Type
*type
,
2291 union spoolss_PrinterData
*data
)
2293 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2295 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2301 if (!StrCaseCmp(value
, "BeepEnabled")) {
2307 if (!StrCaseCmp(value
, "EventLog")) {
2309 /* formally was 0x1b */
2314 if (!StrCaseCmp(value
, "NetPopup")) {
2320 if (!StrCaseCmp(value
, "MajorVersion")) {
2323 /* Windows NT 4.0 seems to not allow uploading of drivers
2324 to a server that reports 0x3 as the MajorVersion.
2325 need to investigate more how Win2k gets around this .
2328 if (RA_WINNT
== get_remote_arch()) {
2337 if (!StrCaseCmp(value
, "MinorVersion")) {
2344 * uint32_t size = 0x114
2345 * uint32_t major = 5
2346 * uint32_t minor = [0|1]
2347 * uint32_t build = [2195|2600]
2348 * extra unicode string = e.g. "Service Pack 3"
2350 if (!StrCaseCmp(value
, "OSVersion")) {
2352 enum ndr_err_code ndr_err
;
2353 struct spoolss_OSVersion os
;
2355 os
.major
= 5; /* Windows 2000 == 5.0 */
2357 os
.build
= 2195; /* build */
2358 os
.extra_string
= ""; /* leave extra string empty */
2360 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &os
,
2361 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2362 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2363 return WERR_GENERAL_FAILURE
;
2367 data
->binary
= blob
;
2373 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2376 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2377 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2382 if (!StrCaseCmp(value
, "Architecture")) {
2384 data
->string
= talloc_strdup(mem_ctx
,
2385 lp_parm_const_string(GLOBAL_SECTION_SNUM
, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86
));
2386 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2391 if (!StrCaseCmp(value
, "DsPresent")) {
2394 /* only show the publish check box if we are a
2395 member of a AD domain */
2397 if (lp_security() == SEC_ADS
) {
2405 if (!StrCaseCmp(value
, "DNSMachineName")) {
2406 const char *hostname
= get_mydnsfullname();
2409 return WERR_BADFILE
;
2413 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2414 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2421 return WERR_INVALID_PARAM
;
2424 /****************************************************************
2425 _spoolss_GetPrinterData
2426 ****************************************************************/
2428 WERROR
_spoolss_GetPrinterData(struct pipes_struct
*p
,
2429 struct spoolss_GetPrinterData
*r
)
2431 struct spoolss_GetPrinterDataEx r2
;
2433 r2
.in
.handle
= r
->in
.handle
;
2434 r2
.in
.key_name
= "PrinterDriverData";
2435 r2
.in
.value_name
= r
->in
.value_name
;
2436 r2
.in
.offered
= r
->in
.offered
;
2437 r2
.out
.type
= r
->out
.type
;
2438 r2
.out
.data
= r
->out
.data
;
2439 r2
.out
.needed
= r
->out
.needed
;
2441 return _spoolss_GetPrinterDataEx(p
, &r2
);
2444 /*********************************************************
2445 Connect to the client machine.
2446 **********************************************************/
2448 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2449 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2452 struct cli_state
*the_cli
;
2453 struct sockaddr_storage rm_addr
;
2454 char addr
[INET6_ADDRSTRLEN
];
2456 if ( is_zero_addr(client_ss
) ) {
2457 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2459 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20, false) ) {
2460 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2463 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2465 rm_addr
= *client_ss
;
2466 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2467 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2471 if (ismyaddr((struct sockaddr
*)(void *)&rm_addr
)) {
2472 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2477 /* setup the connection */
2478 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2479 &rm_addr
, 0, "IPC$", "IPC",
2483 0, lp_client_signing());
2485 if ( !NT_STATUS_IS_OK( ret
) ) {
2486 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2491 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2492 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2493 cli_shutdown(the_cli
);
2498 * Ok - we have an anonymous connection to the IPC$ share.
2499 * Now start the NT Domain stuff :-).
2502 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2503 if (!NT_STATUS_IS_OK(ret
)) {
2504 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2505 remote_machine
, nt_errstr(ret
)));
2506 cli_shutdown(the_cli
);
2513 /***************************************************************************
2514 Connect to the client.
2515 ****************************************************************************/
2517 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2518 uint32_t localprinter
,
2519 enum winreg_Type type
,
2520 struct policy_handle
*handle
,
2521 struct notify_back_channel
**_chan
,
2522 struct sockaddr_storage
*client_ss
,
2523 struct messaging_context
*msg_ctx
)
2527 struct notify_back_channel
*chan
;
2529 for (chan
= back_channels
; chan
; chan
= chan
->next
) {
2530 if (memcmp(&chan
->client_address
, client_ss
,
2531 sizeof(struct sockaddr_storage
)) == 0) {
2537 * If it's the first connection, contact the client
2538 * and connect to the IPC$ share anonymously
2541 fstring unix_printer
;
2543 /* the +2 is to strip the leading 2 backslashs */
2544 fstrcpy(unix_printer
, printer
+ 2);
2546 chan
= talloc_zero(back_channels
, struct notify_back_channel
);
2550 chan
->client_address
= *client_ss
;
2552 if (!spoolss_connect_to_client(&chan
->cli_pipe
, client_ss
, unix_printer
)) {
2556 chan
->binding_handle
= chan
->cli_pipe
->binding_handle
;
2558 DLIST_ADD(back_channels
, chan
);
2560 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_NOTIFY2
,
2561 receive_notify2_message_list
);
2562 /* Tell the connections db we're now interested in printer
2563 * notify messages. */
2564 serverid_register_msg_flags(messaging_server_id(msg_ctx
),
2565 true, FLAG_MSG_PRINT_NOTIFY
);
2569 * Tell the specific printing tdb we want messages for this printer
2570 * by registering our PID.
2573 if (!print_notify_register_pid(snum
)) {
2574 DEBUG(0, ("Failed to register our pid for printer %s\n",
2578 status
= dcerpc_spoolss_ReplyOpenPrinter(chan
->binding_handle
,
2587 if (!NT_STATUS_IS_OK(status
)) {
2588 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status
)));
2589 result
= ntstatus_to_werror(status
);
2590 } else if (!W_ERROR_IS_OK(result
)) {
2591 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result
)));
2594 chan
->active_connections
++;
2597 return (W_ERROR_IS_OK(result
));
2600 /****************************************************************
2601 ****************************************************************/
2603 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2604 const struct spoolss_NotifyOption
*r
)
2606 struct spoolss_NotifyOption
*option
;
2613 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2620 if (!option
->count
) {
2624 option
->types
= talloc_zero_array(option
,
2625 struct spoolss_NotifyOptionType
, option
->count
);
2626 if (!option
->types
) {
2627 talloc_free(option
);
2631 for (i
=0; i
< option
->count
; i
++) {
2632 option
->types
[i
] = r
->types
[i
];
2634 if (option
->types
[i
].count
) {
2635 option
->types
[i
].fields
= talloc_zero_array(option
,
2636 union spoolss_Field
, option
->types
[i
].count
);
2637 if (!option
->types
[i
].fields
) {
2638 talloc_free(option
);
2641 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2642 option
->types
[i
].fields
[k
] =
2643 r
->types
[i
].fields
[k
];
2651 /****************************************************************
2652 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2654 * before replying OK: status=0 a rpc call is made to the workstation
2655 * asking ReplyOpenPrinter
2657 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2658 * called from api_spoolss_rffpcnex
2659 ****************************************************************/
2661 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct
*p
,
2662 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2665 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2666 struct sockaddr_storage client_ss
;
2668 /* store the notify value in the printer struct */
2670 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2673 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2674 "Invalid handle (%s:%u:%u).\n",
2675 OUR_HANDLE(r
->in
.handle
)));
2679 Printer
->notify
.flags
= r
->in
.flags
;
2680 Printer
->notify
.options
= r
->in
.options
;
2681 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2682 Printer
->notify
.msg_ctx
= p
->msg_ctx
;
2684 TALLOC_FREE(Printer
->notify
.option
);
2685 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2687 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2689 /* Connect to the client machine and send a ReplyOpenPrinter */
2691 if ( Printer
->printer_type
== SPLHND_SERVER
)
2693 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2694 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2697 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2698 "client_address is %s\n", p
->client_id
->addr
));
2700 if (!lp_print_notify_backchannel(snum
)) {
2701 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2702 "backchannel disabled\n"));
2703 return WERR_SERVER_UNAVAILABLE
;
2706 if (!interpret_string_addr(&client_ss
, p
->client_id
->addr
,
2708 return WERR_SERVER_UNAVAILABLE
;
2711 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2712 Printer
->notify
.printerlocal
, REG_SZ
,
2713 &Printer
->notify
.cli_hnd
,
2714 &Printer
->notify
.cli_chan
,
2715 &client_ss
, p
->msg_ctx
)) {
2716 return WERR_SERVER_UNAVAILABLE
;
2722 /*******************************************************************
2723 * fill a notify_info_data with the servername
2724 ********************************************************************/
2726 static void spoolss_notify_server_name(struct messaging_context
*msg_ctx
,
2728 struct spoolss_Notify
*data
,
2729 print_queue_struct
*queue
,
2730 struct spoolss_PrinterInfo2
*pinfo2
,
2731 TALLOC_CTX
*mem_ctx
)
2733 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->servername
);
2736 /*******************************************************************
2737 * fill a notify_info_data with the printername (not including the servername).
2738 ********************************************************************/
2740 static void spoolss_notify_printer_name(struct messaging_context
*msg_ctx
,
2742 struct spoolss_Notify
*data
,
2743 print_queue_struct
*queue
,
2744 struct spoolss_PrinterInfo2
*pinfo2
,
2745 TALLOC_CTX
*mem_ctx
)
2747 /* the notify name should not contain the \\server\ part */
2748 const char *p
= strrchr(pinfo2
->printername
, '\\');
2751 p
= pinfo2
->printername
;
2756 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2759 /*******************************************************************
2760 * fill a notify_info_data with the servicename
2761 ********************************************************************/
2763 static void spoolss_notify_share_name(struct messaging_context
*msg_ctx
,
2765 struct spoolss_Notify
*data
,
2766 print_queue_struct
*queue
,
2767 struct spoolss_PrinterInfo2
*pinfo2
,
2768 TALLOC_CTX
*mem_ctx
)
2770 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2773 /*******************************************************************
2774 * fill a notify_info_data with the port name
2775 ********************************************************************/
2777 static void spoolss_notify_port_name(struct messaging_context
*msg_ctx
,
2779 struct spoolss_Notify
*data
,
2780 print_queue_struct
*queue
,
2781 struct spoolss_PrinterInfo2
*pinfo2
,
2782 TALLOC_CTX
*mem_ctx
)
2784 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->portname
);
2787 /*******************************************************************
2788 * fill a notify_info_data with the printername
2789 * but it doesn't exist, have to see what to do
2790 ********************************************************************/
2792 static void spoolss_notify_driver_name(struct messaging_context
*msg_ctx
,
2794 struct spoolss_Notify
*data
,
2795 print_queue_struct
*queue
,
2796 struct spoolss_PrinterInfo2
*pinfo2
,
2797 TALLOC_CTX
*mem_ctx
)
2799 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->drivername
);
2802 /*******************************************************************
2803 * fill a notify_info_data with the comment
2804 ********************************************************************/
2806 static void spoolss_notify_comment(struct messaging_context
*msg_ctx
,
2808 struct spoolss_Notify
*data
,
2809 print_queue_struct
*queue
,
2810 struct spoolss_PrinterInfo2
*pinfo2
,
2811 TALLOC_CTX
*mem_ctx
)
2815 if (*pinfo2
->comment
== '\0') {
2816 p
= lp_comment(snum
);
2818 p
= pinfo2
->comment
;
2821 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2824 /*******************************************************************
2825 * fill a notify_info_data with the comment
2826 * location = "Room 1, floor 2, building 3"
2827 ********************************************************************/
2829 static void spoolss_notify_location(struct messaging_context
*msg_ctx
,
2831 struct spoolss_Notify
*data
,
2832 print_queue_struct
*queue
,
2833 struct spoolss_PrinterInfo2
*pinfo2
,
2834 TALLOC_CTX
*mem_ctx
)
2836 const char *loc
= pinfo2
->location
;
2839 status
= printer_list_get_printer(mem_ctx
,
2844 if (NT_STATUS_IS_OK(status
)) {
2846 loc
= pinfo2
->location
;
2850 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, loc
);
2853 /*******************************************************************
2854 * fill a notify_info_data with the device mode
2855 * jfm:xxxx don't to it for know but that's a real problem !!!
2856 ********************************************************************/
2858 static void spoolss_notify_devmode(struct messaging_context
*msg_ctx
,
2860 struct spoolss_Notify
*data
,
2861 print_queue_struct
*queue
,
2862 struct spoolss_PrinterInfo2
*pinfo2
,
2863 TALLOC_CTX
*mem_ctx
)
2865 /* for a dummy implementation we have to zero the fields */
2866 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2869 /*******************************************************************
2870 * fill a notify_info_data with the separator file name
2871 ********************************************************************/
2873 static void spoolss_notify_sepfile(struct messaging_context
*msg_ctx
,
2875 struct spoolss_Notify
*data
,
2876 print_queue_struct
*queue
,
2877 struct spoolss_PrinterInfo2
*pinfo2
,
2878 TALLOC_CTX
*mem_ctx
)
2880 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->sepfile
);
2883 /*******************************************************************
2884 * fill a notify_info_data with the print processor
2885 * jfm:xxxx return always winprint to indicate we don't do anything to it
2886 ********************************************************************/
2888 static void spoolss_notify_print_processor(struct messaging_context
*msg_ctx
,
2890 struct spoolss_Notify
*data
,
2891 print_queue_struct
*queue
,
2892 struct spoolss_PrinterInfo2
*pinfo2
,
2893 TALLOC_CTX
*mem_ctx
)
2895 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->printprocessor
);
2898 /*******************************************************************
2899 * fill a notify_info_data with the print processor options
2900 * jfm:xxxx send an empty string
2901 ********************************************************************/
2903 static void spoolss_notify_parameters(struct messaging_context
*msg_ctx
,
2905 struct spoolss_Notify
*data
,
2906 print_queue_struct
*queue
,
2907 struct spoolss_PrinterInfo2
*pinfo2
,
2908 TALLOC_CTX
*mem_ctx
)
2910 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->parameters
);
2913 /*******************************************************************
2914 * fill a notify_info_data with the data type
2915 * jfm:xxxx always send RAW as data type
2916 ********************************************************************/
2918 static void spoolss_notify_datatype(struct messaging_context
*msg_ctx
,
2920 struct spoolss_Notify
*data
,
2921 print_queue_struct
*queue
,
2922 struct spoolss_PrinterInfo2
*pinfo2
,
2923 TALLOC_CTX
*mem_ctx
)
2925 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->datatype
);
2928 /*******************************************************************
2929 * fill a notify_info_data with the security descriptor
2930 * jfm:xxxx send an null pointer to say no security desc
2931 * have to implement security before !
2932 ********************************************************************/
2934 static void spoolss_notify_security_desc(struct messaging_context
*msg_ctx
,
2936 struct spoolss_Notify
*data
,
2937 print_queue_struct
*queue
,
2938 struct spoolss_PrinterInfo2
*pinfo2
,
2939 TALLOC_CTX
*mem_ctx
)
2941 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
, pinfo2
->secdesc
);
2944 /*******************************************************************
2945 * fill a notify_info_data with the attributes
2946 * jfm:xxxx a samba printer is always shared
2947 ********************************************************************/
2949 static void spoolss_notify_attributes(struct messaging_context
*msg_ctx
,
2951 struct spoolss_Notify
*data
,
2952 print_queue_struct
*queue
,
2953 struct spoolss_PrinterInfo2
*pinfo2
,
2954 TALLOC_CTX
*mem_ctx
)
2956 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->attributes
);
2959 /*******************************************************************
2960 * fill a notify_info_data with the priority
2961 ********************************************************************/
2963 static void spoolss_notify_priority(struct messaging_context
*msg_ctx
,
2965 struct spoolss_Notify
*data
,
2966 print_queue_struct
*queue
,
2967 struct spoolss_PrinterInfo2
*pinfo2
,
2968 TALLOC_CTX
*mem_ctx
)
2970 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->priority
);
2973 /*******************************************************************
2974 * fill a notify_info_data with the default priority
2975 ********************************************************************/
2977 static void spoolss_notify_default_priority(struct messaging_context
*msg_ctx
,
2979 struct spoolss_Notify
*data
,
2980 print_queue_struct
*queue
,
2981 struct spoolss_PrinterInfo2
*pinfo2
,
2982 TALLOC_CTX
*mem_ctx
)
2984 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->defaultpriority
);
2987 /*******************************************************************
2988 * fill a notify_info_data with the start time
2989 ********************************************************************/
2991 static void spoolss_notify_start_time(struct messaging_context
*msg_ctx
,
2993 struct spoolss_Notify
*data
,
2994 print_queue_struct
*queue
,
2995 struct spoolss_PrinterInfo2
*pinfo2
,
2996 TALLOC_CTX
*mem_ctx
)
2998 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->starttime
);
3001 /*******************************************************************
3002 * fill a notify_info_data with the until time
3003 ********************************************************************/
3005 static void spoolss_notify_until_time(struct messaging_context
*msg_ctx
,
3007 struct spoolss_Notify
*data
,
3008 print_queue_struct
*queue
,
3009 struct spoolss_PrinterInfo2
*pinfo2
,
3010 TALLOC_CTX
*mem_ctx
)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->untiltime
);
3015 /*******************************************************************
3016 * fill a notify_info_data with the status
3017 ********************************************************************/
3019 static void spoolss_notify_status(struct messaging_context
*msg_ctx
,
3021 struct spoolss_Notify
*data
,
3022 print_queue_struct
*queue
,
3023 struct spoolss_PrinterInfo2
*pinfo2
,
3024 TALLOC_CTX
*mem_ctx
)
3026 print_status_struct status
;
3028 print_queue_length(msg_ctx
, snum
, &status
);
3029 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
3032 /*******************************************************************
3033 * fill a notify_info_data with the number of jobs queued
3034 ********************************************************************/
3036 static void spoolss_notify_cjobs(struct messaging_context
*msg_ctx
,
3038 struct spoolss_Notify
*data
,
3039 print_queue_struct
*queue
,
3040 struct spoolss_PrinterInfo2
*pinfo2
,
3041 TALLOC_CTX
*mem_ctx
)
3043 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3044 data
, print_queue_length(msg_ctx
, snum
, NULL
));
3047 /*******************************************************************
3048 * fill a notify_info_data with the average ppm
3049 ********************************************************************/
3051 static void spoolss_notify_average_ppm(struct messaging_context
*msg_ctx
,
3053 struct spoolss_Notify
*data
,
3054 print_queue_struct
*queue
,
3055 struct spoolss_PrinterInfo2
*pinfo2
,
3056 TALLOC_CTX
*mem_ctx
)
3058 /* always respond 8 pages per minutes */
3059 /* a little hard ! */
3060 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->averageppm
);
3063 /*******************************************************************
3064 * fill a notify_info_data with username
3065 ********************************************************************/
3067 static void spoolss_notify_username(struct messaging_context
*msg_ctx
,
3069 struct spoolss_Notify
*data
,
3070 print_queue_struct
*queue
,
3071 struct spoolss_PrinterInfo2
*pinfo2
,
3072 TALLOC_CTX
*mem_ctx
)
3074 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
3077 /*******************************************************************
3078 * fill a notify_info_data with job status
3079 ********************************************************************/
3081 static void spoolss_notify_job_status(struct messaging_context
*msg_ctx
,
3083 struct spoolss_Notify
*data
,
3084 print_queue_struct
*queue
,
3085 struct spoolss_PrinterInfo2
*pinfo2
,
3086 TALLOC_CTX
*mem_ctx
)
3088 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
3091 /*******************************************************************
3092 * fill a notify_info_data with job name
3093 ********************************************************************/
3095 static void spoolss_notify_job_name(struct messaging_context
*msg_ctx
,
3097 struct spoolss_Notify
*data
,
3098 print_queue_struct
*queue
,
3099 struct spoolss_PrinterInfo2
*pinfo2
,
3100 TALLOC_CTX
*mem_ctx
)
3102 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
3105 /*******************************************************************
3106 * fill a notify_info_data with job status
3107 ********************************************************************/
3109 static void spoolss_notify_job_status_string(struct messaging_context
*msg_ctx
,
3111 struct spoolss_Notify
*data
,
3112 print_queue_struct
*queue
,
3113 struct spoolss_PrinterInfo2
*pinfo2
,
3114 TALLOC_CTX
*mem_ctx
)
3117 * Now we're returning job status codes we just return a "" here. JRA.
3122 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3125 switch (queue
->status
) {
3130 p
= ""; /* NT provides the paused string */
3139 #endif /* NO LONGER NEEDED. */
3141 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
3144 /*******************************************************************
3145 * fill a notify_info_data with job time
3146 ********************************************************************/
3148 static void spoolss_notify_job_time(struct messaging_context
*msg_ctx
,
3150 struct spoolss_Notify
*data
,
3151 print_queue_struct
*queue
,
3152 struct spoolss_PrinterInfo2
*pinfo2
,
3153 TALLOC_CTX
*mem_ctx
)
3155 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3158 /*******************************************************************
3159 * fill a notify_info_data with job size
3160 ********************************************************************/
3162 static void spoolss_notify_job_size(struct messaging_context
*msg_ctx
,
3164 struct spoolss_Notify
*data
,
3165 print_queue_struct
*queue
,
3166 struct spoolss_PrinterInfo2
*pinfo2
,
3167 TALLOC_CTX
*mem_ctx
)
3169 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
3172 /*******************************************************************
3173 * fill a notify_info_data with page info
3174 ********************************************************************/
3175 static void spoolss_notify_total_pages(struct messaging_context
*msg_ctx
,
3177 struct spoolss_Notify
*data
,
3178 print_queue_struct
*queue
,
3179 struct spoolss_PrinterInfo2
*pinfo2
,
3180 TALLOC_CTX
*mem_ctx
)
3182 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
3185 /*******************************************************************
3186 * fill a notify_info_data with pages printed info.
3187 ********************************************************************/
3188 static void spoolss_notify_pages_printed(struct messaging_context
*msg_ctx
,
3190 struct spoolss_Notify
*data
,
3191 print_queue_struct
*queue
,
3192 struct spoolss_PrinterInfo2
*pinfo2
,
3193 TALLOC_CTX
*mem_ctx
)
3195 /* Add code when back-end tracks this */
3196 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3199 /*******************************************************************
3200 Fill a notify_info_data with job position.
3201 ********************************************************************/
3203 static void spoolss_notify_job_position(struct messaging_context
*msg_ctx
,
3205 struct spoolss_Notify
*data
,
3206 print_queue_struct
*queue
,
3207 struct spoolss_PrinterInfo2
*pinfo2
,
3208 TALLOC_CTX
*mem_ctx
)
3210 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->sysjob
);
3213 /*******************************************************************
3214 Fill a notify_info_data with submitted time.
3215 ********************************************************************/
3217 static void spoolss_notify_submitted_time(struct messaging_context
*msg_ctx
,
3219 struct spoolss_Notify
*data
,
3220 print_queue_struct
*queue
,
3221 struct spoolss_PrinterInfo2
*pinfo2
,
3222 TALLOC_CTX
*mem_ctx
)
3224 data
->data
.string
.string
= NULL
;
3225 data
->data
.string
.size
= 0;
3227 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
3228 &data
->data
.string
.string
,
3229 &data
->data
.string
.size
);
3233 struct s_notify_info_data_table
3235 enum spoolss_NotifyType type
;
3238 enum spoolss_NotifyTable variable_type
;
3239 void (*fn
) (struct messaging_context
*msg_ctx
,
3240 int snum
, struct spoolss_Notify
*data
,
3241 print_queue_struct
*queue
,
3242 struct spoolss_PrinterInfo2
*pinfo2
,
3243 TALLOC_CTX
*mem_ctx
);
3246 /* A table describing the various print notification constants and
3247 whether the notification data is a pointer to a variable sized
3248 buffer, a one value uint32_t or a two value uint32_t. */
3250 static const struct s_notify_info_data_table notify_info_data_table
[] =
3252 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3253 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3254 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
3255 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3256 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3257 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
3258 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
3259 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3260 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
3261 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3262 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3263 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3264 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
3265 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
3266 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3267 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
3268 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3269 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3270 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
3271 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
3272 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
3273 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3274 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3275 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3276 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3277 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3278 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3279 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3280 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3281 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3282 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3283 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3284 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3285 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3286 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3287 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3288 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3289 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3290 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3291 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3292 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3293 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3294 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3295 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3296 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3297 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3298 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3299 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3300 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3303 /*******************************************************************
3304 Return the variable_type of info_data structure.
3305 ********************************************************************/
3307 static enum spoolss_NotifyTable
variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3312 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3313 if ( (notify_info_data_table
[i
].type
== type
) &&
3314 (notify_info_data_table
[i
].field
== field
) ) {
3315 return notify_info_data_table
[i
].variable_type
;
3319 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3321 return (enum spoolss_NotifyTable
) 0;
3324 /****************************************************************************
3325 ****************************************************************************/
3327 static bool search_notify(enum spoolss_NotifyType type
,
3333 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3334 if (notify_info_data_table
[i
].type
== type
&&
3335 notify_info_data_table
[i
].field
== field
&&
3336 notify_info_data_table
[i
].fn
!= NULL
) {
3345 /****************************************************************************
3346 ****************************************************************************/
3348 static void construct_info_data(struct spoolss_Notify
*info_data
,
3349 enum spoolss_NotifyType type
,
3350 uint16_t field
, int id
)
3352 info_data
->type
= type
;
3353 info_data
->field
.field
= field
;
3354 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3355 info_data
->job_id
= id
;
3358 /*******************************************************************
3360 * fill a notify_info struct with info asked
3362 ********************************************************************/
3364 static bool construct_notify_printer_info(struct messaging_context
*msg_ctx
,
3365 struct printer_handle
*print_hnd
,
3366 struct spoolss_NotifyInfo
*info
,
3367 struct spoolss_PrinterInfo2
*pinfo2
,
3369 const struct spoolss_NotifyOptionType
*option_type
,
3371 TALLOC_CTX
*mem_ctx
)
3374 enum spoolss_NotifyType type
;
3377 struct spoolss_Notify
*current_data
;
3379 type
= option_type
->type
;
3381 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3382 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3383 option_type
->count
, lp_servicename(snum
)));
3385 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3386 field
= option_type
->fields
[field_num
].field
;
3388 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3390 if (!search_notify(type
, field
, &j
) )
3393 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3394 struct spoolss_Notify
,
3396 if (info
->notifies
== NULL
) {
3397 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3401 current_data
= &info
->notifies
[info
->count
];
3403 construct_info_data(current_data
, type
, field
, id
);
3405 DEBUG(10, ("construct_notify_printer_info: "
3406 "calling [%s] snum=%d printername=[%s])\n",
3407 notify_info_data_table
[j
].name
, snum
,
3408 pinfo2
->printername
));
3410 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3411 NULL
, pinfo2
, mem_ctx
);
3419 /*******************************************************************
3421 * fill a notify_info struct with info asked
3423 ********************************************************************/
3425 static bool construct_notify_jobs_info(struct messaging_context
*msg_ctx
,
3426 print_queue_struct
*queue
,
3427 struct spoolss_NotifyInfo
*info
,
3428 struct spoolss_PrinterInfo2
*pinfo2
,
3430 const struct spoolss_NotifyOptionType
*option_type
,
3432 TALLOC_CTX
*mem_ctx
)
3435 enum spoolss_NotifyType type
;
3437 struct spoolss_Notify
*current_data
;
3439 DEBUG(4,("construct_notify_jobs_info\n"));
3441 type
= option_type
->type
;
3443 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3444 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3445 option_type
->count
));
3447 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3448 field
= option_type
->fields
[field_num
].field
;
3450 if (!search_notify(type
, field
, &j
) )
3453 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3454 struct spoolss_Notify
,
3456 if (info
->notifies
== NULL
) {
3457 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3461 current_data
=&(info
->notifies
[info
->count
]);
3463 construct_info_data(current_data
, type
, field
, id
);
3464 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3465 queue
, pinfo2
, mem_ctx
);
3473 * JFM: The enumeration is not that simple, it's even non obvious.
3475 * let's take an example: I want to monitor the PRINTER SERVER for
3476 * the printer's name and the number of jobs currently queued.
3477 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3478 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3480 * I have 3 printers on the back of my server.
3482 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3485 * 1 printer 1 name 1
3486 * 2 printer 1 cjob 1
3487 * 3 printer 2 name 2
3488 * 4 printer 2 cjob 2
3489 * 5 printer 3 name 3
3490 * 6 printer 3 name 3
3492 * that's the print server case, the printer case is even worse.
3495 /*******************************************************************
3497 * enumerate all printers on the printserver
3498 * fill a notify_info struct with info asked
3500 ********************************************************************/
3502 static WERROR
printserver_notify_info(struct pipes_struct
*p
,
3503 struct policy_handle
*hnd
,
3504 struct spoolss_NotifyInfo
*info
,
3505 TALLOC_CTX
*mem_ctx
)
3508 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3509 int n_services
=lp_numservices();
3511 struct spoolss_NotifyOption
*option
;
3512 struct spoolss_NotifyOptionType option_type
;
3513 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3516 DEBUG(4,("printserver_notify_info\n"));
3521 option
= Printer
->notify
.option
;
3524 info
->notifies
= NULL
;
3527 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3528 sending a ffpcn() request first */
3533 for (i
=0; i
<option
->count
; i
++) {
3534 option_type
= option
->types
[i
];
3536 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3539 for (snum
= 0; snum
< n_services
; snum
++) {
3540 if (!lp_browseable(snum
) ||
3541 !lp_snum_ok(snum
) ||
3542 !lp_print_ok(snum
)) {
3543 continue; /* skip */
3546 /* Maybe we should use the SYSTEM session_info here... */
3547 result
= winreg_get_printer_internal(mem_ctx
,
3548 get_session_info_system(),
3550 lp_servicename(snum
),
3552 if (!W_ERROR_IS_OK(result
)) {
3553 DEBUG(4, ("printserver_notify_info: "
3554 "Failed to get printer [%s]\n",
3555 lp_servicename(snum
)));
3560 construct_notify_printer_info(p
->msg_ctx
,
3566 TALLOC_FREE(pinfo2
);
3572 * Debugging information, don't delete.
3575 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3576 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3577 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3579 for (i
=0; i
<info
->count
; i
++) {
3580 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3581 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3582 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3589 /*******************************************************************
3591 * fill a notify_info struct with info asked
3593 ********************************************************************/
3595 static WERROR
printer_notify_info(struct pipes_struct
*p
,
3596 struct policy_handle
*hnd
,
3597 struct spoolss_NotifyInfo
*info
,
3598 TALLOC_CTX
*mem_ctx
)
3601 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3604 struct spoolss_NotifyOption
*option
;
3605 struct spoolss_NotifyOptionType option_type
;
3607 print_queue_struct
*queue
=NULL
;
3608 print_status_struct status
;
3609 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3612 DEBUG(4,("printer_notify_info\n"));
3617 option
= Printer
->notify
.option
;
3621 info
->notifies
= NULL
;
3624 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3625 sending a ffpcn() request first */
3630 if (!get_printer_snum(p
, hnd
, &snum
, NULL
)) {
3634 /* Maybe we should use the SYSTEM session_info here... */
3635 result
= winreg_get_printer_internal(mem_ctx
,
3636 get_session_info_system(),
3638 lp_servicename(snum
), &pinfo2
);
3639 if (!W_ERROR_IS_OK(result
)) {
3644 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3645 * correct servername.
3647 pinfo2
->servername
= talloc_strdup(pinfo2
, Printer
->servername
);
3648 if (pinfo2
->servername
== NULL
) {
3652 for (i
=0; i
<option
->count
; i
++) {
3653 option_type
= option
->types
[i
];
3655 switch (option_type
.type
) {
3656 case PRINTER_NOTIFY_TYPE
:
3657 if (construct_notify_printer_info(p
->msg_ctx
,
3666 case JOB_NOTIFY_TYPE
:
3668 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
,
3671 for (j
=0; j
<count
; j
++) {
3672 construct_notify_jobs_info(p
->msg_ctx
,
3686 * Debugging information, don't delete.
3689 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3690 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3691 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3693 for (i=0; i<info->count; i++) {
3694 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3695 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3696 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3700 talloc_free(pinfo2
);
3704 /****************************************************************
3705 _spoolss_RouterRefreshPrinterChangeNotify
3706 ****************************************************************/
3708 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct
*p
,
3709 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3711 struct spoolss_NotifyInfo
*info
;
3713 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3714 WERROR result
= WERR_BADFID
;
3716 /* we always have a spoolss_NotifyInfo struct */
3717 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3719 result
= WERR_NOMEM
;
3723 *r
->out
.info
= info
;
3726 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3727 "Invalid handle (%s:%u:%u).\n",
3728 OUR_HANDLE(r
->in
.handle
)));
3732 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3735 * We are now using the change value, and
3736 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3737 * I don't have a global notification system, I'm sending back all the
3738 * information even when _NOTHING_ has changed.
3741 /* We need to keep track of the change value to send back in
3742 RRPCN replies otherwise our updates are ignored. */
3744 Printer
->notify
.fnpcn
= true;
3746 if (Printer
->notify
.cli_chan
!= NULL
&&
3747 Printer
->notify
.cli_chan
->active_connections
> 0) {
3748 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3749 "Saving change value in request [%x]\n",
3751 Printer
->notify
.change
= r
->in
.change_low
;
3754 /* just ignore the spoolss_NotifyOption */
3756 switch (Printer
->printer_type
) {
3758 result
= printserver_notify_info(p
, r
->in
.handle
,
3762 case SPLHND_PRINTER
:
3763 result
= printer_notify_info(p
, r
->in
.handle
,
3768 Printer
->notify
.fnpcn
= false;
3774 /********************************************************************
3775 ********************************************************************/
3777 static WERROR
create_printername(TALLOC_CTX
*mem_ctx
,
3778 const char *servername
,
3779 const char *printername
,
3780 const char **printername_p
)
3782 /* FIXME: add lp_force_printername() */
3784 if (servername
== NULL
) {
3785 *printername_p
= talloc_strdup(mem_ctx
, printername
);
3786 W_ERROR_HAVE_NO_MEMORY(*printername_p
);
3790 if (servername
[0] == '\\' && servername
[1] == '\\') {
3794 *printername_p
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s", servername
, printername
);
3795 W_ERROR_HAVE_NO_MEMORY(*printername_p
);
3800 /********************************************************************
3801 ********************************************************************/
3803 static void compose_devicemode_devicename(struct spoolss_DeviceMode
*dm
,
3804 const char *printername
)
3810 dm
->devicename
= talloc_strndup(dm
, printername
,
3811 MIN(strlen(printername
), 31));
3814 /********************************************************************
3815 * construct_printer_info_0
3816 * fill a printer_info_0 struct
3817 ********************************************************************/
3819 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3820 const struct auth_serversupplied_info
*session_info
,
3821 struct messaging_context
*msg_ctx
,
3822 struct spoolss_PrinterInfo2
*info2
,
3823 const char *servername
,
3824 struct spoolss_PrinterInfo0
*r
,
3828 struct printer_session_counter
*session_counter
;
3829 struct timeval setuptime
;
3830 print_status_struct status
;
3833 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
3834 if (!W_ERROR_IS_OK(result
)) {
3839 r
->servername
= talloc_strdup(mem_ctx
, servername
);
3840 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3842 r
->servername
= NULL
;
3845 count
= print_queue_length(msg_ctx
, snum
, &status
);
3847 /* check if we already have a counter for this printer */
3848 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3849 if (session_counter
->snum
== snum
)
3853 /* it's the first time, add it to the list */
3854 if (session_counter
== NULL
) {
3855 session_counter
= talloc_zero(counter_list
, struct printer_session_counter
);
3856 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3857 session_counter
->snum
= snum
;
3858 session_counter
->counter
= 0;
3859 DLIST_ADD(counter_list
, session_counter
);
3863 session_counter
->counter
++;
3869 get_startup_time(&setuptime
);
3870 init_systemtime(&r
->time
, gmtime(&setuptime
.tv_sec
));
3873 * the global_counter should be stored in a TDB as it's common to all the clients
3874 * and should be zeroed on samba startup
3876 r
->global_counter
= session_counter
->counter
;
3878 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3879 SSVAL(&r
->version
, 0, 0x0005); /* NT 5 */
3880 SSVAL(&r
->version
, 2, 0x0893); /* build 2195 */
3881 r
->free_build
= SPOOLSS_RELEASE_BUILD
;
3883 r
->max_spooling
= 0;
3884 r
->session_counter
= session_counter
->counter
;
3885 r
->num_error_out_of_paper
= 0x0;
3886 r
->num_error_not_ready
= 0x0; /* number of print failure */
3888 r
->number_of_processors
= 0x1;
3889 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3890 r
->high_part_total_bytes
= 0x0;
3892 /* ChangeID in milliseconds*/
3893 winreg_printer_get_changeid_internal(mem_ctx
, session_info
, msg_ctx
,
3894 info2
->sharename
, &r
->change_id
);
3896 r
->last_error
= WERR_OK
;
3897 r
->status
= nt_printq_status(status
.status
);
3898 r
->enumerate_network_printers
= 0x0;
3899 r
->c_setprinter
= 0x0;
3900 r
->processor_architecture
= PROCESSOR_ARCHITECTURE_INTEL
;
3901 r
->processor_level
= 0x6; /* 6 ???*/
3910 /********************************************************************
3911 * construct_printer_info1
3912 * fill a spoolss_PrinterInfo1 struct
3913 ********************************************************************/
3915 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
3916 const struct spoolss_PrinterInfo2
*info2
,
3918 const char *servername
,
3919 struct spoolss_PrinterInfo1
*r
,
3926 if (info2
->comment
== NULL
|| info2
->comment
[0] == '\0') {
3927 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3929 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
); /* saved comment */
3931 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3933 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->name
);
3934 if (!W_ERROR_IS_OK(result
)) {
3938 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
3942 W_ERROR_HAVE_NO_MEMORY(r
->description
);
3947 /********************************************************************
3948 * construct_printer_info2
3949 * fill a spoolss_PrinterInfo2 struct
3950 ********************************************************************/
3952 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
3953 struct messaging_context
*msg_ctx
,
3954 const struct spoolss_PrinterInfo2
*info2
,
3955 const char *servername
,
3956 struct spoolss_PrinterInfo2
*r
,
3960 print_status_struct status
;
3963 count
= print_queue_length(msg_ctx
, snum
, &status
);
3966 r
->servername
= talloc_strdup(mem_ctx
, servername
);
3967 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3969 r
->servername
= NULL
;
3972 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
3973 if (!W_ERROR_IS_OK(result
)) {
3977 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
3978 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
3979 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
3980 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3981 r
->drivername
= talloc_strdup(mem_ctx
, info2
->drivername
);
3982 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
3984 if (info2
->comment
[0] == '\0') {
3985 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3987 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
);
3989 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3991 r
->location
= talloc_strdup(mem_ctx
, info2
->location
);
3992 if (info2
->location
[0] == '\0') {
3993 const char *loc
= NULL
;
3996 nt_status
= printer_list_get_printer(mem_ctx
,
4001 if (NT_STATUS_IS_OK(nt_status
)) {
4003 r
->location
= talloc_strdup(mem_ctx
, loc
);
4007 W_ERROR_HAVE_NO_MEMORY(r
->location
);
4009 r
->sepfile
= talloc_strdup(mem_ctx
, info2
->sepfile
);
4010 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
4011 r
->printprocessor
= talloc_strdup(mem_ctx
, info2
->printprocessor
);
4012 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
4013 r
->datatype
= talloc_strdup(mem_ctx
, info2
->datatype
);
4014 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
4015 r
->parameters
= talloc_strdup(mem_ctx
, info2
->parameters
);
4016 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
4018 r
->attributes
= info2
->attributes
;
4020 r
->priority
= info2
->priority
;
4021 r
->defaultpriority
= info2
->defaultpriority
;
4022 r
->starttime
= info2
->starttime
;
4023 r
->untiltime
= info2
->untiltime
;
4024 r
->status
= nt_printq_status(status
.status
);
4026 r
->averageppm
= info2
->averageppm
;
4028 if (info2
->devmode
!= NULL
) {
4029 result
= copy_devicemode(mem_ctx
,
4032 if (!W_ERROR_IS_OK(result
)) {
4035 } else if (lp_default_devmode(snum
)) {
4036 result
= spoolss_create_default_devmode(mem_ctx
,
4039 if (!W_ERROR_IS_OK(result
)) {
4044 DEBUG(8,("Returning NULL Devicemode!\n"));
4047 compose_devicemode_devicename(r
->devmode
, r
->printername
);
4051 if (info2
->secdesc
!= NULL
) {
4052 /* don't use talloc_steal() here unless you do a deep steal of all
4053 the SEC_DESC members */
4055 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
4061 /********************************************************************
4062 * construct_printer_info3
4063 * fill a spoolss_PrinterInfo3 struct
4064 ********************************************************************/
4066 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
4067 const struct spoolss_PrinterInfo2
*info2
,
4068 const char *servername
,
4069 struct spoolss_PrinterInfo3
*r
,
4072 /* These are the components of the SD we are returning. */
4074 if (info2
->secdesc
!= NULL
) {
4075 /* don't use talloc_steal() here unless you do a deep steal of all
4076 the SEC_DESC members */
4078 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
4079 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
4085 /********************************************************************
4086 * construct_printer_info4
4087 * fill a spoolss_PrinterInfo4 struct
4088 ********************************************************************/
4090 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
4091 const struct spoolss_PrinterInfo2
*info2
,
4092 const char *servername
,
4093 struct spoolss_PrinterInfo4
*r
,
4098 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4099 if (!W_ERROR_IS_OK(result
)) {
4104 r
->servername
= talloc_strdup(mem_ctx
, servername
);
4105 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4107 r
->servername
= NULL
;
4110 r
->attributes
= info2
->attributes
;
4115 /********************************************************************
4116 * construct_printer_info5
4117 * fill a spoolss_PrinterInfo5 struct
4118 ********************************************************************/
4120 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
4121 const struct spoolss_PrinterInfo2
*info2
,
4122 const char *servername
,
4123 struct spoolss_PrinterInfo5
*r
,
4128 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4129 if (!W_ERROR_IS_OK(result
)) {
4133 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
4134 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4136 r
->attributes
= info2
->attributes
;
4138 /* these two are not used by NT+ according to MSDN */
4139 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4140 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4145 /********************************************************************
4146 * construct_printer_info_6
4147 * fill a spoolss_PrinterInfo6 struct
4148 ********************************************************************/
4150 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
4151 struct messaging_context
*msg_ctx
,
4152 const struct spoolss_PrinterInfo2
*info2
,
4153 const char *servername
,
4154 struct spoolss_PrinterInfo6
*r
,
4158 print_status_struct status
;
4160 count
= print_queue_length(msg_ctx
, snum
, &status
);
4162 r
->status
= nt_printq_status(status
.status
);
4167 /********************************************************************
4168 * construct_printer_info7
4169 * fill a spoolss_PrinterInfo7 struct
4170 ********************************************************************/
4172 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
4173 struct messaging_context
*msg_ctx
,
4174 const char *servername
,
4175 struct spoolss_PrinterInfo7
*r
,
4178 struct auth_serversupplied_info
*session_info
;
4182 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
4183 if (tmp_ctx
== NULL
) {
4187 status
= make_session_info_system(tmp_ctx
, &session_info
);
4188 if (!NT_STATUS_IS_OK(status
)) {
4189 DEBUG(0, ("construct_printer_info7: "
4190 "Could not create system session_info\n"));
4195 printer
= lp_servicename(snum
);
4196 if (printer
== NULL
) {
4197 DEBUG(0, ("invalid printer snum %d\n", snum
));
4198 werr
= WERR_INVALID_PARAM
;
4202 if (is_printer_published(tmp_ctx
, session_info
, msg_ctx
,
4203 servername
, printer
, NULL
)) {
4205 werr
= nt_printer_guid_get(tmp_ctx
, session_info
, msg_ctx
,
4207 if (!W_ERROR_IS_OK(werr
)) {
4210 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
4211 r
->action
= DSPRINT_PUBLISH
;
4213 r
->guid
= talloc_strdup(mem_ctx
, "");
4214 r
->action
= DSPRINT_UNPUBLISH
;
4216 if (r
->guid
== NULL
) {
4223 talloc_free(tmp_ctx
);
4227 /********************************************************************
4228 * construct_printer_info8
4229 * fill a spoolss_PrinterInfo8 struct
4230 ********************************************************************/
4232 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
4233 const struct spoolss_PrinterInfo2
*info2
,
4234 const char *servername
,
4235 struct spoolss_DeviceModeInfo
*r
,
4239 const char *printername
;
4241 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &printername
);
4242 if (!W_ERROR_IS_OK(result
)) {
4246 if (info2
->devmode
!= NULL
) {
4247 result
= copy_devicemode(mem_ctx
,
4250 if (!W_ERROR_IS_OK(result
)) {
4253 } else if (lp_default_devmode(snum
)) {
4254 result
= spoolss_create_default_devmode(mem_ctx
,
4257 if (!W_ERROR_IS_OK(result
)) {
4262 DEBUG(8,("Returning NULL Devicemode!\n"));
4265 compose_devicemode_devicename(r
->devmode
, printername
);
4271 /********************************************************************
4272 ********************************************************************/
4274 static bool snum_is_shared_printer(int snum
)
4276 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
4279 /********************************************************************
4280 Spoolss_enumprinters.
4281 ********************************************************************/
4283 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
4284 const struct auth_serversupplied_info
*session_info
,
4285 struct messaging_context
*msg_ctx
,
4286 const char *servername
,
4289 union spoolss_PrinterInfo
**info_p
,
4293 int n_services
= lp_numservices();
4294 union spoolss_PrinterInfo
*info
= NULL
;
4296 WERROR result
= WERR_OK
;
4297 struct dcerpc_binding_handle
*b
= NULL
;
4302 for (snum
= 0; snum
< n_services
; snum
++) {
4304 const char *printer
;
4305 struct spoolss_PrinterInfo2
*info2
;
4307 if (!snum_is_shared_printer(snum
)) {
4311 printer
= lp_const_servicename(snum
);
4313 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4317 result
= winreg_printer_binding_handle(mem_ctx
,
4321 if (!W_ERROR_IS_OK(result
)) {
4326 result
= winreg_create_printer(mem_ctx
, b
,
4328 if (!W_ERROR_IS_OK(result
)) {
4332 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4333 union spoolss_PrinterInfo
,
4336 result
= WERR_NOMEM
;
4340 result
= winreg_get_printer(mem_ctx
, b
,
4342 if (!W_ERROR_IS_OK(result
)) {
4348 result
= construct_printer_info0(info
, session_info
,
4351 &info
[count
].info0
, snum
);
4354 result
= construct_printer_info1(info
, info2
, flags
,
4356 &info
[count
].info1
, snum
);
4359 result
= construct_printer_info2(info
, msg_ctx
, info2
,
4361 &info
[count
].info2
, snum
);
4364 result
= construct_printer_info4(info
, info2
,
4366 &info
[count
].info4
, snum
);
4369 result
= construct_printer_info5(info
, info2
,
4371 &info
[count
].info5
, snum
);
4375 result
= WERR_UNKNOWN_LEVEL
;
4379 if (!W_ERROR_IS_OK(result
)) {
4390 if (!W_ERROR_IS_OK(result
)) {
4400 /********************************************************************
4401 * handle enumeration of printers at level 0
4402 ********************************************************************/
4404 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
4405 const struct auth_serversupplied_info
*session_info
,
4406 struct messaging_context
*msg_ctx
,
4408 const char *servername
,
4409 union spoolss_PrinterInfo
**info
,
4412 DEBUG(4,("enum_all_printers_info_0\n"));
4414 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4415 servername
, 0, flags
, info
, count
);
4419 /********************************************************************
4420 ********************************************************************/
4422 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4423 const struct auth_serversupplied_info
*session_info
,
4424 struct messaging_context
*msg_ctx
,
4425 const char *servername
,
4427 union spoolss_PrinterInfo
**info
,
4430 DEBUG(4,("enum_all_printers_info_1\n"));
4432 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4433 servername
, 1, flags
, info
, count
);
4436 /********************************************************************
4437 enum_all_printers_info_1_local.
4438 *********************************************************************/
4440 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4441 const struct auth_serversupplied_info
*session_info
,
4442 struct messaging_context
*msg_ctx
,
4443 const char *servername
,
4444 union spoolss_PrinterInfo
**info
,
4447 DEBUG(4,("enum_all_printers_info_1_local\n"));
4449 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4450 servername
, PRINTER_ENUM_ICON8
, info
, count
);
4453 /********************************************************************
4454 enum_all_printers_info_1_name.
4455 *********************************************************************/
4457 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4458 const struct auth_serversupplied_info
*session_info
,
4459 struct messaging_context
*msg_ctx
,
4460 const char *servername
,
4461 union spoolss_PrinterInfo
**info
,
4464 const char *s
= servername
;
4466 DEBUG(4,("enum_all_printers_info_1_name\n"));
4468 if (servername
!= NULL
&&
4469 (servername
[0] == '\\') && (servername
[1] == '\\')) {
4473 if (!is_myname_or_ipaddr(s
)) {
4474 return WERR_INVALID_NAME
;
4477 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4478 servername
, PRINTER_ENUM_ICON8
, info
, count
);
4481 /********************************************************************
4482 enum_all_printers_info_1_network.
4483 *********************************************************************/
4485 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4486 const struct auth_serversupplied_info
*session_info
,
4487 struct messaging_context
*msg_ctx
,
4488 const char *servername
,
4489 union spoolss_PrinterInfo
**info
,
4492 const char *s
= servername
;
4494 DEBUG(4,("enum_all_printers_info_1_network\n"));
4496 /* If we respond to a enum_printers level 1 on our name with flags
4497 set to PRINTER_ENUM_REMOTE with a list of printers then these
4498 printers incorrectly appear in the APW browse list.
4499 Specifically the printers for the server appear at the workgroup
4500 level where all the other servers in the domain are
4501 listed. Windows responds to this call with a
4502 WERR_CAN_NOT_COMPLETE so we should do the same. */
4504 if (servername
!= NULL
&&
4505 (servername
[0] == '\\') && (servername
[1] == '\\')) {
4509 if (is_myname_or_ipaddr(s
)) {
4510 return WERR_CAN_NOT_COMPLETE
;
4513 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4514 servername
, PRINTER_ENUM_NAME
, info
, count
);
4517 /********************************************************************
4518 * api_spoolss_enumprinters
4520 * called from api_spoolss_enumprinters (see this to understand)
4521 ********************************************************************/
4523 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4524 const struct auth_serversupplied_info
*session_info
,
4525 struct messaging_context
*msg_ctx
,
4526 const char *servername
,
4527 union spoolss_PrinterInfo
**info
,
4530 DEBUG(4,("enum_all_printers_info_2\n"));
4532 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4533 servername
, 2, 0, info
, count
);
4536 /********************************************************************
4537 * handle enumeration of printers at level 1
4538 ********************************************************************/
4540 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4541 const struct auth_serversupplied_info
*session_info
,
4542 struct messaging_context
*msg_ctx
,
4544 const char *servername
,
4545 union spoolss_PrinterInfo
**info
,
4548 /* Not all the flags are equals */
4550 if (flags
& PRINTER_ENUM_LOCAL
) {
4551 return enum_all_printers_info_1_local(mem_ctx
, session_info
,
4552 msg_ctx
, servername
, info
, count
);
4555 if (flags
& PRINTER_ENUM_NAME
) {
4556 return enum_all_printers_info_1_name(mem_ctx
, session_info
,
4557 msg_ctx
, servername
, info
,
4561 if (flags
& PRINTER_ENUM_NETWORK
) {
4562 return enum_all_printers_info_1_network(mem_ctx
, session_info
,
4563 msg_ctx
, servername
, info
,
4567 return WERR_OK
; /* NT4sp5 does that */
4570 /********************************************************************
4571 * handle enumeration of printers at level 2
4572 ********************************************************************/
4574 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4575 const struct auth_serversupplied_info
*session_info
,
4576 struct messaging_context
*msg_ctx
,
4578 const char *servername
,
4579 union spoolss_PrinterInfo
**info
,
4582 if (flags
& PRINTER_ENUM_LOCAL
) {
4584 return enum_all_printers_info_2(mem_ctx
, session_info
, msg_ctx
,
4589 if (flags
& PRINTER_ENUM_NAME
) {
4590 if (servername
&& !is_myname_or_ipaddr(canon_servername(servername
))) {
4591 return WERR_INVALID_NAME
;
4594 return enum_all_printers_info_2(mem_ctx
, session_info
, msg_ctx
,
4599 if (flags
& PRINTER_ENUM_REMOTE
) {
4600 return WERR_UNKNOWN_LEVEL
;
4606 /********************************************************************
4607 * handle enumeration of printers at level 4
4608 ********************************************************************/
4610 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4611 const struct auth_serversupplied_info
*session_info
,
4612 struct messaging_context
*msg_ctx
,
4614 const char *servername
,
4615 union spoolss_PrinterInfo
**info
,
4618 DEBUG(4,("enum_all_printers_info_4\n"));
4620 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4621 servername
, 4, flags
, info
, count
);
4625 /********************************************************************
4626 * handle enumeration of printers at level 5
4627 ********************************************************************/
4629 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4630 const struct auth_serversupplied_info
*session_info
,
4631 struct messaging_context
*msg_ctx
,
4633 const char *servername
,
4634 union spoolss_PrinterInfo
**info
,
4637 DEBUG(4,("enum_all_printers_info_5\n"));
4639 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4640 servername
, 5, flags
, info
, count
);
4643 /****************************************************************
4644 _spoolss_EnumPrinters
4645 ****************************************************************/
4647 WERROR
_spoolss_EnumPrinters(struct pipes_struct
*p
,
4648 struct spoolss_EnumPrinters
*r
)
4650 const struct auth_serversupplied_info
*session_info
= get_session_info_system();
4653 /* that's an [in out] buffer */
4655 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4656 return WERR_INVALID_PARAM
;
4659 DEBUG(4,("_spoolss_EnumPrinters\n"));
4663 *r
->out
.info
= NULL
;
4667 * flags==PRINTER_ENUM_NAME
4668 * if name=="" then enumerates all printers
4669 * if name!="" then enumerate the printer
4670 * flags==PRINTER_ENUM_REMOTE
4671 * name is NULL, enumerate printers
4672 * Level 2: name!="" enumerates printers, name can't be NULL
4673 * Level 3: doesn't exist
4674 * Level 4: does a local registry lookup
4675 * Level 5: same as Level 2
4678 if (r
->in
.server
&& r
->in
.server
[0] == '\0') {
4679 r
->in
.server
= NULL
;
4682 switch (r
->in
.level
) {
4684 result
= enumprinters_level0(p
->mem_ctx
, session_info
,
4685 p
->msg_ctx
, r
->in
.flags
,
4687 r
->out
.info
, r
->out
.count
);
4690 result
= enumprinters_level1(p
->mem_ctx
, session_info
,
4691 p
->msg_ctx
, r
->in
.flags
,
4693 r
->out
.info
, r
->out
.count
);
4696 result
= enumprinters_level2(p
->mem_ctx
, session_info
,
4697 p
->msg_ctx
, r
->in
.flags
,
4699 r
->out
.info
, r
->out
.count
);
4702 result
= enumprinters_level4(p
->mem_ctx
, session_info
,
4703 p
->msg_ctx
, r
->in
.flags
,
4705 r
->out
.info
, r
->out
.count
);
4708 result
= enumprinters_level5(p
->mem_ctx
, session_info
,
4709 p
->msg_ctx
, r
->in
.flags
,
4711 r
->out
.info
, r
->out
.count
);
4714 return WERR_UNKNOWN_LEVEL
;
4717 if (!W_ERROR_IS_OK(result
)) {
4721 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4722 spoolss_EnumPrinters
,
4723 *r
->out
.info
, r
->in
.level
,
4725 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4726 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4728 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4731 /****************************************************************
4733 ****************************************************************/
4735 WERROR
_spoolss_GetPrinter(struct pipes_struct
*p
,
4736 struct spoolss_GetPrinter
*r
)
4738 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4739 struct spoolss_PrinterInfo2
*info2
= NULL
;
4740 WERROR result
= WERR_OK
;
4743 /* that's an [in out] buffer */
4745 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4746 return WERR_INVALID_PARAM
;
4751 if (Printer
== NULL
) {
4755 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4759 result
= winreg_get_printer_internal(p
->mem_ctx
,
4760 get_session_info_system(),
4762 lp_const_servicename(snum
),
4764 if (!W_ERROR_IS_OK(result
)) {
4768 switch (r
->in
.level
) {
4770 result
= construct_printer_info0(p
->mem_ctx
,
4771 get_session_info_system(),
4774 Printer
->servername
,
4775 &r
->out
.info
->info0
,
4779 result
= construct_printer_info1(p
->mem_ctx
, info2
,
4781 Printer
->servername
,
4782 &r
->out
.info
->info1
, snum
);
4785 result
= construct_printer_info2(p
->mem_ctx
, p
->msg_ctx
, info2
,
4786 Printer
->servername
,
4787 &r
->out
.info
->info2
, snum
);
4790 result
= construct_printer_info3(p
->mem_ctx
, info2
,
4791 Printer
->servername
,
4792 &r
->out
.info
->info3
, snum
);
4795 result
= construct_printer_info4(p
->mem_ctx
, info2
,
4796 Printer
->servername
,
4797 &r
->out
.info
->info4
, snum
);
4800 result
= construct_printer_info5(p
->mem_ctx
, info2
,
4801 Printer
->servername
,
4802 &r
->out
.info
->info5
, snum
);
4805 result
= construct_printer_info6(p
->mem_ctx
, p
->msg_ctx
, info2
,
4806 Printer
->servername
,
4807 &r
->out
.info
->info6
, snum
);
4810 result
= construct_printer_info7(p
->mem_ctx
, p
->msg_ctx
,
4811 Printer
->servername
,
4812 &r
->out
.info
->info7
, snum
);
4815 result
= construct_printer_info8(p
->mem_ctx
, info2
,
4816 Printer
->servername
,
4817 &r
->out
.info
->info8
, snum
);
4820 result
= WERR_UNKNOWN_LEVEL
;
4825 if (!W_ERROR_IS_OK(result
)) {
4826 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4827 r
->in
.level
, win_errstr(result
)));
4828 TALLOC_FREE(r
->out
.info
);
4832 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
,
4833 r
->out
.info
, r
->in
.level
);
4834 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4836 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4839 /********************************************************************
4840 ********************************************************************/
4842 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4844 if (in && strlen(in)) { \
4845 out = talloc_strdup(mem_ctx, in); \
4847 out = talloc_strdup(mem_ctx, ""); \
4849 W_ERROR_HAVE_NO_MEMORY(out); \
4852 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4854 if (in && strlen(in)) { \
4855 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4857 out = talloc_strdup(mem_ctx, ""); \
4859 W_ERROR_HAVE_NO_MEMORY(out); \
4862 static WERROR
string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4863 const char **string_array
,
4864 const char ***presult
,
4865 const char *cservername
,
4869 int i
, num_strings
= 0;
4870 const char **array
= NULL
;
4872 if (string_array
== NULL
) {
4873 return WERR_INVALID_PARAMETER
;
4876 for (i
=0; string_array
[i
] && string_array
[i
][0] != '\0'; i
++) {
4877 const char *str
= NULL
;
4879 if (cservername
== NULL
|| arch
== NULL
) {
4880 FILL_DRIVER_STRING(mem_ctx
, string_array
[i
], str
);
4882 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
, arch
, version
, string_array
[i
], str
);
4885 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4892 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4893 &array
, &num_strings
);
4903 /********************************************************************
4904 * fill a spoolss_DriverInfo1 struct
4905 ********************************************************************/
4907 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4908 struct spoolss_DriverInfo1
*r
,
4909 const struct spoolss_DriverInfo8
*driver
,
4910 const char *servername
)
4912 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4913 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4918 /********************************************************************
4919 * fill a spoolss_DriverInfo2 struct
4920 ********************************************************************/
4922 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4923 struct spoolss_DriverInfo2
*r
,
4924 const struct spoolss_DriverInfo8
*driver
,
4925 const char *servername
)
4928 const char *cservername
= canon_servername(servername
);
4930 r
->version
= driver
->version
;
4932 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4933 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4934 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4935 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4937 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4938 driver
->architecture
,
4940 driver
->driver_path
,
4943 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4944 driver
->architecture
,
4949 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4950 driver
->architecture
,
4952 driver
->config_file
,
4958 /********************************************************************
4959 * fill a spoolss_DriverInfo3 struct
4960 ********************************************************************/
4962 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4963 struct spoolss_DriverInfo3
*r
,
4964 const struct spoolss_DriverInfo8
*driver
,
4965 const char *servername
)
4967 const char *cservername
= canon_servername(servername
);
4969 r
->version
= driver
->version
;
4971 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4972 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4973 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4974 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4976 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4977 driver
->architecture
,
4979 driver
->driver_path
,
4982 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4983 driver
->architecture
,
4988 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4989 driver
->architecture
,
4991 driver
->config_file
,
4994 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4995 driver
->architecture
,
5000 FILL_DRIVER_STRING(mem_ctx
,
5001 driver
->monitor_name
,
5004 FILL_DRIVER_STRING(mem_ctx
,
5005 driver
->default_datatype
,
5006 r
->default_datatype
);
5008 return string_array_from_driver_info(mem_ctx
,
5009 driver
->dependent_files
,
5010 &r
->dependent_files
,
5012 driver
->architecture
,
5016 /********************************************************************
5017 * fill a spoolss_DriverInfo4 struct
5018 ********************************************************************/
5020 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
5021 struct spoolss_DriverInfo4
*r
,
5022 const struct spoolss_DriverInfo8
*driver
,
5023 const char *servername
)
5025 const char *cservername
= canon_servername(servername
);
5028 r
->version
= driver
->version
;
5030 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5031 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5032 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5033 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5035 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5036 driver
->architecture
,
5038 driver
->driver_path
,
5041 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5042 driver
->architecture
,
5047 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5048 driver
->architecture
,
5050 driver
->config_file
,
5053 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5054 driver
->architecture
,
5059 result
= string_array_from_driver_info(mem_ctx
,
5060 driver
->dependent_files
,
5061 &r
->dependent_files
,
5063 driver
->architecture
,
5065 if (!W_ERROR_IS_OK(result
)) {
5069 FILL_DRIVER_STRING(mem_ctx
,
5070 driver
->monitor_name
,
5073 FILL_DRIVER_STRING(mem_ctx
,
5074 driver
->default_datatype
,
5075 r
->default_datatype
);
5078 result
= string_array_from_driver_info(mem_ctx
,
5079 driver
->previous_names
,
5086 /********************************************************************
5087 * fill a spoolss_DriverInfo5 struct
5088 ********************************************************************/
5090 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
5091 struct spoolss_DriverInfo5
*r
,
5092 const struct spoolss_DriverInfo8
*driver
,
5093 const char *servername
)
5095 const char *cservername
= canon_servername(servername
);
5097 r
->version
= driver
->version
;
5099 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5100 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5101 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5102 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5104 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5105 driver
->architecture
,
5107 driver
->driver_path
,
5110 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5111 driver
->architecture
,
5116 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5117 driver
->architecture
,
5119 driver
->config_file
,
5122 r
->driver_attributes
= 0;
5123 r
->config_version
= 0;
5124 r
->driver_version
= 0;
5128 /********************************************************************
5129 * fill a spoolss_DriverInfo6 struct
5130 ********************************************************************/
5132 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
5133 struct spoolss_DriverInfo6
*r
,
5134 const struct spoolss_DriverInfo8
*driver
,
5135 const char *servername
)
5137 const char *cservername
= canon_servername(servername
);
5140 r
->version
= driver
->version
;
5142 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5143 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5144 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5145 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5147 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5148 driver
->architecture
,
5150 driver
->driver_path
,
5153 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5154 driver
->architecture
,
5159 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5160 driver
->architecture
,
5162 driver
->config_file
,
5165 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5166 driver
->architecture
,
5171 FILL_DRIVER_STRING(mem_ctx
,
5172 driver
->monitor_name
,
5175 FILL_DRIVER_STRING(mem_ctx
,
5176 driver
->default_datatype
,
5177 r
->default_datatype
);
5179 result
= string_array_from_driver_info(mem_ctx
,
5180 driver
->dependent_files
,
5181 &r
->dependent_files
,
5183 driver
->architecture
,
5185 if (!W_ERROR_IS_OK(result
)) {
5189 result
= string_array_from_driver_info(mem_ctx
,
5190 driver
->previous_names
,
5193 if (!W_ERROR_IS_OK(result
)) {
5197 r
->driver_date
= driver
->driver_date
;
5198 r
->driver_version
= driver
->driver_version
;
5200 FILL_DRIVER_STRING(mem_ctx
,
5201 driver
->manufacturer_name
,
5202 r
->manufacturer_name
);
5203 FILL_DRIVER_STRING(mem_ctx
,
5204 driver
->manufacturer_url
,
5205 r
->manufacturer_url
);
5206 FILL_DRIVER_STRING(mem_ctx
,
5207 driver
->hardware_id
,
5209 FILL_DRIVER_STRING(mem_ctx
,
5216 /********************************************************************
5217 * fill a spoolss_DriverInfo8 struct
5218 ********************************************************************/
5220 static WERROR
fill_printer_driver_info8(TALLOC_CTX
*mem_ctx
,
5221 struct spoolss_DriverInfo8
*r
,
5222 const struct spoolss_DriverInfo8
*driver
,
5223 const char *servername
)
5225 const char *cservername
= canon_servername(servername
);
5228 r
->version
= driver
->version
;
5230 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5231 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5232 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5233 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5235 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5236 driver
->architecture
,
5238 driver
->driver_path
,
5241 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5242 driver
->architecture
,
5247 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5248 driver
->architecture
,
5250 driver
->config_file
,
5253 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5254 driver
->architecture
,
5259 FILL_DRIVER_STRING(mem_ctx
,
5260 driver
->monitor_name
,
5263 FILL_DRIVER_STRING(mem_ctx
,
5264 driver
->default_datatype
,
5265 r
->default_datatype
);
5267 result
= string_array_from_driver_info(mem_ctx
,
5268 driver
->dependent_files
,
5269 &r
->dependent_files
,
5271 driver
->architecture
,
5273 if (!W_ERROR_IS_OK(result
)) {
5277 result
= string_array_from_driver_info(mem_ctx
,
5278 driver
->previous_names
,
5281 if (!W_ERROR_IS_OK(result
)) {
5285 r
->driver_date
= driver
->driver_date
;
5286 r
->driver_version
= driver
->driver_version
;
5288 FILL_DRIVER_STRING(mem_ctx
,
5289 driver
->manufacturer_name
,
5290 r
->manufacturer_name
);
5291 FILL_DRIVER_STRING(mem_ctx
,
5292 driver
->manufacturer_url
,
5293 r
->manufacturer_url
);
5294 FILL_DRIVER_STRING(mem_ctx
,
5295 driver
->hardware_id
,
5297 FILL_DRIVER_STRING(mem_ctx
,
5301 FILL_DRIVER_STRING(mem_ctx
,
5302 driver
->print_processor
,
5303 r
->print_processor
);
5304 FILL_DRIVER_STRING(mem_ctx
,
5305 driver
->vendor_setup
,
5308 result
= string_array_from_driver_info(mem_ctx
,
5309 driver
->color_profiles
,
5312 if (!W_ERROR_IS_OK(result
)) {
5316 FILL_DRIVER_STRING(mem_ctx
,
5320 r
->printer_driver_attributes
= driver
->printer_driver_attributes
;
5322 result
= string_array_from_driver_info(mem_ctx
,
5323 driver
->core_driver_dependencies
,
5324 &r
->core_driver_dependencies
,
5326 if (!W_ERROR_IS_OK(result
)) {
5330 r
->min_inbox_driver_ver_date
= driver
->min_inbox_driver_ver_date
;
5331 r
->min_inbox_driver_ver_version
= driver
->min_inbox_driver_ver_version
;
5336 #if 0 /* disabled until marshalling issues are resolved - gd */
5337 /********************************************************************
5338 ********************************************************************/
5340 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
5341 struct spoolss_DriverFileInfo
*r
,
5342 const char *cservername
,
5343 const char *file_name
,
5344 enum spoolss_DriverFileType file_type
,
5345 uint32_t file_version
)
5347 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
5348 cservername
, file_name
);
5349 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
5350 r
->file_type
= file_type
;
5351 r
->file_version
= file_version
;
5356 /********************************************************************
5357 ********************************************************************/
5359 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
5360 const struct spoolss_DriverInfo8
*driver
,
5361 const char *cservername
,
5362 struct spoolss_DriverFileInfo
**info_p
,
5365 struct spoolss_DriverFileInfo
*info
= NULL
;
5373 if (strlen(driver
->driver_path
)) {
5374 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5375 struct spoolss_DriverFileInfo
,
5377 W_ERROR_HAVE_NO_MEMORY(info
);
5378 result
= fill_spoolss_DriverFileInfo(info
,
5381 driver
->driver_path
,
5382 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
5384 W_ERROR_NOT_OK_RETURN(result
);
5388 if (strlen(driver
->config_file
)) {
5389 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5390 struct spoolss_DriverFileInfo
,
5392 W_ERROR_HAVE_NO_MEMORY(info
);
5393 result
= fill_spoolss_DriverFileInfo(info
,
5396 driver
->config_file
,
5397 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
5399 W_ERROR_NOT_OK_RETURN(result
);
5403 if (strlen(driver
->data_file
)) {
5404 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5405 struct spoolss_DriverFileInfo
,
5407 W_ERROR_HAVE_NO_MEMORY(info
);
5408 result
= fill_spoolss_DriverFileInfo(info
,
5412 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
5414 W_ERROR_NOT_OK_RETURN(result
);
5418 if (strlen(driver
->help_file
)) {
5419 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5420 struct spoolss_DriverFileInfo
,
5422 W_ERROR_HAVE_NO_MEMORY(info
);
5423 result
= fill_spoolss_DriverFileInfo(info
,
5427 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
5429 W_ERROR_NOT_OK_RETURN(result
);
5433 for (i
=0; driver
->dependent_files
[i
] && driver
->dependent_files
[i
][0] != '\0'; i
++) {
5434 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5435 struct spoolss_DriverFileInfo
,
5437 W_ERROR_HAVE_NO_MEMORY(info
);
5438 result
= fill_spoolss_DriverFileInfo(info
,
5441 driver
->dependent_files
[i
],
5442 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
5444 W_ERROR_NOT_OK_RETURN(result
);
5454 /********************************************************************
5455 * fill a spoolss_DriverInfo101 struct
5456 ********************************************************************/
5458 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
5459 struct spoolss_DriverInfo101
*r
,
5460 const struct spoolss_DriverInfo8
*driver
,
5461 const char *servername
)
5463 const char *cservername
= canon_servername(servername
);
5466 r
->version
= driver
->version
;
5468 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5469 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5470 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5471 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5473 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
5477 if (!W_ERROR_IS_OK(result
)) {
5481 FILL_DRIVER_STRING(mem_ctx
,
5482 driver
->monitor_name
,
5485 FILL_DRIVER_STRING(mem_ctx
,
5486 driver
->default_datatype
,
5487 r
->default_datatype
);
5489 result
= string_array_from_driver_info(mem_ctx
,
5490 driver
->previous_names
,
5493 if (!W_ERROR_IS_OK(result
)) {
5497 r
->driver_date
= driver
->driver_date
;
5498 r
->driver_version
= driver
->driver_version
;
5500 FILL_DRIVER_STRING(mem_ctx
,
5501 driver
->manufacturer_name
,
5502 r
->manufacturer_name
);
5503 FILL_DRIVER_STRING(mem_ctx
,
5504 driver
->manufacturer_url
,
5505 r
->manufacturer_url
);
5506 FILL_DRIVER_STRING(mem_ctx
,
5507 driver
->hardware_id
,
5509 FILL_DRIVER_STRING(mem_ctx
,
5516 /********************************************************************
5517 ********************************************************************/
5519 static WERROR
construct_printer_driver_info_level(TALLOC_CTX
*mem_ctx
,
5520 const struct auth_serversupplied_info
*session_info
,
5521 struct messaging_context
*msg_ctx
,
5523 union spoolss_DriverInfo
*r
,
5525 const char *servername
,
5526 const char *architecture
,
5529 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
5530 struct spoolss_DriverInfo8
*driver
;
5532 struct dcerpc_binding_handle
*b
;
5535 return WERR_UNKNOWN_LEVEL
;
5538 result
= winreg_printer_binding_handle(mem_ctx
,
5542 if (!W_ERROR_IS_OK(result
)) {
5546 result
= winreg_get_printer(mem_ctx
, b
,
5547 lp_const_servicename(snum
),
5550 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5551 win_errstr(result
)));
5553 if (!W_ERROR_IS_OK(result
)) {
5554 return WERR_INVALID_PRINTER_NAME
;
5557 result
= winreg_get_driver(mem_ctx
, b
,
5559 pinfo2
->drivername
, version
, &driver
);
5561 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5562 win_errstr(result
)));
5564 if (!W_ERROR_IS_OK(result
)) {
5566 * Is this a W2k client ?
5570 talloc_free(pinfo2
);
5571 return WERR_UNKNOWN_PRINTER_DRIVER
;
5574 /* Yes - try again with a WinNT driver. */
5576 result
= winreg_get_driver(mem_ctx
, b
,
5580 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5581 win_errstr(result
)));
5582 if (!W_ERROR_IS_OK(result
)) {
5583 talloc_free(pinfo2
);
5584 return WERR_UNKNOWN_PRINTER_DRIVER
;
5590 result
= fill_printer_driver_info1(mem_ctx
, &r
->info1
, driver
, servername
);
5593 result
= fill_printer_driver_info2(mem_ctx
, &r
->info2
, driver
, servername
);
5596 result
= fill_printer_driver_info3(mem_ctx
, &r
->info3
, driver
, servername
);
5599 result
= fill_printer_driver_info4(mem_ctx
, &r
->info4
, driver
, servername
);
5602 result
= fill_printer_driver_info5(mem_ctx
, &r
->info5
, driver
, servername
);
5605 result
= fill_printer_driver_info6(mem_ctx
, &r
->info6
, driver
, servername
);
5608 result
= fill_printer_driver_info8(mem_ctx
, &r
->info8
, driver
, servername
);
5610 #if 0 /* disabled until marshalling issues are resolved - gd */
5612 result
= fill_printer_driver_info101(mem_ctx
, &r
->info101
, driver
, servername
);
5616 result
= WERR_UNKNOWN_LEVEL
;
5620 talloc_free(pinfo2
);
5621 talloc_free(driver
);
5626 /****************************************************************
5627 _spoolss_GetPrinterDriver2
5628 ****************************************************************/
5630 WERROR
_spoolss_GetPrinterDriver2(struct pipes_struct
*p
,
5631 struct spoolss_GetPrinterDriver2
*r
)
5633 struct printer_handle
*printer
;
5635 uint32_t version
= r
->in
.client_major_version
;
5639 /* that's an [in out] buffer */
5641 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5642 return WERR_INVALID_PARAM
;
5645 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5647 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5648 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5649 return WERR_INVALID_PRINTER_NAME
;
5653 *r
->out
.server_major_version
= 0;
5654 *r
->out
.server_minor_version
= 0;
5656 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5660 if (r
->in
.client_major_version
== SPOOLSS_DRIVER_VERSION_2012
) {
5661 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5662 "downgrading to v3\n"));
5663 version
= SPOOLSS_DRIVER_VERSION_200X
;
5666 result
= construct_printer_driver_info_level(p
->mem_ctx
,
5667 get_session_info_system(),
5669 r
->in
.level
, r
->out
.info
,
5670 snum
, printer
->servername
,
5673 if (!W_ERROR_IS_OK(result
)) {
5674 TALLOC_FREE(r
->out
.info
);
5678 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
,
5679 r
->out
.info
, r
->in
.level
);
5680 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5682 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5686 /****************************************************************
5687 _spoolss_StartPagePrinter
5688 ****************************************************************/
5690 WERROR
_spoolss_StartPagePrinter(struct pipes_struct
*p
,
5691 struct spoolss_StartPagePrinter
*r
)
5693 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5696 DEBUG(3,("_spoolss_StartPagePrinter: "
5697 "Error in startpageprinter printer handle\n"));
5701 Printer
->page_started
= true;
5705 /****************************************************************
5706 _spoolss_EndPagePrinter
5707 ****************************************************************/
5709 WERROR
_spoolss_EndPagePrinter(struct pipes_struct
*p
,
5710 struct spoolss_EndPagePrinter
*r
)
5714 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5717 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5718 OUR_HANDLE(r
->in
.handle
)));
5722 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5725 Printer
->page_started
= false;
5726 print_job_endpage(p
->msg_ctx
, snum
, Printer
->jobid
);
5731 /****************************************************************
5732 _spoolss_StartDocPrinter
5733 ****************************************************************/
5735 WERROR
_spoolss_StartDocPrinter(struct pipes_struct
*p
,
5736 struct spoolss_StartDocPrinter
*r
)
5738 struct spoolss_DocumentInfo1
*info_1
;
5740 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5744 DEBUG(2,("_spoolss_StartDocPrinter: "
5745 "Invalid handle (%s:%u:%u)\n",
5746 OUR_HANDLE(r
->in
.handle
)));
5750 if (Printer
->jobid
) {
5751 DEBUG(2, ("_spoolss_StartDocPrinter: "
5752 "StartDocPrinter called twice! "
5753 "(existing jobid = %d)\n", Printer
->jobid
));
5754 return WERR_INVALID_HANDLE
;
5757 if (r
->in
.level
!= 1) {
5758 return WERR_UNKNOWN_LEVEL
;
5761 info_1
= r
->in
.info
.info1
;
5764 * a nice thing with NT is it doesn't listen to what you tell it.
5765 * when asked to send _only_ RAW datas, it tries to send datas
5768 * So I add checks like in NT Server ...
5771 if (info_1
->datatype
) {
5773 * The v4 driver model used in Windows 8 declares print jobs
5774 * intended to bypass the XPS processing layer by setting
5775 * datatype to "XPS_PASS" instead of "RAW".
5777 if ((strcmp(info_1
->datatype
, "RAW") != 0)
5778 && (strcmp(info_1
->datatype
, "XPS_PASS") != 0)) {
5780 return WERR_INVALID_DATATYPE
;
5784 /* get the share number of the printer */
5785 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5789 werr
= print_job_start(p
->session_info
,
5793 info_1
->document_name
,
5794 info_1
->output_file
,
5798 /* An error occured in print_job_start() so return an appropriate
5801 if (!W_ERROR_IS_OK(werr
)) {
5805 Printer
->document_started
= true;
5806 *r
->out
.job_id
= Printer
->jobid
;
5811 /****************************************************************
5812 _spoolss_EndDocPrinter
5813 ****************************************************************/
5815 WERROR
_spoolss_EndDocPrinter(struct pipes_struct
*p
,
5816 struct spoolss_EndDocPrinter
*r
)
5818 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5823 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5824 OUR_HANDLE(r
->in
.handle
)));
5828 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5832 Printer
->document_started
= false;
5833 status
= print_job_end(p
->msg_ctx
, snum
, Printer
->jobid
, NORMAL_CLOSE
);
5834 if (!NT_STATUS_IS_OK(status
)) {
5835 DEBUG(2, ("_spoolss_EndDocPrinter: "
5836 "print_job_end failed [%s]\n",
5837 nt_errstr(status
)));
5841 return ntstatus_to_werror(status
);
5844 /****************************************************************
5845 _spoolss_WritePrinter
5846 ****************************************************************/
5848 WERROR
_spoolss_WritePrinter(struct pipes_struct
*p
,
5849 struct spoolss_WritePrinter
*r
)
5851 ssize_t buffer_written
;
5853 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5856 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5857 OUR_HANDLE(r
->in
.handle
)));
5858 *r
->out
.num_written
= r
->in
._data_size
;
5862 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5865 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5866 buffer_written
= print_job_write(server_event_context(),p
->msg_ctx
,
5867 snum
, Printer
->jobid
,
5868 (const char *)r
->in
.data
.data
,
5869 (size_t)r
->in
._data_size
);
5870 if (buffer_written
== (ssize_t
)-1) {
5871 *r
->out
.num_written
= 0;
5872 if (errno
== ENOSPC
)
5873 return WERR_NO_SPOOL_SPACE
;
5875 return WERR_ACCESS_DENIED
;
5878 *r
->out
.num_written
= r
->in
._data_size
;
5883 /********************************************************************
5884 * api_spoolss_getprinter
5885 * called from the spoolss dispatcher
5887 ********************************************************************/
5889 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5890 struct pipes_struct
*p
)
5892 const struct auth_serversupplied_info
*session_info
= p
->session_info
;
5894 WERROR errcode
= WERR_BADFUNC
;
5895 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
5898 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5899 OUR_HANDLE(handle
)));
5903 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5907 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5908 errcode
= print_queue_pause(session_info
, p
->msg_ctx
, snum
);
5910 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5911 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5912 errcode
= print_queue_resume(session_info
, p
->msg_ctx
, snum
);
5914 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5915 errcode
= print_queue_purge(session_info
, p
->msg_ctx
, snum
);
5918 return WERR_UNKNOWN_LEVEL
;
5925 /****************************************************************
5926 _spoolss_AbortPrinter
5927 * From MSDN: "Deletes printer's spool file if printer is configured
5929 ****************************************************************/
5931 WERROR
_spoolss_AbortPrinter(struct pipes_struct
*p
,
5932 struct spoolss_AbortPrinter
*r
)
5934 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5936 WERROR errcode
= WERR_OK
;
5939 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5940 OUR_HANDLE(r
->in
.handle
)));
5944 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5947 if (!Printer
->document_started
) {
5948 return WERR_SPL_NO_STARTDOC
;
5951 errcode
= print_job_delete(p
->session_info
,
5959 /********************************************************************
5960 * called by spoolss_api_setprinter
5961 * when updating a printer description
5962 ********************************************************************/
5964 static WERROR
update_printer_sec(struct policy_handle
*handle
,
5965 struct pipes_struct
*p
,
5966 struct sec_desc_buf
*secdesc_ctr
)
5968 struct spoolss_security_descriptor
*new_secdesc
= NULL
;
5969 struct spoolss_security_descriptor
*old_secdesc
= NULL
;
5970 const char *printer
;
5973 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
5974 struct dcerpc_binding_handle
*b
;
5976 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5977 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5978 OUR_HANDLE(handle
)));
5980 result
= WERR_BADFID
;
5984 if (secdesc_ctr
== NULL
) {
5985 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5986 result
= WERR_INVALID_PARAM
;
5989 printer
= lp_const_servicename(snum
);
5991 /* Check the user has permissions to change the security
5992 descriptor. By experimentation with two NT machines, the user
5993 requires Full Access to the printer to change security
5996 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5997 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5998 result
= WERR_ACCESS_DENIED
;
6002 result
= winreg_printer_binding_handle(p
->mem_ctx
,
6003 get_session_info_system(),
6006 if (!W_ERROR_IS_OK(result
)) {
6010 /* NT seems to like setting the security descriptor even though
6011 nothing may have actually changed. */
6012 result
= winreg_get_printer_secdesc(p
->mem_ctx
, b
,
6015 if (!W_ERROR_IS_OK(result
)) {
6016 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6017 result
= WERR_BADFID
;
6021 if (DEBUGLEVEL
>= 10) {
6022 struct security_acl
*the_acl
;
6025 the_acl
= old_secdesc
->dacl
;
6026 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6027 printer
, the_acl
->num_aces
));
6029 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6030 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6031 &the_acl
->aces
[i
].trustee
),
6032 the_acl
->aces
[i
].access_mask
));
6035 the_acl
= secdesc_ctr
->sd
->dacl
;
6038 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6039 printer
, the_acl
->num_aces
));
6041 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6042 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6043 &the_acl
->aces
[i
].trustee
),
6044 the_acl
->aces
[i
].access_mask
));
6047 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6051 new_secdesc
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
->sd
, old_secdesc
);
6052 if (new_secdesc
== NULL
) {
6053 result
= WERR_NOMEM
;
6057 if (security_descriptor_equal(new_secdesc
, old_secdesc
)) {
6062 result
= winreg_set_printer_secdesc(p
->mem_ctx
, b
,
6070 /********************************************************************
6071 Canonicalize printer info from a client
6072 ********************************************************************/
6074 static bool check_printer_ok(TALLOC_CTX
*mem_ctx
,
6075 struct spoolss_SetPrinterInfo2
*info2
,
6078 fstring printername
;
6081 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6082 "portname=%s drivername=%s comment=%s location=%s\n",
6083 info2
->servername
, info2
->printername
, info2
->sharename
,
6084 info2
->portname
, info2
->drivername
, info2
->comment
,
6087 /* we force some elements to "correct" values */
6088 info2
->servername
= talloc_asprintf(mem_ctx
, "\\\\%s", global_myname());
6089 if (info2
->servername
== NULL
) {
6092 info2
->sharename
= talloc_strdup(mem_ctx
, lp_const_servicename(snum
));
6093 if (info2
->sharename
== NULL
) {
6097 /* check to see if we allow printername != sharename */
6098 if (lp_force_printername(snum
)) {
6099 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6100 global_myname(), info2
->sharename
);
6102 /* make sure printername is in \\server\printername format */
6103 fstrcpy(printername
, info2
->printername
);
6105 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
6106 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
6110 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6111 global_myname(), p
);
6113 if (info2
->printername
== NULL
) {
6117 info2
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
6118 info2
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
6123 /****************************************************************************
6124 ****************************************************************************/
6126 static WERROR
add_port_hook(TALLOC_CTX
*ctx
, struct security_token
*token
, const char *portname
, const char *uri
)
6128 char *cmd
= lp_addport_cmd();
6129 char *command
= NULL
;
6131 bool is_print_op
= false;
6134 return WERR_ACCESS_DENIED
;
6137 command
= talloc_asprintf(ctx
,
6138 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
6144 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
6146 DEBUG(10,("Running [%s]\n", command
));
6148 /********* BEGIN SePrintOperatorPrivilege **********/
6153 ret
= smbrun(command
, NULL
);
6158 /********* END SePrintOperatorPrivilege **********/
6160 DEBUGADD(10,("returned [%d]\n", ret
));
6162 TALLOC_FREE(command
);
6165 return WERR_ACCESS_DENIED
;
6171 /****************************************************************************
6172 ****************************************************************************/
6174 static bool add_printer_hook(TALLOC_CTX
*ctx
, struct security_token
*token
,
6175 struct spoolss_SetPrinterInfo2
*info2
,
6176 const char *remote_machine
,
6177 struct messaging_context
*msg_ctx
)
6179 char *cmd
= lp_addprinter_cmd();
6181 char *command
= NULL
;
6185 bool is_print_op
= false;
6187 if (!remote_machine
) {
6191 command
= talloc_asprintf(ctx
,
6192 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6193 cmd
, info2
->printername
, info2
->sharename
,
6194 info2
->portname
, info2
->drivername
,
6195 info2
->location
, info2
->comment
, remote_machine
);
6201 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
6203 DEBUG(10,("Running [%s]\n", command
));
6205 /********* BEGIN SePrintOperatorPrivilege **********/
6210 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6211 /* Tell everyone we updated smb.conf. */
6212 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
6218 /********* END SePrintOperatorPrivilege **********/
6220 DEBUGADD(10,("returned [%d]\n", ret
));
6222 TALLOC_FREE(command
);
6230 /* reload our services immediately */
6232 reload_services(msg_ctx
, -1, false);
6236 /* Get lines and convert them back to dos-codepage */
6237 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
6238 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6241 /* Set the portname to what the script says the portname should be. */
6242 /* but don't require anything to be return from the script exit a good error code */
6245 /* Set the portname to what the script says the portname should be. */
6246 info2
->portname
= talloc_strdup(ctx
, qlines
[0]);
6247 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6250 TALLOC_FREE(qlines
);
6254 static WERROR
update_dsspooler(TALLOC_CTX
*mem_ctx
,
6255 const struct auth_serversupplied_info
*session_info
,
6256 struct messaging_context
*msg_ctx
,
6258 struct spoolss_SetPrinterInfo2
*printer
,
6259 struct spoolss_PrinterInfo2
*old_printer
)
6261 bool force_update
= (old_printer
== NULL
);
6262 const char *dnsdomname
;
6263 const char *longname
;
6264 const char *uncname
;
6265 const char *spooling
;
6267 WERROR result
= WERR_OK
;
6268 struct dcerpc_binding_handle
*b
;
6270 result
= winreg_printer_binding_handle(mem_ctx
,
6274 if (!W_ERROR_IS_OK(result
)) {
6278 if (force_update
|| !strequal(printer
->drivername
, old_printer
->drivername
)) {
6279 push_reg_sz(mem_ctx
, &buffer
, printer
->drivername
);
6280 winreg_set_printer_dataex(mem_ctx
, b
,
6282 SPOOL_DSSPOOLER_KEY
,
6283 SPOOL_REG_DRIVERNAME
,
6288 if (!force_update
) {
6289 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6290 printer
->drivername
));
6292 notify_printer_driver(server_event_context(), msg_ctx
,
6293 snum
, printer
->drivername
?
6294 printer
->drivername
: "");
6298 if (force_update
|| !strequal(printer
->comment
, old_printer
->comment
)) {
6299 push_reg_sz(mem_ctx
, &buffer
, printer
->comment
);
6300 winreg_set_printer_dataex(mem_ctx
, b
,
6302 SPOOL_DSSPOOLER_KEY
,
6303 SPOOL_REG_DESCRIPTION
,
6308 if (!force_update
) {
6309 notify_printer_comment(server_event_context(), msg_ctx
,
6310 snum
, printer
->comment
?
6311 printer
->comment
: "");
6315 if (force_update
|| !strequal(printer
->sharename
, old_printer
->sharename
)) {
6316 push_reg_sz(mem_ctx
, &buffer
, printer
->sharename
);
6317 winreg_set_printer_dataex(mem_ctx
, b
,
6319 SPOOL_DSSPOOLER_KEY
,
6320 SPOOL_REG_PRINTSHARENAME
,
6325 if (!force_update
) {
6326 notify_printer_sharename(server_event_context(),
6328 snum
, printer
->sharename
?
6329 printer
->sharename
: "");
6333 if (force_update
|| !strequal(printer
->printername
, old_printer
->printername
)) {
6336 p
= strrchr(printer
->printername
, '\\' );
6340 p
= printer
->printername
;
6343 push_reg_sz(mem_ctx
, &buffer
, p
);
6344 winreg_set_printer_dataex(mem_ctx
, b
,
6346 SPOOL_DSSPOOLER_KEY
,
6347 SPOOL_REG_PRINTERNAME
,
6352 if (!force_update
) {
6353 notify_printer_printername(server_event_context(),
6354 msg_ctx
, snum
, p
? p
: "");
6358 if (force_update
|| !strequal(printer
->portname
, old_printer
->portname
)) {
6359 push_reg_sz(mem_ctx
, &buffer
, printer
->portname
);
6360 winreg_set_printer_dataex(mem_ctx
, b
,
6362 SPOOL_DSSPOOLER_KEY
,
6368 if (!force_update
) {
6369 notify_printer_port(server_event_context(),
6370 msg_ctx
, snum
, printer
->portname
?
6371 printer
->portname
: "");
6375 if (force_update
|| !strequal(printer
->location
, old_printer
->location
)) {
6376 push_reg_sz(mem_ctx
, &buffer
, printer
->location
);
6377 winreg_set_printer_dataex(mem_ctx
, b
,
6379 SPOOL_DSSPOOLER_KEY
,
6385 if (!force_update
) {
6386 notify_printer_location(server_event_context(),
6389 printer
->location
: "");
6393 if (force_update
|| !strequal(printer
->sepfile
, old_printer
->sepfile
)) {
6394 push_reg_sz(mem_ctx
, &buffer
, printer
->sepfile
);
6395 winreg_set_printer_dataex(mem_ctx
, b
,
6397 SPOOL_DSSPOOLER_KEY
,
6398 SPOOL_REG_PRINTSEPARATORFILE
,
6403 if (!force_update
) {
6404 notify_printer_sepfile(server_event_context(),
6407 printer
->sepfile
: "");
6411 if (force_update
|| printer
->starttime
!= old_printer
->starttime
) {
6412 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
6413 SIVAL(buffer
.data
, 0, printer
->starttime
);
6414 winreg_set_printer_dataex(mem_ctx
, b
,
6416 SPOOL_DSSPOOLER_KEY
,
6417 SPOOL_REG_PRINTSTARTTIME
,
6423 if (force_update
|| printer
->untiltime
!= old_printer
->untiltime
) {
6424 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
6425 SIVAL(buffer
.data
, 0, printer
->untiltime
);
6426 winreg_set_printer_dataex(mem_ctx
, b
,
6428 SPOOL_DSSPOOLER_KEY
,
6429 SPOOL_REG_PRINTENDTIME
,
6435 if (force_update
|| printer
->priority
!= old_printer
->priority
) {
6436 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
6437 SIVAL(buffer
.data
, 0, printer
->priority
);
6438 winreg_set_printer_dataex(mem_ctx
, b
,
6440 SPOOL_DSSPOOLER_KEY
,
6447 if (force_update
|| printer
->attributes
!= old_printer
->attributes
) {
6448 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
6449 SIVAL(buffer
.data
, 0, (printer
->attributes
&
6450 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
6451 winreg_set_printer_dataex(mem_ctx
, b
,
6453 SPOOL_DSSPOOLER_KEY
,
6454 SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
6459 switch (printer
->attributes
& 0x3) {
6461 spooling
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
6464 spooling
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
6467 spooling
= SPOOL_REGVAL_PRINTDIRECT
;
6470 spooling
= "unknown";
6472 push_reg_sz(mem_ctx
, &buffer
, spooling
);
6473 winreg_set_printer_dataex(mem_ctx
, b
,
6475 SPOOL_DSSPOOLER_KEY
,
6476 SPOOL_REG_PRINTSPOOLING
,
6482 push_reg_sz(mem_ctx
, &buffer
, global_myname());
6483 winreg_set_printer_dataex(mem_ctx
, b
,
6485 SPOOL_DSSPOOLER_KEY
,
6486 SPOOL_REG_SHORTSERVERNAME
,
6491 dnsdomname
= get_mydnsfullname();
6492 if (dnsdomname
!= NULL
&& dnsdomname
[0] != '\0') {
6493 longname
= talloc_strdup(mem_ctx
, dnsdomname
);
6495 longname
= talloc_strdup(mem_ctx
, global_myname());
6497 if (longname
== NULL
) {
6498 result
= WERR_NOMEM
;
6502 push_reg_sz(mem_ctx
, &buffer
, longname
);
6503 winreg_set_printer_dataex(mem_ctx
, b
,
6505 SPOOL_DSSPOOLER_KEY
,
6506 SPOOL_REG_SERVERNAME
,
6511 uncname
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6512 global_myname(), printer
->sharename
);
6513 push_reg_sz(mem_ctx
, &buffer
, uncname
);
6514 winreg_set_printer_dataex(mem_ctx
, b
,
6516 SPOOL_DSSPOOLER_KEY
,
6526 /********************************************************************
6527 * Called by spoolss_api_setprinter
6528 * when updating a printer description.
6529 ********************************************************************/
6531 static WERROR
update_printer(struct pipes_struct
*p
,
6532 struct policy_handle
*handle
,
6533 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
6534 struct spoolss_DeviceMode
*devmode
)
6536 uint32_t printer_mask
= SPOOLSS_PRINTER_INFO_ALL
;
6537 struct spoolss_SetPrinterInfo2
*printer
= info_ctr
->info
.info2
;
6538 struct spoolss_PrinterInfo2
*old_printer
;
6539 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6541 WERROR result
= WERR_OK
;
6542 TALLOC_CTX
*tmp_ctx
;
6543 struct dcerpc_binding_handle
*b
;
6545 DEBUG(8,("update_printer\n"));
6547 tmp_ctx
= talloc_new(p
->mem_ctx
);
6548 if (tmp_ctx
== NULL
) {
6553 result
= WERR_BADFID
;
6557 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6558 result
= WERR_BADFID
;
6562 result
= winreg_printer_binding_handle(tmp_ctx
,
6563 get_session_info_system(),
6566 if (!W_ERROR_IS_OK(result
)) {
6570 result
= winreg_get_printer(tmp_ctx
, b
,
6571 lp_const_servicename(snum
),
6573 if (!W_ERROR_IS_OK(result
)) {
6574 result
= WERR_BADFID
;
6578 /* Do sanity check on the requested changes for Samba */
6579 if (!check_printer_ok(tmp_ctx
, printer
, snum
)) {
6580 result
= WERR_INVALID_PARAM
;
6584 /* FIXME!!! If the driver has changed we really should verify that
6585 it is installed before doing much else --jerry */
6587 /* Check calling user has permission to update printer description */
6588 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6589 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6590 result
= WERR_ACCESS_DENIED
;
6594 /* Call addprinter hook */
6595 /* Check changes to see if this is really needed */
6597 if (*lp_addprinter_cmd() &&
6598 (!strequal(printer
->drivername
, old_printer
->drivername
) ||
6599 !strequal(printer
->comment
, old_printer
->comment
) ||
6600 !strequal(printer
->portname
, old_printer
->portname
) ||
6601 !strequal(printer
->location
, old_printer
->location
)) )
6603 /* add_printer_hook() will call reload_services() */
6604 if (!add_printer_hook(tmp_ctx
, p
->session_info
->security_token
,
6605 printer
, p
->client_id
->addr
,
6607 result
= WERR_ACCESS_DENIED
;
6612 update_dsspooler(tmp_ctx
,
6613 get_session_info_system(),
6619 printer_mask
&= ~SPOOLSS_PRINTER_INFO_SECDESC
;
6621 if (devmode
== NULL
) {
6622 printer_mask
&= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
6624 result
= winreg_update_printer(tmp_ctx
, b
,
6632 talloc_free(tmp_ctx
);
6637 /****************************************************************************
6638 ****************************************************************************/
6639 static WERROR
publish_or_unpublish_printer(struct pipes_struct
*p
,
6640 struct policy_handle
*handle
,
6641 struct spoolss_SetPrinterInfo7
*info7
)
6644 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
6647 struct printer_handle
*Printer
;
6649 if ( lp_security() != SEC_ADS
) {
6650 return WERR_UNKNOWN_LEVEL
;
6653 Printer
= find_printer_index_by_hnd(p
, handle
);
6655 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6660 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6663 result
= winreg_get_printer_internal(p
->mem_ctx
,
6664 get_session_info_system(),
6666 lp_servicename(snum
),
6668 if (!W_ERROR_IS_OK(result
)) {
6672 nt_printer_publish(pinfo2
,
6673 get_session_info_system(),
6678 TALLOC_FREE(pinfo2
);
6681 return WERR_UNKNOWN_LEVEL
;
6685 /********************************************************************
6686 ********************************************************************/
6688 static WERROR
update_printer_devmode(struct pipes_struct
*p
,
6689 struct policy_handle
*handle
,
6690 struct spoolss_DeviceMode
*devmode
)
6693 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6694 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_DEVMODE
;
6696 DEBUG(8,("update_printer_devmode\n"));
6702 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6706 /* Check calling user has permission to update printer description */
6707 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6708 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6709 return WERR_ACCESS_DENIED
;
6712 return winreg_update_printer_internal(p
->mem_ctx
,
6713 get_session_info_system(),
6715 lp_const_servicename(snum
),
6723 /****************************************************************
6725 ****************************************************************/
6727 WERROR
_spoolss_SetPrinter(struct pipes_struct
*p
,
6728 struct spoolss_SetPrinter
*r
)
6732 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6735 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6736 OUR_HANDLE(r
->in
.handle
)));
6740 /* check the level */
6741 switch (r
->in
.info_ctr
->level
) {
6743 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
6745 result
= update_printer(p
, r
->in
.handle
,
6747 r
->in
.devmode_ctr
->devmode
);
6748 if (!W_ERROR_IS_OK(result
))
6750 if (r
->in
.secdesc_ctr
->sd
)
6751 result
= update_printer_sec(r
->in
.handle
, p
,
6755 return update_printer_sec(r
->in
.handle
, p
,
6758 return publish_or_unpublish_printer(p
, r
->in
.handle
,
6759 r
->in
.info_ctr
->info
.info7
);
6761 return update_printer_devmode(p
, r
->in
.handle
,
6762 r
->in
.devmode_ctr
->devmode
);
6764 return WERR_UNKNOWN_LEVEL
;
6768 /****************************************************************
6769 _spoolss_FindClosePrinterNotify
6770 ****************************************************************/
6772 WERROR
_spoolss_FindClosePrinterNotify(struct pipes_struct
*p
,
6773 struct spoolss_FindClosePrinterNotify
*r
)
6775 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6778 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6779 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
6783 if (Printer
->notify
.cli_chan
!= NULL
&&
6784 Printer
->notify
.cli_chan
->active_connections
> 0) {
6787 if (Printer
->printer_type
== SPLHND_PRINTER
) {
6788 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6793 srv_spoolss_replycloseprinter(snum
, Printer
);
6796 Printer
->notify
.flags
=0;
6797 Printer
->notify
.options
=0;
6798 Printer
->notify
.localmachine
[0]='\0';
6799 Printer
->notify
.printerlocal
=0;
6800 TALLOC_FREE(Printer
->notify
.option
);
6805 /****************************************************************
6807 ****************************************************************/
6809 WERROR
_spoolss_AddJob(struct pipes_struct
*p
,
6810 struct spoolss_AddJob
*r
)
6812 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6813 return WERR_INVALID_PARAM
;
6816 /* this is what a NT server returns for AddJob. AddJob must fail on
6817 * non-local printers */
6819 if (r
->in
.level
!= 1) {
6820 return WERR_UNKNOWN_LEVEL
;
6823 return WERR_INVALID_PARAM
;
6826 /****************************************************************************
6828 ****************************************************************************/
6830 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
6831 struct spoolss_JobInfo1
*r
,
6832 const print_queue_struct
*queue
,
6833 int position
, int snum
,
6834 struct spoolss_PrinterInfo2
*pinfo2
)
6838 t
= gmtime(&queue
->time
);
6840 r
->job_id
= queue
->sysjob
;
6842 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6843 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6844 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
6845 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6846 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6847 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6848 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6849 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6850 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6851 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6852 r
->text_status
= talloc_strdup(mem_ctx
, "");
6853 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6855 r
->status
= nt_printj_status(queue
->status
);
6856 r
->priority
= queue
->priority
;
6857 r
->position
= position
;
6858 r
->total_pages
= queue
->page_count
;
6859 r
->pages_printed
= 0; /* ??? */
6861 init_systemtime(&r
->submitted
, t
);
6866 /****************************************************************************
6868 ****************************************************************************/
6870 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6871 struct spoolss_JobInfo2
*r
,
6872 const print_queue_struct
*queue
,
6873 int position
, int snum
,
6874 struct spoolss_PrinterInfo2
*pinfo2
,
6875 struct spoolss_DeviceMode
*devmode
)
6879 t
= gmtime(&queue
->time
);
6881 r
->job_id
= queue
->sysjob
;
6883 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6884 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6885 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
6886 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6887 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6888 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6889 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6890 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6891 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6892 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6893 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6894 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6895 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6896 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6897 r
->parameters
= talloc_strdup(mem_ctx
, "");
6898 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6899 r
->driver_name
= talloc_strdup(mem_ctx
, pinfo2
->drivername
);
6900 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6902 r
->devmode
= devmode
;
6904 r
->text_status
= talloc_strdup(mem_ctx
, "");
6905 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6909 r
->status
= nt_printj_status(queue
->status
);
6910 r
->priority
= queue
->priority
;
6911 r
->position
= position
;
6914 r
->total_pages
= queue
->page_count
;
6915 r
->size
= queue
->size
;
6916 init_systemtime(&r
->submitted
, t
);
6918 r
->pages_printed
= 0; /* ??? */
6923 /****************************************************************************
6925 ****************************************************************************/
6927 static WERROR
fill_job_info3(TALLOC_CTX
*mem_ctx
,
6928 struct spoolss_JobInfo3
*r
,
6929 const print_queue_struct
*queue
,
6930 const print_queue_struct
*next_queue
,
6931 int position
, int snum
,
6932 struct spoolss_PrinterInfo2
*pinfo2
)
6934 r
->job_id
= queue
->sysjob
;
6937 r
->next_job_id
= next_queue
->sysjob
;
6944 /****************************************************************************
6945 Enumjobs at level 1.
6946 ****************************************************************************/
6948 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6949 const print_queue_struct
*queue
,
6950 uint32_t num_queues
, int snum
,
6951 struct spoolss_PrinterInfo2
*pinfo2
,
6952 union spoolss_JobInfo
**info_p
,
6955 union spoolss_JobInfo
*info
;
6957 WERROR result
= WERR_OK
;
6959 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6960 W_ERROR_HAVE_NO_MEMORY(info
);
6962 *count
= num_queues
;
6964 for (i
=0; i
<*count
; i
++) {
6965 result
= fill_job_info1(info
,
6971 if (!W_ERROR_IS_OK(result
)) {
6977 if (!W_ERROR_IS_OK(result
)) {
6988 /****************************************************************************
6989 Enumjobs at level 2.
6990 ****************************************************************************/
6992 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6993 const print_queue_struct
*queue
,
6994 uint32_t num_queues
, int snum
,
6995 struct spoolss_PrinterInfo2
*pinfo2
,
6996 union spoolss_JobInfo
**info_p
,
6999 union spoolss_JobInfo
*info
;
7001 WERROR result
= WERR_OK
;
7003 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7004 W_ERROR_HAVE_NO_MEMORY(info
);
7006 *count
= num_queues
;
7008 for (i
=0; i
<*count
; i
++) {
7009 struct spoolss_DeviceMode
*devmode
;
7011 result
= spoolss_create_default_devmode(info
,
7012 pinfo2
->printername
,
7014 if (!W_ERROR_IS_OK(result
)) {
7015 DEBUG(3, ("Can't proceed w/o a devmode!"));
7019 result
= fill_job_info2(info
,
7026 if (!W_ERROR_IS_OK(result
)) {
7032 if (!W_ERROR_IS_OK(result
)) {
7043 /****************************************************************************
7044 Enumjobs at level 3.
7045 ****************************************************************************/
7047 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
7048 const print_queue_struct
*queue
,
7049 uint32_t num_queues
, int snum
,
7050 struct spoolss_PrinterInfo2
*pinfo2
,
7051 union spoolss_JobInfo
**info_p
,
7054 union spoolss_JobInfo
*info
;
7056 WERROR result
= WERR_OK
;
7058 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7059 W_ERROR_HAVE_NO_MEMORY(info
);
7061 *count
= num_queues
;
7063 for (i
=0; i
<*count
; i
++) {
7064 const print_queue_struct
*next_queue
= NULL
;
7067 next_queue
= &queue
[i
+1];
7070 result
= fill_job_info3(info
,
7077 if (!W_ERROR_IS_OK(result
)) {
7083 if (!W_ERROR_IS_OK(result
)) {
7094 /****************************************************************
7096 ****************************************************************/
7098 WERROR
_spoolss_EnumJobs(struct pipes_struct
*p
,
7099 struct spoolss_EnumJobs
*r
)
7102 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
7104 print_status_struct prt_status
;
7105 print_queue_struct
*queue
= NULL
;
7108 /* that's an [in out] buffer */
7110 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7111 return WERR_INVALID_PARAM
;
7114 DEBUG(4,("_spoolss_EnumJobs\n"));
7118 *r
->out
.info
= NULL
;
7120 /* lookup the printer snum and tdb entry */
7122 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7126 result
= winreg_get_printer_internal(p
->mem_ctx
,
7127 get_session_info_system(),
7129 lp_const_servicename(snum
),
7131 if (!W_ERROR_IS_OK(result
)) {
7135 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
7136 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7137 count
, prt_status
.status
, prt_status
.message
));
7141 TALLOC_FREE(pinfo2
);
7145 switch (r
->in
.level
) {
7147 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
7148 pinfo2
, r
->out
.info
, r
->out
.count
);
7151 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
7152 pinfo2
, r
->out
.info
, r
->out
.count
);
7155 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
7156 pinfo2
, r
->out
.info
, r
->out
.count
);
7159 result
= WERR_UNKNOWN_LEVEL
;
7164 TALLOC_FREE(pinfo2
);
7166 if (!W_ERROR_IS_OK(result
)) {
7170 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7172 *r
->out
.info
, r
->in
.level
,
7174 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7175 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7177 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7180 /****************************************************************
7181 _spoolss_ScheduleJob
7182 ****************************************************************/
7184 WERROR
_spoolss_ScheduleJob(struct pipes_struct
*p
,
7185 struct spoolss_ScheduleJob
*r
)
7190 /****************************************************************
7191 ****************************************************************/
7193 static WERROR
spoolss_setjob_1(TALLOC_CTX
*mem_ctx
,
7194 struct messaging_context
*msg_ctx
,
7195 const char *printer_name
,
7197 struct spoolss_SetJobInfo1
*r
)
7201 if (!print_job_get_name(mem_ctx
, printer_name
, job_id
, &old_doc_name
)) {
7205 if (strequal(old_doc_name
, r
->document_name
)) {
7209 if (!print_job_set_name(server_event_context(), msg_ctx
,
7210 printer_name
, job_id
, r
->document_name
)) {
7217 /****************************************************************
7219 ****************************************************************/
7221 WERROR
_spoolss_SetJob(struct pipes_struct
*p
,
7222 struct spoolss_SetJob
*r
)
7224 const struct auth_serversupplied_info
*session_info
= p
->session_info
;
7226 WERROR errcode
= WERR_BADFUNC
;
7228 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7232 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
7233 return WERR_INVALID_PRINTER_NAME
;
7236 switch (r
->in
.command
) {
7237 case SPOOLSS_JOB_CONTROL_CANCEL
:
7238 case SPOOLSS_JOB_CONTROL_DELETE
:
7239 errcode
= print_job_delete(session_info
, p
->msg_ctx
,
7240 snum
, r
->in
.job_id
);
7241 if (W_ERROR_EQUAL(errcode
, WERR_PRINTER_HAS_JOBS_QUEUED
)) {
7245 case SPOOLSS_JOB_CONTROL_PAUSE
:
7246 errcode
= print_job_pause(session_info
, p
->msg_ctx
,
7247 snum
, r
->in
.job_id
);
7249 case SPOOLSS_JOB_CONTROL_RESTART
:
7250 case SPOOLSS_JOB_CONTROL_RESUME
:
7251 errcode
= print_job_resume(session_info
, p
->msg_ctx
,
7252 snum
, r
->in
.job_id
);
7258 return WERR_UNKNOWN_LEVEL
;
7261 if (!W_ERROR_IS_OK(errcode
)) {
7265 if (r
->in
.ctr
== NULL
) {
7269 switch (r
->in
.ctr
->level
) {
7271 errcode
= spoolss_setjob_1(p
->mem_ctx
, p
->msg_ctx
,
7272 lp_const_servicename(snum
),
7274 r
->in
.ctr
->info
.info1
);
7280 return WERR_UNKNOWN_LEVEL
;
7286 /****************************************************************************
7287 Enumerates all printer drivers by level and architecture.
7288 ****************************************************************************/
7290 static WERROR
enumprinterdrivers_level_by_architecture(TALLOC_CTX
*mem_ctx
,
7291 const struct auth_serversupplied_info
*session_info
,
7292 struct messaging_context
*msg_ctx
,
7293 const char *servername
,
7294 const char *architecture
,
7296 union spoolss_DriverInfo
**info_p
,
7301 struct spoolss_DriverInfo8
*driver
;
7302 union spoolss_DriverInfo
*info
= NULL
;
7304 WERROR result
= WERR_OK
;
7305 uint32_t num_drivers
;
7306 const char **drivers
;
7307 struct dcerpc_binding_handle
*b
;
7312 result
= winreg_printer_binding_handle(mem_ctx
,
7316 if (!W_ERROR_IS_OK(result
)) {
7320 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
7321 result
= winreg_get_driver_list(mem_ctx
, b
,
7322 architecture
, version
,
7323 &num_drivers
, &drivers
);
7324 if (!W_ERROR_IS_OK(result
)) {
7327 DEBUG(4, ("we have:[%d] drivers in environment"
7328 " [%s] and version [%d]\n",
7329 num_drivers
, architecture
, version
));
7331 if (num_drivers
!= 0) {
7332 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
7333 union spoolss_DriverInfo
,
7334 count
+ num_drivers
);
7336 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7337 "failed to enlarge driver info buffer!\n"));
7338 result
= WERR_NOMEM
;
7343 for (i
= 0; i
< num_drivers
; i
++) {
7344 DEBUG(5, ("\tdriver: [%s]\n", drivers
[i
]));
7346 result
= winreg_get_driver(mem_ctx
, b
,
7347 architecture
, drivers
[i
],
7349 if (!W_ERROR_IS_OK(result
)) {
7355 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
7356 driver
, servername
);
7359 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
7360 driver
, servername
);
7363 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
7364 driver
, servername
);
7367 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
7368 driver
, servername
);
7371 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
7372 driver
, servername
);
7375 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
7376 driver
, servername
);
7379 result
= fill_printer_driver_info8(info
, &info
[count
+i
].info8
,
7380 driver
, servername
);
7383 result
= WERR_UNKNOWN_LEVEL
;
7387 TALLOC_FREE(driver
);
7389 if (!W_ERROR_IS_OK(result
)) {
7394 count
+= num_drivers
;
7395 TALLOC_FREE(drivers
);
7399 TALLOC_FREE(drivers
);
7401 if (!W_ERROR_IS_OK(result
)) {
7412 /****************************************************************************
7413 Enumerates all printer drivers by level.
7414 ****************************************************************************/
7416 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
7417 const struct auth_serversupplied_info
*session_info
,
7418 struct messaging_context
*msg_ctx
,
7419 const char *servername
,
7420 const char *architecture
,
7422 union spoolss_DriverInfo
**info_p
,
7426 WERROR result
= WERR_OK
;
7428 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_ALL
)) {
7430 for (a
=0; archi_table
[a
].long_archi
!= NULL
; a
++) {
7432 union spoolss_DriverInfo
*info
= NULL
;
7435 result
= enumprinterdrivers_level_by_architecture(mem_ctx
,
7439 archi_table
[a
].long_archi
,
7443 if (!W_ERROR_IS_OK(result
)) {
7447 for (i
=0; i
< count
; i
++) {
7448 ADD_TO_ARRAY(mem_ctx
, union spoolss_DriverInfo
,
7449 info
[i
], info_p
, count_p
);
7456 return enumprinterdrivers_level_by_architecture(mem_ctx
,
7466 /****************************************************************
7467 _spoolss_EnumPrinterDrivers
7468 ****************************************************************/
7470 WERROR
_spoolss_EnumPrinterDrivers(struct pipes_struct
*p
,
7471 struct spoolss_EnumPrinterDrivers
*r
)
7473 const char *cservername
;
7476 /* that's an [in out] buffer */
7478 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7479 return WERR_INVALID_PARAM
;
7482 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7486 *r
->out
.info
= NULL
;
7488 cservername
= canon_servername(r
->in
.server
);
7490 if (!is_myname_or_ipaddr(cservername
)) {
7491 return WERR_UNKNOWN_PRINTER_DRIVER
;
7494 result
= enumprinterdrivers_level(p
->mem_ctx
,
7495 get_session_info_system(),
7502 if (!W_ERROR_IS_OK(result
)) {
7506 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7507 spoolss_EnumPrinterDrivers
,
7508 *r
->out
.info
, r
->in
.level
,
7510 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7511 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7513 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7516 /****************************************************************
7518 ****************************************************************/
7520 WERROR
_spoolss_EnumForms(struct pipes_struct
*p
,
7521 struct spoolss_EnumForms
*r
)
7527 *r
->out
.info
= NULL
;
7529 /* that's an [in out] buffer */
7531 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
7532 return WERR_INVALID_PARAM
;
7535 DEBUG(4,("_spoolss_EnumForms\n"));
7536 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7537 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7539 switch (r
->in
.level
) {
7541 result
= winreg_printer_enumforms1_internal(p
->mem_ctx
,
7542 get_session_info_system(),
7548 result
= WERR_UNKNOWN_LEVEL
;
7552 if (!W_ERROR_IS_OK(result
)) {
7556 if (*r
->out
.count
== 0) {
7557 return WERR_NO_MORE_ITEMS
;
7560 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7562 *r
->out
.info
, r
->in
.level
,
7564 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7565 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7567 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7570 /****************************************************************
7572 ****************************************************************/
7574 WERROR
_spoolss_GetForm(struct pipes_struct
*p
,
7575 struct spoolss_GetForm
*r
)
7579 /* that's an [in out] buffer */
7581 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7582 return WERR_INVALID_PARAM
;
7585 DEBUG(4,("_spoolss_GetForm\n"));
7586 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7587 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7589 switch (r
->in
.level
) {
7591 result
= winreg_printer_getform1_internal(p
->mem_ctx
,
7592 get_session_info_system(),
7595 &r
->out
.info
->info1
);
7598 result
= WERR_UNKNOWN_LEVEL
;
7602 if (!W_ERROR_IS_OK(result
)) {
7603 TALLOC_FREE(r
->out
.info
);
7607 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
,
7608 r
->out
.info
, r
->in
.level
);
7609 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7611 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7614 /****************************************************************************
7615 ****************************************************************************/
7617 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
7618 struct spoolss_PortInfo1
*r
,
7621 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7622 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7627 /****************************************************************************
7628 TODO: This probably needs distinguish between TCP/IP and Local ports
7630 ****************************************************************************/
7632 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
7633 struct spoolss_PortInfo2
*r
,
7636 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7637 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7639 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
7640 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
7642 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
7643 W_ERROR_HAVE_NO_MEMORY(r
->description
);
7645 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
7652 /****************************************************************************
7653 wrapper around the enumer ports command
7654 ****************************************************************************/
7656 static WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
7658 char *cmd
= lp_enumports_cmd();
7659 char **qlines
= NULL
;
7660 char *command
= NULL
;
7668 /* if no hook then just fill in the default port */
7671 if (!(qlines
= TALLOC_ARRAY( NULL
, char*, 2 ))) {
7674 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
7675 TALLOC_FREE(qlines
);
7682 /* we have a valid enumport command */
7684 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
7689 DEBUG(10,("Running [%s]\n", command
));
7690 ret
= smbrun(command
, &fd
);
7691 DEBUG(10,("Returned [%d]\n", ret
));
7692 TALLOC_FREE(command
);
7697 return WERR_ACCESS_DENIED
;
7701 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
7702 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7712 /****************************************************************************
7714 ****************************************************************************/
7716 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
7717 union spoolss_PortInfo
**info_p
,
7720 union spoolss_PortInfo
*info
= NULL
;
7722 WERROR result
= WERR_OK
;
7723 char **qlines
= NULL
;
7726 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7727 if (!W_ERROR_IS_OK(result
)) {
7732 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7734 DEBUG(10,("Returning WERR_NOMEM\n"));
7735 result
= WERR_NOMEM
;
7739 for (i
=0; i
<numlines
; i
++) {
7740 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7741 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7742 if (!W_ERROR_IS_OK(result
)) {
7747 TALLOC_FREE(qlines
);
7750 if (!W_ERROR_IS_OK(result
)) {
7752 TALLOC_FREE(qlines
);
7764 /****************************************************************************
7766 ****************************************************************************/
7768 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7769 union spoolss_PortInfo
**info_p
,
7772 union spoolss_PortInfo
*info
= NULL
;
7774 WERROR result
= WERR_OK
;
7775 char **qlines
= NULL
;
7778 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7779 if (!W_ERROR_IS_OK(result
)) {
7784 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7786 DEBUG(10,("Returning WERR_NOMEM\n"));
7787 result
= WERR_NOMEM
;
7791 for (i
=0; i
<numlines
; i
++) {
7792 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7793 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7794 if (!W_ERROR_IS_OK(result
)) {
7799 TALLOC_FREE(qlines
);
7802 if (!W_ERROR_IS_OK(result
)) {
7804 TALLOC_FREE(qlines
);
7816 /****************************************************************
7818 ****************************************************************/
7820 WERROR
_spoolss_EnumPorts(struct pipes_struct
*p
,
7821 struct spoolss_EnumPorts
*r
)
7825 /* that's an [in out] buffer */
7827 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7828 return WERR_INVALID_PARAM
;
7831 DEBUG(4,("_spoolss_EnumPorts\n"));
7835 *r
->out
.info
= NULL
;
7837 switch (r
->in
.level
) {
7839 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7843 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7847 return WERR_UNKNOWN_LEVEL
;
7850 if (!W_ERROR_IS_OK(result
)) {
7854 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7856 *r
->out
.info
, r
->in
.level
,
7858 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7859 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7861 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7864 /****************************************************************************
7865 ****************************************************************************/
7867 static WERROR
spoolss_addprinterex_level_2(struct pipes_struct
*p
,
7869 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7870 struct spoolss_DeviceMode
*devmode
,
7871 struct security_descriptor
*secdesc
,
7872 struct spoolss_UserLevelCtr
*user_ctr
,
7873 struct policy_handle
*handle
)
7875 struct spoolss_SetPrinterInfo2
*info2
= info_ctr
->info
.info2
;
7876 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_ALL
;
7878 WERROR err
= WERR_OK
;
7880 /* samba does not have a concept of local, non-shared printers yet, so
7881 * make sure we always setup sharename - gd */
7882 if ((info2
->sharename
== NULL
|| info2
->sharename
[0] == '\0') &&
7883 (info2
->printername
!= NULL
&& info2
->printername
[0] != '\0')) {
7884 DEBUG(5, ("spoolss_addprinterex_level_2: "
7885 "no sharename has been set, setting printername %s as sharename\n",
7886 info2
->printername
));
7887 info2
->sharename
= info2
->printername
;
7890 /* check to see if the printer already exists */
7891 if ((snum
= print_queue_snum(info2
->sharename
)) != -1) {
7892 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7894 return WERR_PRINTER_ALREADY_EXISTS
;
7897 if (!lp_force_printername(GLOBAL_SECTION_SNUM
)) {
7898 if ((snum
= print_queue_snum(info2
->printername
)) != -1) {
7899 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7900 info2
->printername
));
7901 return WERR_PRINTER_ALREADY_EXISTS
;
7905 /* validate printer info struct */
7906 if (!info2
->printername
|| strlen(info2
->printername
) == 0) {
7907 return WERR_INVALID_PRINTER_NAME
;
7909 if (!info2
->portname
|| strlen(info2
->portname
) == 0) {
7910 return WERR_UNKNOWN_PORT
;
7912 if (!info2
->drivername
|| strlen(info2
->drivername
) == 0) {
7913 return WERR_UNKNOWN_PRINTER_DRIVER
;
7915 if (!info2
->printprocessor
|| strlen(info2
->printprocessor
) == 0) {
7916 return WERR_UNKNOWN_PRINTPROCESSOR
;
7919 /* FIXME!!! smbd should check to see if the driver is installed before
7920 trying to add a printer like this --jerry */
7922 if (*lp_addprinter_cmd() ) {
7923 if ( !add_printer_hook(p
->mem_ctx
, p
->session_info
->security_token
,
7924 info2
, p
->client_id
->addr
,
7926 return WERR_ACCESS_DENIED
;
7929 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7930 "smb.conf parameter \"addprinter command\" is defined. This "
7931 "parameter must exist for this call to succeed\n",
7932 info2
->sharename
));
7935 if ((snum
= print_queue_snum(info2
->sharename
)) == -1) {
7936 return WERR_ACCESS_DENIED
;
7939 /* you must be a printer admin to add a new printer */
7940 if (!print_access_check(p
->session_info
,
7943 PRINTER_ACCESS_ADMINISTER
)) {
7944 return WERR_ACCESS_DENIED
;
7948 * Do sanity check on the requested changes for Samba.
7951 if (!check_printer_ok(p
->mem_ctx
, info2
, snum
)) {
7952 return WERR_INVALID_PARAM
;
7955 if (devmode
== NULL
) {
7956 info2_mask
= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
7959 update_dsspooler(p
->mem_ctx
,
7960 get_session_info_system(),
7966 err
= winreg_update_printer_internal(p
->mem_ctx
,
7967 get_session_info_system(),
7974 if (!W_ERROR_IS_OK(err
)) {
7978 err
= open_printer_hnd(p
, handle
, info2
->printername
, PRINTER_ACCESS_ADMINISTER
);
7979 if (!W_ERROR_IS_OK(err
)) {
7980 /* Handle open failed - remove addition. */
7981 ZERO_STRUCTP(handle
);
7988 /****************************************************************
7989 _spoolss_AddPrinterEx
7990 ****************************************************************/
7992 WERROR
_spoolss_AddPrinterEx(struct pipes_struct
*p
,
7993 struct spoolss_AddPrinterEx
*r
)
7995 switch (r
->in
.info_ctr
->level
) {
7997 /* we don't handle yet */
7998 /* but I know what to do ... */
7999 return WERR_UNKNOWN_LEVEL
;
8001 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
8003 r
->in
.devmode_ctr
->devmode
,
8004 r
->in
.secdesc_ctr
->sd
,
8005 r
->in
.userlevel_ctr
,
8008 return WERR_UNKNOWN_LEVEL
;
8012 /****************************************************************
8014 ****************************************************************/
8016 WERROR
_spoolss_AddPrinter(struct pipes_struct
*p
,
8017 struct spoolss_AddPrinter
*r
)
8019 struct spoolss_AddPrinterEx a
;
8020 struct spoolss_UserLevelCtr userlevel_ctr
;
8022 ZERO_STRUCT(userlevel_ctr
);
8024 userlevel_ctr
.level
= 1;
8026 a
.in
.server
= r
->in
.server
;
8027 a
.in
.info_ctr
= r
->in
.info_ctr
;
8028 a
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
8029 a
.in
.secdesc_ctr
= r
->in
.secdesc_ctr
;
8030 a
.in
.userlevel_ctr
= &userlevel_ctr
;
8031 a
.out
.handle
= r
->out
.handle
;
8033 return _spoolss_AddPrinterEx(p
, &a
);
8036 /****************************************************************
8037 _spoolss_AddPrinterDriverEx
8038 ****************************************************************/
8040 WERROR
_spoolss_AddPrinterDriverEx(struct pipes_struct
*p
,
8041 struct spoolss_AddPrinterDriverEx
*r
)
8043 WERROR err
= WERR_OK
;
8044 const char *driver_name
= NULL
;
8049 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
8050 fn
= "_spoolss_AddPrinterDriver";
8052 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
8053 fn
= "_spoolss_AddPrinterDriverEx";
8056 return WERR_INVALID_PARAM
;
8060 * we only support the semantics of AddPrinterDriver()
8061 * i.e. only copy files that are newer than existing ones
8064 if (r
->in
.flags
== 0) {
8065 return WERR_INVALID_PARAM
;
8068 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
8069 return WERR_ACCESS_DENIED
;
8073 if (r
->in
.info_ctr
->level
!= 3 && r
->in
.info_ctr
->level
!= 6) {
8074 /* Clever hack from Martin Zielinski <mz@seh.de>
8075 * to allow downgrade from level 8 (Vista).
8077 DEBUG(0,("%s: level %d not yet implemented\n", fn
,
8078 r
->in
.info_ctr
->level
));
8079 return WERR_UNKNOWN_LEVEL
;
8082 DEBUG(5,("Cleaning driver's information\n"));
8083 err
= clean_up_driver_struct(p
->mem_ctx
, p
->session_info
, r
->in
.info_ctr
);
8084 if (!W_ERROR_IS_OK(err
))
8087 DEBUG(5,("Moving driver to final destination\n"));
8088 err
= move_driver_to_download_area(p
->session_info
, r
->in
.info_ctr
);
8089 if (!W_ERROR_IS_OK(err
)) {
8093 err
= winreg_add_driver_internal(p
->mem_ctx
,
8094 get_session_info_system(),
8099 if (!W_ERROR_IS_OK(err
)) {
8104 * I think this is where he DrvUpgradePrinter() hook would be
8105 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8106 * server. Right now, we just need to send ourselves a message
8107 * to update each printer bound to this driver. --jerry
8110 if (!srv_spoolss_drv_upgrade_printer(driver_name
, p
->msg_ctx
)) {
8111 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8119 /****************************************************************
8120 _spoolss_AddPrinterDriver
8121 ****************************************************************/
8123 WERROR
_spoolss_AddPrinterDriver(struct pipes_struct
*p
,
8124 struct spoolss_AddPrinterDriver
*r
)
8126 struct spoolss_AddPrinterDriverEx a
;
8128 switch (r
->in
.info_ctr
->level
) {
8135 return WERR_UNKNOWN_LEVEL
;
8138 a
.in
.servername
= r
->in
.servername
;
8139 a
.in
.info_ctr
= r
->in
.info_ctr
;
8140 a
.in
.flags
= APD_COPY_NEW_FILES
;
8142 return _spoolss_AddPrinterDriverEx(p
, &a
);
8145 /****************************************************************************
8146 ****************************************************************************/
8148 struct _spoolss_paths
{
8154 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
8156 static const struct _spoolss_paths spoolss_paths
[]= {
8157 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
8158 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
8161 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
8162 const char *servername
,
8163 const char *environment
,
8167 const char *pservername
= NULL
;
8168 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
8169 const char *short_archi
;
8173 /* environment may be empty */
8174 if (environment
&& strlen(environment
)) {
8175 long_archi
= environment
;
8178 /* servername may be empty */
8179 if (servername
&& strlen(servername
)) {
8180 pservername
= canon_servername(servername
);
8182 if (!is_myname_or_ipaddr(pservername
)) {
8183 return WERR_INVALID_PARAM
;
8187 if (!(short_archi
= get_short_archi(long_archi
))) {
8188 return WERR_INVALID_ENVIRONMENT
;
8191 switch (component
) {
8192 case SPOOLSS_PRTPROCS_PATH
:
8193 case SPOOLSS_DRIVER_PATH
:
8195 *path
= talloc_asprintf(mem_ctx
,
8198 spoolss_paths
[component
].share
,
8201 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
8202 SPOOLSS_DEFAULT_SERVER_PATH
,
8203 spoolss_paths
[component
].dir
,
8208 return WERR_INVALID_PARAM
;
8218 /****************************************************************************
8219 ****************************************************************************/
8221 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
8222 const char *servername
,
8223 const char *environment
,
8224 struct spoolss_DriverDirectoryInfo1
*r
)
8229 werr
= compose_spoolss_server_path(mem_ctx
,
8232 SPOOLSS_DRIVER_PATH
,
8234 if (!W_ERROR_IS_OK(werr
)) {
8238 DEBUG(4,("printer driver directory: [%s]\n", path
));
8240 r
->directory_name
= path
;
8245 /****************************************************************
8246 _spoolss_GetPrinterDriverDirectory
8247 ****************************************************************/
8249 WERROR
_spoolss_GetPrinterDriverDirectory(struct pipes_struct
*p
,
8250 struct spoolss_GetPrinterDriverDirectory
*r
)
8254 /* that's an [in out] buffer */
8256 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8257 return WERR_INVALID_PARAM
;
8260 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8265 /* r->in.level is ignored */
8267 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
8270 &r
->out
.info
->info1
);
8271 if (!W_ERROR_IS_OK(werror
)) {
8272 TALLOC_FREE(r
->out
.info
);
8276 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
,
8277 r
->out
.info
, r
->in
.level
);
8278 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8280 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8283 /****************************************************************
8284 _spoolss_EnumPrinterData
8285 ****************************************************************/
8287 WERROR
_spoolss_EnumPrinterData(struct pipes_struct
*p
,
8288 struct spoolss_EnumPrinterData
*r
)
8291 struct spoolss_EnumPrinterDataEx r2
;
8293 struct spoolss_PrinterEnumValues
*info
, *val
= NULL
;
8296 r2
.in
.handle
= r
->in
.handle
;
8297 r2
.in
.key_name
= "PrinterDriverData";
8299 r2
.out
.count
= &count
;
8300 r2
.out
.info
= &info
;
8301 r2
.out
.needed
= &needed
;
8303 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
8304 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
8305 r2
.in
.offered
= needed
;
8306 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
8308 if (!W_ERROR_IS_OK(result
)) {
8313 * The NT machine wants to know the biggest size of value and data
8315 * cf: MSDN EnumPrinterData remark section
8318 if (!r
->in
.value_offered
&& !r
->in
.data_offered
) {
8319 uint32_t biggest_valuesize
= 0;
8320 uint32_t biggest_datasize
= 0;
8323 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8325 for (i
=0; i
<count
; i
++) {
8327 name_length
= strlen(info
[i
].value_name
);
8328 if (strlen(info
[i
].value_name
) > biggest_valuesize
) {
8329 biggest_valuesize
= name_length
;
8332 if (info
[i
].data_length
> biggest_datasize
) {
8333 biggest_datasize
= info
[i
].data_length
;
8336 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
8340 /* the value is an UNICODE string but real_value_size is the length
8341 in bytes including the trailing 0 */
8343 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
8344 *r
->out
.data_needed
= biggest_datasize
;
8346 DEBUG(6,("final values: [%d], [%d]\n",
8347 *r
->out
.value_needed
, *r
->out
.data_needed
));
8352 if (r
->in
.enum_index
< count
) {
8353 val
= &info
[r
->in
.enum_index
];
8357 /* out_value should default to "" or else NT4 has
8358 problems unmarshalling the response */
8360 if (r
->in
.value_offered
) {
8361 *r
->out
.value_needed
= 1;
8362 r
->out
.value_name
= talloc_strdup(r
, "");
8363 if (!r
->out
.value_name
) {
8367 r
->out
.value_name
= NULL
;
8368 *r
->out
.value_needed
= 0;
8371 /* the data is counted in bytes */
8373 *r
->out
.data_needed
= r
->in
.data_offered
;
8375 result
= WERR_NO_MORE_ITEMS
;
8379 * - counted in bytes in the request
8380 * - counted in UNICODE chars in the max reply
8381 * - counted in bytes in the real size
8383 * take a pause *before* coding not *during* coding
8387 if (r
->in
.value_offered
) {
8388 r
->out
.value_name
= talloc_strdup(r
, val
->value_name
);
8389 if (!r
->out
.value_name
) {
8392 *r
->out
.value_needed
= val
->value_name_len
;
8394 r
->out
.value_name
= NULL
;
8395 *r
->out
.value_needed
= 0;
8400 *r
->out
.type
= val
->type
;
8402 /* data - counted in bytes */
8405 * See the section "Dynamically Typed Query Parameters"
8409 if (r
->out
.data
&& val
->data
&& val
->data
->data
&&
8410 val
->data_length
&& r
->in
.data_offered
) {
8411 memcpy(r
->out
.data
, val
->data
->data
,
8412 MIN(val
->data_length
,r
->in
.data_offered
));
8415 *r
->out
.data_needed
= val
->data_length
;
8423 /****************************************************************
8424 _spoolss_SetPrinterData
8425 ****************************************************************/
8427 WERROR
_spoolss_SetPrinterData(struct pipes_struct
*p
,
8428 struct spoolss_SetPrinterData
*r
)
8430 struct spoolss_SetPrinterDataEx r2
;
8432 r2
.in
.handle
= r
->in
.handle
;
8433 r2
.in
.key_name
= "PrinterDriverData";
8434 r2
.in
.value_name
= r
->in
.value_name
;
8435 r2
.in
.type
= r
->in
.type
;
8436 r2
.in
.data
= r
->in
.data
;
8437 r2
.in
.offered
= r
->in
.offered
;
8439 return _spoolss_SetPrinterDataEx(p
, &r2
);
8442 /****************************************************************
8443 _spoolss_ResetPrinter
8444 ****************************************************************/
8446 WERROR
_spoolss_ResetPrinter(struct pipes_struct
*p
,
8447 struct spoolss_ResetPrinter
*r
)
8449 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8452 DEBUG(5,("_spoolss_ResetPrinter\n"));
8455 * All we do is to check to see if the handle and queue is valid.
8456 * This call really doesn't mean anything to us because we only
8457 * support RAW printing. --jerry
8461 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8462 OUR_HANDLE(r
->in
.handle
)));
8466 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8470 /* blindly return success */
8474 /****************************************************************
8475 _spoolss_DeletePrinterData
8476 ****************************************************************/
8478 WERROR
_spoolss_DeletePrinterData(struct pipes_struct
*p
,
8479 struct spoolss_DeletePrinterData
*r
)
8481 struct spoolss_DeletePrinterDataEx r2
;
8483 r2
.in
.handle
= r
->in
.handle
;
8484 r2
.in
.key_name
= "PrinterDriverData";
8485 r2
.in
.value_name
= r
->in
.value_name
;
8487 return _spoolss_DeletePrinterDataEx(p
, &r2
);
8490 /****************************************************************
8492 ****************************************************************/
8494 WERROR
_spoolss_AddForm(struct pipes_struct
*p
,
8495 struct spoolss_AddForm
*r
)
8497 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8499 WERROR status
= WERR_OK
;
8500 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8501 struct dcerpc_binding_handle
*b
;
8503 DEBUG(5,("_spoolss_AddForm\n"));
8506 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8507 OUR_HANDLE(r
->in
.handle
)));
8511 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8512 and not a printer admin, then fail */
8514 if ((p
->session_info
->utok
.uid
!= sec_initial_uid()) &&
8515 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
8516 !token_contains_name_in_list(uidtoname(p
->session_info
->utok
.uid
),
8517 p
->session_info
->info3
->base
.domain
.string
,
8519 p
->session_info
->security_token
,
8520 lp_printer_admin(snum
))) {
8521 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8522 return WERR_ACCESS_DENIED
;
8525 switch (form
->flags
) {
8526 case SPOOLSS_FORM_USER
:
8527 case SPOOLSS_FORM_BUILTIN
:
8528 case SPOOLSS_FORM_PRINTER
:
8531 return WERR_INVALID_PARAM
;
8534 status
= winreg_printer_binding_handle(p
->mem_ctx
,
8535 get_session_info_system(),
8538 if (!W_ERROR_IS_OK(status
)) {
8542 status
= winreg_printer_addform1(p
->mem_ctx
, b
,
8544 if (!W_ERROR_IS_OK(status
)) {
8549 * ChangeID must always be set if this is a printer
8551 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8552 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8556 status
= winreg_printer_update_changeid(p
->mem_ctx
, b
,
8557 lp_const_servicename(snum
));
8558 if (!W_ERROR_IS_OK(status
)) {
8566 /****************************************************************
8568 ****************************************************************/
8570 WERROR
_spoolss_DeleteForm(struct pipes_struct
*p
,
8571 struct spoolss_DeleteForm
*r
)
8573 const char *form_name
= r
->in
.form_name
;
8574 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8576 WERROR status
= WERR_OK
;
8577 struct dcerpc_binding_handle
*b
;
8579 DEBUG(5,("_spoolss_DeleteForm\n"));
8582 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8583 OUR_HANDLE(r
->in
.handle
)));
8587 if ((p
->session_info
->utok
.uid
!= sec_initial_uid()) &&
8588 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
8589 !token_contains_name_in_list(uidtoname(p
->session_info
->utok
.uid
),
8590 p
->session_info
->info3
->base
.domain
.string
,
8592 p
->session_info
->security_token
,
8593 lp_printer_admin(snum
))) {
8594 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8595 return WERR_ACCESS_DENIED
;
8598 status
= winreg_printer_binding_handle(p
->mem_ctx
,
8599 get_session_info_system(),
8602 if (!W_ERROR_IS_OK(status
)) {
8606 status
= winreg_printer_deleteform1(p
->mem_ctx
, b
,
8608 if (!W_ERROR_IS_OK(status
)) {
8613 * ChangeID must always be set if this is a printer
8615 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8616 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8620 status
= winreg_printer_update_changeid(p
->mem_ctx
, b
,
8621 lp_const_servicename(snum
));
8622 if (!W_ERROR_IS_OK(status
)) {
8630 /****************************************************************
8632 ****************************************************************/
8634 WERROR
_spoolss_SetForm(struct pipes_struct
*p
,
8635 struct spoolss_SetForm
*r
)
8637 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8638 const char *form_name
= r
->in
.form_name
;
8640 WERROR status
= WERR_OK
;
8641 struct dcerpc_binding_handle
*b
;
8643 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8645 DEBUG(5,("_spoolss_SetForm\n"));
8648 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8649 OUR_HANDLE(r
->in
.handle
)));
8653 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8654 and not a printer admin, then fail */
8656 if ((p
->session_info
->utok
.uid
!= sec_initial_uid()) &&
8657 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
8658 !token_contains_name_in_list(uidtoname(p
->session_info
->utok
.uid
),
8659 p
->session_info
->info3
->base
.domain
.string
,
8661 p
->session_info
->security_token
,
8662 lp_printer_admin(snum
))) {
8663 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8664 return WERR_ACCESS_DENIED
;
8667 status
= winreg_printer_binding_handle(p
->mem_ctx
,
8668 get_session_info_system(),
8671 if (!W_ERROR_IS_OK(status
)) {
8675 status
= winreg_printer_setform1(p
->mem_ctx
, b
,
8678 if (!W_ERROR_IS_OK(status
)) {
8683 * ChangeID must always be set if this is a printer
8685 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8686 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8690 status
= winreg_printer_update_changeid(p
->mem_ctx
, b
,
8691 lp_const_servicename(snum
));
8692 if (!W_ERROR_IS_OK(status
)) {
8700 /****************************************************************************
8701 fill_print_processor1
8702 ****************************************************************************/
8704 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8705 struct spoolss_PrintProcessorInfo1
*r
,
8706 const char *print_processor_name
)
8708 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8709 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8714 /****************************************************************************
8715 enumprintprocessors level 1.
8716 ****************************************************************************/
8718 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8719 union spoolss_PrintProcessorInfo
**info_p
,
8722 union spoolss_PrintProcessorInfo
*info
;
8725 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8726 W_ERROR_HAVE_NO_MEMORY(info
);
8730 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8731 if (!W_ERROR_IS_OK(result
)) {
8736 if (!W_ERROR_IS_OK(result
)) {
8747 /****************************************************************
8748 _spoolss_EnumPrintProcessors
8749 ****************************************************************/
8751 WERROR
_spoolss_EnumPrintProcessors(struct pipes_struct
*p
,
8752 struct spoolss_EnumPrintProcessors
*r
)
8756 /* that's an [in out] buffer */
8758 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8759 return WERR_INVALID_PARAM
;
8762 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8765 * Enumerate the print processors ...
8767 * Just reply with "winprint", to keep NT happy
8768 * and I can use my nice printer checker.
8773 *r
->out
.info
= NULL
;
8775 if (!get_short_archi(r
->in
.environment
)) {
8776 return WERR_INVALID_ENVIRONMENT
;
8779 switch (r
->in
.level
) {
8781 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8785 return WERR_UNKNOWN_LEVEL
;
8788 if (!W_ERROR_IS_OK(result
)) {
8792 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8793 spoolss_EnumPrintProcessors
,
8794 *r
->out
.info
, r
->in
.level
,
8796 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8797 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8799 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8802 /****************************************************************************
8803 fill_printprocdatatype1
8804 ****************************************************************************/
8806 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8807 struct spoolss_PrintProcDataTypesInfo1
*r
,
8808 const char *name_array
)
8810 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8811 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8816 /****************************************************************************
8817 enumprintprocdatatypes level 1.
8818 ****************************************************************************/
8820 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8821 union spoolss_PrintProcDataTypesInfo
**info_p
,
8825 union spoolss_PrintProcDataTypesInfo
*info
;
8827 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8828 W_ERROR_HAVE_NO_MEMORY(info
);
8832 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8833 if (!W_ERROR_IS_OK(result
)) {
8838 if (!W_ERROR_IS_OK(result
)) {
8849 /****************************************************************
8850 _spoolss_EnumPrintProcDataTypes
8851 ****************************************************************/
8853 WERROR
_spoolss_EnumPrintProcDataTypes(struct pipes_struct
*p
,
8854 struct spoolss_EnumPrintProcDataTypes
*r
)
8858 /* that's an [in out] buffer */
8860 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8861 return WERR_INVALID_PARAM
;
8864 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8868 *r
->out
.info
= NULL
;
8870 if (r
->in
.print_processor_name
== NULL
||
8871 !strequal(r
->in
.print_processor_name
, "winprint")) {
8872 return WERR_UNKNOWN_PRINTPROCESSOR
;
8875 switch (r
->in
.level
) {
8877 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8881 return WERR_UNKNOWN_LEVEL
;
8884 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8885 spoolss_EnumPrintProcDataTypes
,
8886 *r
->out
.info
, r
->in
.level
,
8888 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8889 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8891 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8894 /****************************************************************************
8896 ****************************************************************************/
8898 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8899 struct spoolss_MonitorInfo1
*r
,
8900 const char *monitor_name
)
8902 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8903 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8908 /****************************************************************************
8910 ****************************************************************************/
8912 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8913 struct spoolss_MonitorInfo2
*r
,
8914 const char *monitor_name
,
8915 const char *environment
,
8916 const char *dll_name
)
8918 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8919 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8920 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8921 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8922 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8923 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8928 /****************************************************************************
8929 enumprintmonitors level 1.
8930 ****************************************************************************/
8932 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8933 union spoolss_MonitorInfo
**info_p
,
8936 union spoolss_MonitorInfo
*info
;
8937 WERROR result
= WERR_OK
;
8939 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8940 W_ERROR_HAVE_NO_MEMORY(info
);
8944 result
= fill_monitor_1(info
, &info
[0].info1
,
8946 if (!W_ERROR_IS_OK(result
)) {
8950 result
= fill_monitor_1(info
, &info
[1].info1
,
8952 if (!W_ERROR_IS_OK(result
)) {
8957 if (!W_ERROR_IS_OK(result
)) {
8968 /****************************************************************************
8969 enumprintmonitors level 2.
8970 ****************************************************************************/
8972 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
8973 union spoolss_MonitorInfo
**info_p
,
8976 union spoolss_MonitorInfo
*info
;
8977 WERROR result
= WERR_OK
;
8979 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8980 W_ERROR_HAVE_NO_MEMORY(info
);
8984 result
= fill_monitor_2(info
, &info
[0].info2
,
8986 "Windows NT X86", /* FIXME */
8988 if (!W_ERROR_IS_OK(result
)) {
8992 result
= fill_monitor_2(info
, &info
[1].info2
,
8994 "Windows NT X86", /* FIXME */
8996 if (!W_ERROR_IS_OK(result
)) {
9001 if (!W_ERROR_IS_OK(result
)) {
9012 /****************************************************************
9013 _spoolss_EnumMonitors
9014 ****************************************************************/
9016 WERROR
_spoolss_EnumMonitors(struct pipes_struct
*p
,
9017 struct spoolss_EnumMonitors
*r
)
9021 /* that's an [in out] buffer */
9023 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9024 return WERR_INVALID_PARAM
;
9027 DEBUG(5,("_spoolss_EnumMonitors\n"));
9030 * Enumerate the print monitors ...
9032 * Just reply with "Local Port", to keep NT happy
9033 * and I can use my nice printer checker.
9038 *r
->out
.info
= NULL
;
9040 switch (r
->in
.level
) {
9042 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
9046 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
9050 return WERR_UNKNOWN_LEVEL
;
9053 if (!W_ERROR_IS_OK(result
)) {
9057 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
9058 spoolss_EnumMonitors
,
9059 *r
->out
.info
, r
->in
.level
,
9061 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9062 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
9064 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9067 /****************************************************************************
9068 ****************************************************************************/
9070 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
9071 const print_queue_struct
*queue
,
9072 int count
, int snum
,
9073 struct spoolss_PrinterInfo2
*pinfo2
,
9075 struct spoolss_JobInfo1
*r
)
9080 for (i
=0; i
<count
; i
++) {
9081 if (queue
[i
].sysjob
== (int)jobid
) {
9087 if (found
== false) {
9088 /* NT treats not found as bad param... yet another bad choice */
9089 return WERR_INVALID_PARAM
;
9092 return fill_job_info1(mem_ctx
,
9100 /****************************************************************************
9101 ****************************************************************************/
9103 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
9104 const print_queue_struct
*queue
,
9105 int count
, int snum
,
9106 struct spoolss_PrinterInfo2
*pinfo2
,
9108 struct spoolss_JobInfo2
*r
)
9112 struct spoolss_DeviceMode
*devmode
;
9115 for (i
=0; i
<count
; i
++) {
9116 if (queue
[i
].sysjob
== (int)jobid
) {
9122 if (found
== false) {
9123 /* NT treats not found as bad param... yet another bad
9125 return WERR_INVALID_PARAM
;
9129 * if the print job does not have a DEVMODE associated with it,
9130 * just use the one for the printer. A NULL devicemode is not
9131 * a failure condition
9134 devmode
= print_job_devmode(mem_ctx
, lp_const_servicename(snum
), jobid
);
9136 result
= spoolss_create_default_devmode(mem_ctx
,
9137 pinfo2
->printername
,
9139 if (!W_ERROR_IS_OK(result
)) {
9140 DEBUG(3, ("Can't proceed w/o a devmode!"));
9145 return fill_job_info2(mem_ctx
,
9154 /****************************************************************
9156 ****************************************************************/
9158 WERROR
_spoolss_GetJob(struct pipes_struct
*p
,
9159 struct spoolss_GetJob
*r
)
9161 WERROR result
= WERR_OK
;
9162 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
9165 print_queue_struct
*queue
= NULL
;
9166 print_status_struct prt_status
;
9168 /* that's an [in out] buffer */
9170 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9171 return WERR_INVALID_PARAM
;
9174 DEBUG(5,("_spoolss_GetJob\n"));
9178 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9182 result
= winreg_get_printer_internal(p
->mem_ctx
,
9183 get_session_info_system(),
9185 lp_const_servicename(snum
),
9187 if (!W_ERROR_IS_OK(result
)) {
9191 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
9193 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9194 count
, prt_status
.status
, prt_status
.message
));
9196 switch (r
->in
.level
) {
9198 result
= getjob_level_1(p
->mem_ctx
,
9199 queue
, count
, snum
, pinfo2
,
9200 r
->in
.job_id
, &r
->out
.info
->info1
);
9203 result
= getjob_level_2(p
->mem_ctx
,
9204 queue
, count
, snum
, pinfo2
,
9205 r
->in
.job_id
, &r
->out
.info
->info2
);
9208 result
= WERR_UNKNOWN_LEVEL
;
9213 TALLOC_FREE(pinfo2
);
9215 if (!W_ERROR_IS_OK(result
)) {
9216 TALLOC_FREE(r
->out
.info
);
9220 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, r
->out
.info
,
9222 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9224 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9227 /****************************************************************
9228 _spoolss_GetPrinterDataEx
9229 ****************************************************************/
9231 WERROR
_spoolss_GetPrinterDataEx(struct pipes_struct
*p
,
9232 struct spoolss_GetPrinterDataEx
*r
)
9235 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9236 const char *printer
;
9238 WERROR result
= WERR_OK
;
9240 enum winreg_Type val_type
= REG_NONE
;
9241 uint8_t *val_data
= NULL
;
9242 uint32_t val_size
= 0;
9243 struct dcerpc_binding_handle
*b
;
9245 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9247 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9248 r
->in
.key_name
, r
->in
.value_name
));
9250 /* in case of problem, return some default values */
9253 *r
->out
.type
= REG_NONE
;
9256 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9257 OUR_HANDLE(r
->in
.handle
)));
9258 result
= WERR_BADFID
;
9262 /* Is the handle to a printer or to the server? */
9264 if (Printer
->printer_type
== SPLHND_SERVER
) {
9266 union spoolss_PrinterData data
;
9268 result
= getprinterdata_printer_server(p
->mem_ctx
,
9272 if (!W_ERROR_IS_OK(result
)) {
9276 result
= push_spoolss_PrinterData(p
->mem_ctx
, &blob
,
9277 *r
->out
.type
, &data
);
9278 if (!W_ERROR_IS_OK(result
)) {
9282 *r
->out
.needed
= blob
.length
;
9284 if (r
->in
.offered
>= *r
->out
.needed
) {
9285 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
9288 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9291 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9294 printer
= lp_const_servicename(snum
);
9296 /* check to see if the keyname is valid */
9297 if (!strlen(r
->in
.key_name
)) {
9298 return WERR_INVALID_PARAM
;
9301 result
= winreg_printer_binding_handle(p
->mem_ctx
,
9302 get_session_info_system(),
9305 if (!W_ERROR_IS_OK(result
)) {
9309 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9310 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
9311 strequal(r
->in
.value_name
, "ChangeId")) {
9312 *r
->out
.type
= REG_DWORD
;
9314 if (r
->in
.offered
>= *r
->out
.needed
) {
9315 uint32_t changeid
= 0;
9317 result
= winreg_printer_get_changeid(p
->mem_ctx
, b
,
9320 if (!W_ERROR_IS_OK(result
)) {
9324 SIVAL(r
->out
.data
, 0, changeid
);
9330 result
= winreg_get_printer_dataex(p
->mem_ctx
, b
,
9337 if (!W_ERROR_IS_OK(result
)) {
9341 *r
->out
.needed
= val_size
;
9342 *r
->out
.type
= val_type
;
9344 if (r
->in
.offered
>= *r
->out
.needed
) {
9345 memcpy(r
->out
.data
, val_data
, val_size
);
9349 /* retain type when returning WERR_MORE_DATA */
9350 r
->out
.data
= SPOOLSS_BUFFER_OK(r
->out
.data
, r
->out
.data
);
9352 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9355 /****************************************************************
9356 _spoolss_SetPrinterDataEx
9357 ****************************************************************/
9359 WERROR
_spoolss_SetPrinterDataEx(struct pipes_struct
*p
,
9360 struct spoolss_SetPrinterDataEx
*r
)
9362 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
9364 WERROR result
= WERR_OK
;
9365 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9367 struct dcerpc_binding_handle
*b
;
9369 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9371 /* From MSDN documentation of SetPrinterDataEx: pass request to
9372 SetPrinterData if key is "PrinterDriverData" */
9375 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9376 OUR_HANDLE(r
->in
.handle
)));
9380 if (Printer
->printer_type
== SPLHND_SERVER
) {
9381 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9382 "Not implemented for server handles yet\n"));
9383 return WERR_INVALID_PARAM
;
9386 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9391 * Access check : NT returns "access denied" if you make a
9392 * SetPrinterData call without the necessary privildge.
9393 * we were originally returning OK if nothing changed
9394 * which made Win2k issue **a lot** of SetPrinterData
9395 * when connecting to a printer --jerry
9398 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9399 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9400 "change denied by handle access permissions\n"));
9401 return WERR_ACCESS_DENIED
;
9404 result
= winreg_printer_binding_handle(p
->mem_ctx
,
9405 get_session_info_system(),
9408 if (!W_ERROR_IS_OK(result
)) {
9412 result
= winreg_get_printer(Printer
, b
,
9413 lp_servicename(snum
),
9415 if (!W_ERROR_IS_OK(result
)) {
9419 /* check for OID in valuename */
9421 oid_string
= strchr(r
->in
.value_name
, ',');
9427 /* save the registry data */
9429 result
= winreg_set_printer_dataex(p
->mem_ctx
, b
,
9437 if (W_ERROR_IS_OK(result
)) {
9438 /* save the OID if one was specified */
9440 char *str
= talloc_asprintf(p
->mem_ctx
, "%s\\%s",
9441 r
->in
.key_name
, SPOOL_OID_KEY
);
9443 result
= WERR_NOMEM
;
9448 * I'm not checking the status here on purpose. Don't know
9449 * if this is right, but I'm returning the status from the
9450 * previous set_printer_dataex() call. I have no idea if
9451 * this is right. --jerry
9453 winreg_set_printer_dataex(p
->mem_ctx
, b
,
9458 (uint8_t *) oid_string
,
9459 strlen(oid_string
) + 1);
9462 result
= winreg_printer_update_changeid(p
->mem_ctx
, b
,
9463 lp_const_servicename(snum
));
9468 talloc_free(pinfo2
);
9472 /****************************************************************
9473 _spoolss_DeletePrinterDataEx
9474 ****************************************************************/
9476 WERROR
_spoolss_DeletePrinterDataEx(struct pipes_struct
*p
,
9477 struct spoolss_DeletePrinterDataEx
*r
)
9479 const char *printer
;
9481 WERROR status
= WERR_OK
;
9482 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9484 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9487 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9488 "Invalid handle (%s:%u:%u).\n",
9489 OUR_HANDLE(r
->in
.handle
)));
9493 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9494 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9495 "printer properties change denied by handle\n"));
9496 return WERR_ACCESS_DENIED
;
9499 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
9503 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9506 printer
= lp_const_servicename(snum
);
9508 status
= winreg_delete_printer_dataex_internal(p
->mem_ctx
,
9509 get_session_info_system(),
9514 if (W_ERROR_IS_OK(status
)) {
9515 status
= winreg_printer_update_changeid_internal(p
->mem_ctx
,
9516 get_session_info_system(),
9524 /****************************************************************
9525 _spoolss_EnumPrinterKey
9526 ****************************************************************/
9528 WERROR
_spoolss_EnumPrinterKey(struct pipes_struct
*p
,
9529 struct spoolss_EnumPrinterKey
*r
)
9532 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9534 WERROR result
= WERR_BADFILE
;
9535 const char **array
= NULL
;
9538 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9541 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9542 OUR_HANDLE(r
->in
.handle
)));
9546 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9550 result
= winreg_enum_printer_key_internal(p
->mem_ctx
,
9551 get_session_info_system(),
9553 lp_const_servicename(snum
),
9557 if (!W_ERROR_IS_OK(result
)) {
9561 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
9562 result
= WERR_NOMEM
;
9566 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
9567 *r
->out
.needed
= blob
.length
;
9569 if (r
->in
.offered
< *r
->out
.needed
) {
9570 result
= WERR_MORE_DATA
;
9573 r
->out
.key_buffer
->string_array
= array
;
9577 if (!W_ERROR_IS_OK(result
)) {
9579 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
9587 /****************************************************************
9588 _spoolss_DeletePrinterKey
9589 ****************************************************************/
9591 WERROR
_spoolss_DeletePrinterKey(struct pipes_struct
*p
,
9592 struct spoolss_DeletePrinterKey
*r
)
9594 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9597 const char *printer
;
9598 struct dcerpc_binding_handle
*b
;
9600 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9603 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9604 OUR_HANDLE(r
->in
.handle
)));
9608 /* if keyname == NULL, return error */
9609 if ( !r
->in
.key_name
)
9610 return WERR_INVALID_PARAM
;
9612 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9616 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9617 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9618 "printer properties change denied by handle\n"));
9619 return WERR_ACCESS_DENIED
;
9622 printer
= lp_const_servicename(snum
);
9624 status
= winreg_printer_binding_handle(p
->mem_ctx
,
9625 get_session_info_system(),
9628 if (!W_ERROR_IS_OK(status
)) {
9632 /* delete the key and all subkeys */
9633 status
= winreg_delete_printer_key(p
->mem_ctx
, b
,
9636 if (W_ERROR_IS_OK(status
)) {
9637 status
= winreg_printer_update_changeid(p
->mem_ctx
, b
,
9644 /****************************************************************
9645 _spoolss_EnumPrinterDataEx
9646 ****************************************************************/
9648 WERROR
_spoolss_EnumPrinterDataEx(struct pipes_struct
*p
,
9649 struct spoolss_EnumPrinterDataEx
*r
)
9652 struct spoolss_PrinterEnumValues
*info
= NULL
;
9653 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9657 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9661 *r
->out
.info
= NULL
;
9664 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9665 OUR_HANDLE(r
->in
.handle
)));
9670 * first check for a keyname of NULL or "". Win2k seems to send
9671 * this a lot and we should send back WERR_INVALID_PARAM
9672 * no need to spend time looking up the printer in this case.
9676 if (!strlen(r
->in
.key_name
)) {
9677 result
= WERR_INVALID_PARAM
;
9681 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9685 /* now look for a match on the key name */
9686 result
= winreg_enum_printer_dataex_internal(p
->mem_ctx
,
9687 get_session_info_system(),
9689 lp_const_servicename(snum
),
9693 if (!W_ERROR_IS_OK(result
)) {
9697 #if 0 /* FIXME - gd */
9698 /* housekeeping information in the reply */
9700 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9701 * the hand marshalled container size is a multiple
9702 * of 4 bytes for RPC alignment.
9706 needed
+= 4-(needed
% 4);
9709 *r
->out
.count
= count
;
9710 *r
->out
.info
= info
;
9713 if (!W_ERROR_IS_OK(result
)) {
9717 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
9718 spoolss_EnumPrinterDataEx
,
9721 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9722 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
9724 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9727 /****************************************************************************
9728 ****************************************************************************/
9730 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
9731 const char *servername
,
9732 const char *environment
,
9733 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
9738 werr
= compose_spoolss_server_path(mem_ctx
,
9741 SPOOLSS_PRTPROCS_PATH
,
9743 if (!W_ERROR_IS_OK(werr
)) {
9747 DEBUG(4,("print processor directory: [%s]\n", path
));
9749 r
->directory_name
= path
;
9754 /****************************************************************
9755 _spoolss_GetPrintProcessorDirectory
9756 ****************************************************************/
9758 WERROR
_spoolss_GetPrintProcessorDirectory(struct pipes_struct
*p
,
9759 struct spoolss_GetPrintProcessorDirectory
*r
)
9762 char *prnproc_share
= NULL
;
9763 bool prnproc_share_exists
= false;
9766 /* that's an [in out] buffer */
9768 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9769 return WERR_INVALID_PARAM
;
9772 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9777 /* r->in.level is ignored */
9779 /* We always should reply with a local print processor directory so that
9780 * users are not forced to have a [prnproc$] share on the Samba spoolss
9781 * server, if users decide to do so, lets announce it though - Guenther */
9783 snum
= find_service(talloc_tos(), "prnproc$", &prnproc_share
);
9784 if (!prnproc_share
) {
9788 prnproc_share_exists
= true;
9791 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9792 prnproc_share_exists
? r
->in
.server
: NULL
,
9794 &r
->out
.info
->info1
);
9795 if (!W_ERROR_IS_OK(result
)) {
9796 TALLOC_FREE(r
->out
.info
);
9800 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
,
9801 r
->out
.info
, r
->in
.level
);
9802 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9804 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9807 /*******************************************************************
9808 ********************************************************************/
9810 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9811 const char *dllname
)
9813 enum ndr_err_code ndr_err
;
9814 struct spoolss_MonitorUi ui
;
9816 ui
.dll_name
= dllname
;
9818 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, &ui
,
9819 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9820 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9821 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9823 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9826 /*******************************************************************
9827 Streams the monitor UI DLL name in UNICODE
9828 *******************************************************************/
9830 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9831 struct security_token
*token
, DATA_BLOB
*in
,
9832 DATA_BLOB
*out
, uint32_t *needed
)
9834 const char *dllname
= "tcpmonui.dll";
9836 *needed
= (strlen(dllname
)+1) * 2;
9838 if (out
->length
< *needed
) {
9839 return WERR_INSUFFICIENT_BUFFER
;
9842 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9849 /*******************************************************************
9850 ********************************************************************/
9852 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9853 struct spoolss_PortData1
*port1
,
9854 const DATA_BLOB
*buf
)
9856 enum ndr_err_code ndr_err
;
9857 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port1
,
9858 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9859 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9860 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9862 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9865 /*******************************************************************
9866 ********************************************************************/
9868 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9869 struct spoolss_PortData2
*port2
,
9870 const DATA_BLOB
*buf
)
9872 enum ndr_err_code ndr_err
;
9873 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port2
,
9874 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9875 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9876 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9878 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9881 /*******************************************************************
9882 Create a new TCP/IP port
9883 *******************************************************************/
9885 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9886 struct security_token
*token
, DATA_BLOB
*in
,
9887 DATA_BLOB
*out
, uint32_t *needed
)
9889 struct spoolss_PortData1 port1
;
9890 struct spoolss_PortData2 port2
;
9891 char *device_uri
= NULL
;
9894 const char *portname
;
9895 const char *hostaddress
;
9897 uint32_t port_number
;
9900 /* peek for spoolss_PortData version */
9902 if (!in
|| (in
->length
< (128 + 4))) {
9903 return WERR_GENERAL_FAILURE
;
9906 version
= IVAL(in
->data
, 128);
9912 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9916 portname
= port1
.portname
;
9917 hostaddress
= port1
.hostaddress
;
9918 queue
= port1
.queue
;
9919 protocol
= port1
.protocol
;
9920 port_number
= port1
.port_number
;
9926 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9930 portname
= port2
.portname
;
9931 hostaddress
= port2
.hostaddress
;
9932 queue
= port2
.queue
;
9933 protocol
= port2
.protocol
;
9934 port_number
= port2
.port_number
;
9938 DEBUG(1,("xcvtcp_addport: "
9939 "unknown version of port_data: %d\n", version
));
9940 return WERR_UNKNOWN_PORT
;
9943 /* create the device URI and call the add_port_hook() */
9946 case PROTOCOL_RAWTCP_TYPE
:
9947 device_uri
= talloc_asprintf(mem_ctx
,
9948 "socket://%s:%d/", hostaddress
,
9952 case PROTOCOL_LPR_TYPE
:
9953 device_uri
= talloc_asprintf(mem_ctx
,
9954 "lpr://%s/%s", hostaddress
, queue
);
9958 return WERR_UNKNOWN_PORT
;
9965 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
9968 /*******************************************************************
9969 *******************************************************************/
9971 struct xcv_api_table xcvtcp_cmds
[] = {
9972 { "MonitorUI", xcvtcp_monitorui
},
9973 { "AddPort", xcvtcp_addport
},
9977 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
9978 struct security_token
*token
, const char *command
,
9985 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9987 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9988 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9989 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9992 return WERR_BADFUNC
;
9995 /*******************************************************************
9996 *******************************************************************/
9997 #if 0 /* don't support management using the "Local Port" monitor */
9999 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
10000 struct security_token
*token
, DATA_BLOB
*in
,
10001 DATA_BLOB
*out
, uint32_t *needed
)
10003 const char *dllname
= "localui.dll";
10005 *needed
= (strlen(dllname
)+1) * 2;
10007 if (out
->length
< *needed
) {
10008 return WERR_INSUFFICIENT_BUFFER
;
10011 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
10018 /*******************************************************************
10019 *******************************************************************/
10021 struct xcv_api_table xcvlocal_cmds
[] = {
10022 { "MonitorUI", xcvlocal_monitorui
},
10026 struct xcv_api_table xcvlocal_cmds
[] = {
10033 /*******************************************************************
10034 *******************************************************************/
10036 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
10037 struct security_token
*token
, const char *command
,
10038 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
10043 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
10045 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
10046 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
10047 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
10049 return WERR_BADFUNC
;
10052 /****************************************************************
10054 ****************************************************************/
10056 WERROR
_spoolss_XcvData(struct pipes_struct
*p
,
10057 struct spoolss_XcvData
*r
)
10059 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
10060 DATA_BLOB out_data
= data_blob_null
;
10064 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10065 OUR_HANDLE(r
->in
.handle
)));
10066 return WERR_BADFID
;
10069 /* Has to be a handle to the TCP/IP port monitor */
10071 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
10072 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10073 return WERR_BADFID
;
10076 /* requires administrative access to the server */
10078 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
10079 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10080 return WERR_ACCESS_DENIED
;
10083 /* Allocate the outgoing buffer */
10085 if (r
->in
.out_data_size
) {
10086 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
10087 if (out_data
.data
== NULL
) {
10092 switch ( Printer
->printer_type
) {
10093 case SPLHND_PORTMON_TCP
:
10094 werror
= process_xcvtcp_command(p
->mem_ctx
,
10095 p
->session_info
->security_token
,
10096 r
->in
.function_name
,
10097 &r
->in
.in_data
, &out_data
,
10100 case SPLHND_PORTMON_LOCAL
:
10101 werror
= process_xcvlocal_command(p
->mem_ctx
,
10102 p
->session_info
->security_token
,
10103 r
->in
.function_name
,
10104 &r
->in
.in_data
, &out_data
,
10108 werror
= WERR_INVALID_PRINT_MONITOR
;
10111 if (!W_ERROR_IS_OK(werror
)) {
10115 *r
->out
.status_code
= 0;
10117 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
10118 memcpy(r
->out
.out_data
, out_data
.data
,
10119 MIN(r
->in
.out_data_size
, out_data
.length
));
10125 /****************************************************************
10126 _spoolss_AddPrintProcessor
10127 ****************************************************************/
10129 WERROR
_spoolss_AddPrintProcessor(struct pipes_struct
*p
,
10130 struct spoolss_AddPrintProcessor
*r
)
10132 /* for now, just indicate success and ignore the add. We'll
10133 automatically set the winprint processor for printer
10134 entries later. Used to debug the LexMark Optra S 1855 PCL
10140 /****************************************************************
10142 ****************************************************************/
10144 WERROR
_spoolss_AddPort(struct pipes_struct
*p
,
10145 struct spoolss_AddPort
*r
)
10147 /* do what w2k3 does */
10149 return WERR_NOT_SUPPORTED
;
10152 /****************************************************************
10153 _spoolss_GetPrinterDriver
10154 ****************************************************************/
10156 WERROR
_spoolss_GetPrinterDriver(struct pipes_struct
*p
,
10157 struct spoolss_GetPrinterDriver
*r
)
10159 p
->rng_fault_state
= true;
10160 return WERR_NOT_SUPPORTED
;
10163 /****************************************************************
10164 _spoolss_ReadPrinter
10165 ****************************************************************/
10167 WERROR
_spoolss_ReadPrinter(struct pipes_struct
*p
,
10168 struct spoolss_ReadPrinter
*r
)
10170 p
->rng_fault_state
= true;
10171 return WERR_NOT_SUPPORTED
;
10174 /****************************************************************
10175 _spoolss_WaitForPrinterChange
10176 ****************************************************************/
10178 WERROR
_spoolss_WaitForPrinterChange(struct pipes_struct
*p
,
10179 struct spoolss_WaitForPrinterChange
*r
)
10181 p
->rng_fault_state
= true;
10182 return WERR_NOT_SUPPORTED
;
10185 /****************************************************************
10186 _spoolss_ConfigurePort
10187 ****************************************************************/
10189 WERROR
_spoolss_ConfigurePort(struct pipes_struct
*p
,
10190 struct spoolss_ConfigurePort
*r
)
10192 p
->rng_fault_state
= true;
10193 return WERR_NOT_SUPPORTED
;
10196 /****************************************************************
10197 _spoolss_DeletePort
10198 ****************************************************************/
10200 WERROR
_spoolss_DeletePort(struct pipes_struct
*p
,
10201 struct spoolss_DeletePort
*r
)
10203 p
->rng_fault_state
= true;
10204 return WERR_NOT_SUPPORTED
;
10207 /****************************************************************
10208 _spoolss_CreatePrinterIC
10209 ****************************************************************/
10211 WERROR
_spoolss_CreatePrinterIC(struct pipes_struct
*p
,
10212 struct spoolss_CreatePrinterIC
*r
)
10214 p
->rng_fault_state
= true;
10215 return WERR_NOT_SUPPORTED
;
10218 /****************************************************************
10219 _spoolss_PlayGDIScriptOnPrinterIC
10220 ****************************************************************/
10222 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct
*p
,
10223 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
10225 p
->rng_fault_state
= true;
10226 return WERR_NOT_SUPPORTED
;
10229 /****************************************************************
10230 _spoolss_DeletePrinterIC
10231 ****************************************************************/
10233 WERROR
_spoolss_DeletePrinterIC(struct pipes_struct
*p
,
10234 struct spoolss_DeletePrinterIC
*r
)
10236 p
->rng_fault_state
= true;
10237 return WERR_NOT_SUPPORTED
;
10240 /****************************************************************
10241 _spoolss_AddPrinterConnection
10242 ****************************************************************/
10244 WERROR
_spoolss_AddPrinterConnection(struct pipes_struct
*p
,
10245 struct spoolss_AddPrinterConnection
*r
)
10247 p
->rng_fault_state
= true;
10248 return WERR_NOT_SUPPORTED
;
10251 /****************************************************************
10252 _spoolss_DeletePrinterConnection
10253 ****************************************************************/
10255 WERROR
_spoolss_DeletePrinterConnection(struct pipes_struct
*p
,
10256 struct spoolss_DeletePrinterConnection
*r
)
10258 p
->rng_fault_state
= true;
10259 return WERR_NOT_SUPPORTED
;
10262 /****************************************************************
10263 _spoolss_PrinterMessageBox
10264 ****************************************************************/
10266 WERROR
_spoolss_PrinterMessageBox(struct pipes_struct
*p
,
10267 struct spoolss_PrinterMessageBox
*r
)
10269 p
->rng_fault_state
= true;
10270 return WERR_NOT_SUPPORTED
;
10273 /****************************************************************
10274 _spoolss_AddMonitor
10275 ****************************************************************/
10277 WERROR
_spoolss_AddMonitor(struct pipes_struct
*p
,
10278 struct spoolss_AddMonitor
*r
)
10280 p
->rng_fault_state
= true;
10281 return WERR_NOT_SUPPORTED
;
10284 /****************************************************************
10285 _spoolss_DeleteMonitor
10286 ****************************************************************/
10288 WERROR
_spoolss_DeleteMonitor(struct pipes_struct
*p
,
10289 struct spoolss_DeleteMonitor
*r
)
10291 p
->rng_fault_state
= true;
10292 return WERR_NOT_SUPPORTED
;
10295 /****************************************************************
10296 _spoolss_DeletePrintProcessor
10297 ****************************************************************/
10299 WERROR
_spoolss_DeletePrintProcessor(struct pipes_struct
*p
,
10300 struct spoolss_DeletePrintProcessor
*r
)
10302 p
->rng_fault_state
= true;
10303 return WERR_NOT_SUPPORTED
;
10306 /****************************************************************
10307 _spoolss_AddPrintProvidor
10308 ****************************************************************/
10310 WERROR
_spoolss_AddPrintProvidor(struct pipes_struct
*p
,
10311 struct spoolss_AddPrintProvidor
*r
)
10313 p
->rng_fault_state
= true;
10314 return WERR_NOT_SUPPORTED
;
10317 /****************************************************************
10318 _spoolss_DeletePrintProvidor
10319 ****************************************************************/
10321 WERROR
_spoolss_DeletePrintProvidor(struct pipes_struct
*p
,
10322 struct spoolss_DeletePrintProvidor
*r
)
10324 p
->rng_fault_state
= true;
10325 return WERR_NOT_SUPPORTED
;
10328 /****************************************************************
10329 _spoolss_FindFirstPrinterChangeNotification
10330 ****************************************************************/
10332 WERROR
_spoolss_FindFirstPrinterChangeNotification(struct pipes_struct
*p
,
10333 struct spoolss_FindFirstPrinterChangeNotification
*r
)
10335 p
->rng_fault_state
= true;
10336 return WERR_NOT_SUPPORTED
;
10339 /****************************************************************
10340 _spoolss_FindNextPrinterChangeNotification
10341 ****************************************************************/
10343 WERROR
_spoolss_FindNextPrinterChangeNotification(struct pipes_struct
*p
,
10344 struct spoolss_FindNextPrinterChangeNotification
*r
)
10346 p
->rng_fault_state
= true;
10347 return WERR_NOT_SUPPORTED
;
10350 /****************************************************************
10351 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10352 ****************************************************************/
10354 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct
*p
,
10355 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
10357 p
->rng_fault_state
= true;
10358 return WERR_NOT_SUPPORTED
;
10361 /****************************************************************
10362 _spoolss_ReplyOpenPrinter
10363 ****************************************************************/
10365 WERROR
_spoolss_ReplyOpenPrinter(struct pipes_struct
*p
,
10366 struct spoolss_ReplyOpenPrinter
*r
)
10368 p
->rng_fault_state
= true;
10369 return WERR_NOT_SUPPORTED
;
10372 /****************************************************************
10373 _spoolss_RouterReplyPrinter
10374 ****************************************************************/
10376 WERROR
_spoolss_RouterReplyPrinter(struct pipes_struct
*p
,
10377 struct spoolss_RouterReplyPrinter
*r
)
10379 p
->rng_fault_state
= true;
10380 return WERR_NOT_SUPPORTED
;
10383 /****************************************************************
10384 _spoolss_ReplyClosePrinter
10385 ****************************************************************/
10387 WERROR
_spoolss_ReplyClosePrinter(struct pipes_struct
*p
,
10388 struct spoolss_ReplyClosePrinter
*r
)
10390 p
->rng_fault_state
= true;
10391 return WERR_NOT_SUPPORTED
;
10394 /****************************************************************
10396 ****************************************************************/
10398 WERROR
_spoolss_AddPortEx(struct pipes_struct
*p
,
10399 struct spoolss_AddPortEx
*r
)
10401 p
->rng_fault_state
= true;
10402 return WERR_NOT_SUPPORTED
;
10405 /****************************************************************
10406 _spoolss_RouterFindFirstPrinterChangeNotification
10407 ****************************************************************/
10409 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct
*p
,
10410 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
10412 p
->rng_fault_state
= true;
10413 return WERR_NOT_SUPPORTED
;
10416 /****************************************************************
10417 _spoolss_SpoolerInit
10418 ****************************************************************/
10420 WERROR
_spoolss_SpoolerInit(struct pipes_struct
*p
,
10421 struct spoolss_SpoolerInit
*r
)
10423 p
->rng_fault_state
= true;
10424 return WERR_NOT_SUPPORTED
;
10427 /****************************************************************
10428 _spoolss_ResetPrinterEx
10429 ****************************************************************/
10431 WERROR
_spoolss_ResetPrinterEx(struct pipes_struct
*p
,
10432 struct spoolss_ResetPrinterEx
*r
)
10434 p
->rng_fault_state
= true;
10435 return WERR_NOT_SUPPORTED
;
10438 /****************************************************************
10439 _spoolss_RouterReplyPrinterEx
10440 ****************************************************************/
10442 WERROR
_spoolss_RouterReplyPrinterEx(struct pipes_struct
*p
,
10443 struct spoolss_RouterReplyPrinterEx
*r
)
10445 p
->rng_fault_state
= true;
10446 return WERR_NOT_SUPPORTED
;
10449 /****************************************************************
10451 ****************************************************************/
10453 WERROR
_spoolss_44(struct pipes_struct
*p
,
10454 struct spoolss_44
*r
)
10456 p
->rng_fault_state
= true;
10457 return WERR_NOT_SUPPORTED
;
10460 /****************************************************************
10462 ****************************************************************/
10464 WERROR
_spoolss_SetPort(struct pipes_struct
*p
,
10465 struct spoolss_SetPort
*r
)
10467 p
->rng_fault_state
= true;
10468 return WERR_NOT_SUPPORTED
;
10471 /****************************************************************
10473 ****************************************************************/
10475 WERROR
_spoolss_4a(struct pipes_struct
*p
,
10476 struct spoolss_4a
*r
)
10478 p
->rng_fault_state
= true;
10479 return WERR_NOT_SUPPORTED
;
10482 /****************************************************************
10484 ****************************************************************/
10486 WERROR
_spoolss_4b(struct pipes_struct
*p
,
10487 struct spoolss_4b
*r
)
10489 p
->rng_fault_state
= true;
10490 return WERR_NOT_SUPPORTED
;
10493 /****************************************************************
10495 ****************************************************************/
10497 WERROR
_spoolss_4c(struct pipes_struct
*p
,
10498 struct spoolss_4c
*r
)
10500 p
->rng_fault_state
= true;
10501 return WERR_NOT_SUPPORTED
;
10504 /****************************************************************
10506 ****************************************************************/
10508 WERROR
_spoolss_53(struct pipes_struct
*p
,
10509 struct spoolss_53
*r
)
10511 p
->rng_fault_state
= true;
10512 return WERR_NOT_SUPPORTED
;
10515 /****************************************************************
10516 _spoolss_AddPerMachineConnection
10517 ****************************************************************/
10519 WERROR
_spoolss_AddPerMachineConnection(struct pipes_struct
*p
,
10520 struct spoolss_AddPerMachineConnection
*r
)
10522 p
->rng_fault_state
= true;
10523 return WERR_NOT_SUPPORTED
;
10526 /****************************************************************
10527 _spoolss_DeletePerMachineConnection
10528 ****************************************************************/
10530 WERROR
_spoolss_DeletePerMachineConnection(struct pipes_struct
*p
,
10531 struct spoolss_DeletePerMachineConnection
*r
)
10533 p
->rng_fault_state
= true;
10534 return WERR_NOT_SUPPORTED
;
10537 /****************************************************************
10538 _spoolss_EnumPerMachineConnections
10539 ****************************************************************/
10541 WERROR
_spoolss_EnumPerMachineConnections(struct pipes_struct
*p
,
10542 struct spoolss_EnumPerMachineConnections
*r
)
10544 p
->rng_fault_state
= true;
10545 return WERR_NOT_SUPPORTED
;
10548 /****************************************************************
10550 ****************************************************************/
10552 WERROR
_spoolss_5a(struct pipes_struct
*p
,
10553 struct spoolss_5a
*r
)
10555 p
->rng_fault_state
= true;
10556 return WERR_NOT_SUPPORTED
;
10559 /****************************************************************
10561 ****************************************************************/
10563 WERROR
_spoolss_5b(struct pipes_struct
*p
,
10564 struct spoolss_5b
*r
)
10566 p
->rng_fault_state
= true;
10567 return WERR_NOT_SUPPORTED
;
10570 /****************************************************************
10572 ****************************************************************/
10574 WERROR
_spoolss_5c(struct pipes_struct
*p
,
10575 struct spoolss_5c
*r
)
10577 p
->rng_fault_state
= true;
10578 return WERR_NOT_SUPPORTED
;
10581 /****************************************************************
10583 ****************************************************************/
10585 WERROR
_spoolss_5d(struct pipes_struct
*p
,
10586 struct spoolss_5d
*r
)
10588 p
->rng_fault_state
= true;
10589 return WERR_NOT_SUPPORTED
;
10592 /****************************************************************
10594 ****************************************************************/
10596 WERROR
_spoolss_5e(struct pipes_struct
*p
,
10597 struct spoolss_5e
*r
)
10599 p
->rng_fault_state
= true;
10600 return WERR_NOT_SUPPORTED
;
10603 /****************************************************************
10605 ****************************************************************/
10607 WERROR
_spoolss_5f(struct pipes_struct
*p
,
10608 struct spoolss_5f
*r
)
10610 p
->rng_fault_state
= true;
10611 return WERR_NOT_SUPPORTED
;
10614 /****************************************************************
10616 ****************************************************************/
10618 WERROR
_spoolss_60(struct pipes_struct
*p
,
10619 struct spoolss_60
*r
)
10621 p
->rng_fault_state
= true;
10622 return WERR_NOT_SUPPORTED
;
10625 /****************************************************************
10627 ****************************************************************/
10629 WERROR
_spoolss_61(struct pipes_struct
*p
,
10630 struct spoolss_61
*r
)
10632 p
->rng_fault_state
= true;
10633 return WERR_NOT_SUPPORTED
;
10636 /****************************************************************
10638 ****************************************************************/
10640 WERROR
_spoolss_62(struct pipes_struct
*p
,
10641 struct spoolss_62
*r
)
10643 p
->rng_fault_state
= true;
10644 return WERR_NOT_SUPPORTED
;
10647 /****************************************************************
10649 ****************************************************************/
10651 WERROR
_spoolss_63(struct pipes_struct
*p
,
10652 struct spoolss_63
*r
)
10654 p
->rng_fault_state
= true;
10655 return WERR_NOT_SUPPORTED
;
10658 /****************************************************************
10660 ****************************************************************/
10662 WERROR
_spoolss_64(struct pipes_struct
*p
,
10663 struct spoolss_64
*r
)
10665 p
->rng_fault_state
= true;
10666 return WERR_NOT_SUPPORTED
;
10669 /****************************************************************
10671 ****************************************************************/
10673 WERROR
_spoolss_65(struct pipes_struct
*p
,
10674 struct spoolss_65
*r
)
10676 p
->rng_fault_state
= true;
10677 return WERR_NOT_SUPPORTED
;
10680 /****************************************************************
10681 _spoolss_GetCorePrinterDrivers
10682 ****************************************************************/
10684 WERROR
_spoolss_GetCorePrinterDrivers(struct pipes_struct
*p
,
10685 struct spoolss_GetCorePrinterDrivers
*r
)
10687 p
->rng_fault_state
= true;
10688 return WERR_NOT_SUPPORTED
;
10691 /****************************************************************
10693 ****************************************************************/
10695 WERROR
_spoolss_67(struct pipes_struct
*p
,
10696 struct spoolss_67
*r
)
10698 p
->rng_fault_state
= true;
10699 return WERR_NOT_SUPPORTED
;
10702 /****************************************************************
10703 _spoolss_GetPrinterDriverPackagePath
10704 ****************************************************************/
10706 WERROR
_spoolss_GetPrinterDriverPackagePath(struct pipes_struct
*p
,
10707 struct spoolss_GetPrinterDriverPackagePath
*r
)
10709 p
->rng_fault_state
= true;
10710 return WERR_NOT_SUPPORTED
;
10713 /****************************************************************
10715 ****************************************************************/
10717 WERROR
_spoolss_69(struct pipes_struct
*p
,
10718 struct spoolss_69
*r
)
10720 p
->rng_fault_state
= true;
10721 return WERR_NOT_SUPPORTED
;
10724 /****************************************************************
10726 ****************************************************************/
10728 WERROR
_spoolss_6a(struct pipes_struct
*p
,
10729 struct spoolss_6a
*r
)
10731 p
->rng_fault_state
= true;
10732 return WERR_NOT_SUPPORTED
;
10735 /****************************************************************
10737 ****************************************************************/
10739 WERROR
_spoolss_6b(struct pipes_struct
*p
,
10740 struct spoolss_6b
*r
)
10742 p
->rng_fault_state
= true;
10743 return WERR_NOT_SUPPORTED
;
10746 /****************************************************************
10748 ****************************************************************/
10750 WERROR
_spoolss_6c(struct pipes_struct
*p
,
10751 struct spoolss_6c
*r
)
10753 p
->rng_fault_state
= true;
10754 return WERR_NOT_SUPPORTED
;
10757 /****************************************************************
10759 ****************************************************************/
10761 WERROR
_spoolss_6d(struct pipes_struct
*p
,
10762 struct spoolss_6d
*r
)
10764 p
->rng_fault_state
= true;
10765 return WERR_NOT_SUPPORTED
;