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(0,("_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
) {
1947 copy_devicemode(NULL
, r
->in
.devmode_ctr
.devmode
,
1951 #if 0 /* JERRY -- I'm doubtful this is really effective */
1952 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1953 optimization in Windows 2000 clients --jerry */
1955 if ( (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1956 && (RA_WIN2K
== get_remote_arch()) )
1958 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1959 sys_usleep( 500000 );
1966 /****************************************************************
1967 _spoolss_ClosePrinter
1968 ****************************************************************/
1970 WERROR
_spoolss_ClosePrinter(struct pipes_struct
*p
,
1971 struct spoolss_ClosePrinter
*r
)
1973 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1975 if (Printer
&& Printer
->document_started
) {
1976 struct spoolss_EndDocPrinter e
;
1978 e
.in
.handle
= r
->in
.handle
;
1980 _spoolss_EndDocPrinter(p
, &e
);
1983 if (!close_printer_handle(p
, r
->in
.handle
))
1986 /* clear the returned printer handle. Observed behavior
1987 from Win2k server. Don't think this really matters.
1988 Previous code just copied the value of the closed
1991 ZERO_STRUCTP(r
->out
.handle
);
1996 /****************************************************************
1997 _spoolss_DeletePrinter
1998 ****************************************************************/
2000 WERROR
_spoolss_DeletePrinter(struct pipes_struct
*p
,
2001 struct spoolss_DeletePrinter
*r
)
2003 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2007 if (Printer
&& Printer
->document_started
) {
2008 struct spoolss_EndDocPrinter e
;
2010 e
.in
.handle
= r
->in
.handle
;
2012 _spoolss_EndDocPrinter(p
, &e
);
2015 if (get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
2016 winreg_delete_printer_key_internal(p
->mem_ctx
,
2017 get_session_info_system(),
2019 lp_const_servicename(snum
),
2023 result
= delete_printer_handle(p
, r
->in
.handle
);
2028 /*******************************************************************
2029 * static function to lookup the version id corresponding to an
2030 * long architecture string
2031 ******************************************************************/
2033 static const struct print_architecture_table_node archi_table
[]= {
2035 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
2036 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
2037 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
2038 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
2039 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
2040 {"Windows IA64", SPL_ARCH_IA64
, 3 },
2041 {"Windows x64", SPL_ARCH_X64
, 3 },
2045 static int get_version_id(const char *arch
)
2049 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
2051 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
2052 return (archi_table
[i
].version
);
2058 /****************************************************************
2059 _spoolss_DeletePrinterDriver
2060 ****************************************************************/
2062 WERROR
_spoolss_DeletePrinterDriver(struct pipes_struct
*p
,
2063 struct spoolss_DeletePrinterDriver
*r
)
2066 struct spoolss_DriverInfo8
*info
= NULL
;
2067 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
2070 struct dcerpc_binding_handle
*b
;
2072 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2073 and not a printer admin, then fail */
2075 if ( (p
->session_info
->utok
.uid
!= sec_initial_uid())
2076 && !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
)
2077 && !token_contains_name_in_list(
2078 uidtoname(p
->session_info
->utok
.uid
),
2079 p
->session_info
->info3
->base
.domain
.string
,
2081 p
->session_info
->security_token
,
2082 lp_printer_admin(-1)) )
2084 return WERR_ACCESS_DENIED
;
2087 /* check that we have a valid driver name first */
2089 if ((version
= get_version_id(r
->in
.architecture
)) == -1)
2090 return WERR_INVALID_ENVIRONMENT
;
2092 status
= winreg_printer_binding_handle(p
->mem_ctx
,
2093 get_session_info_system(),
2096 if (!W_ERROR_IS_OK(status
)) {
2100 status
= winreg_get_driver(p
->mem_ctx
, b
,
2101 r
->in
.architecture
, r
->in
.driver
,
2103 if (!W_ERROR_IS_OK(status
)) {
2104 /* try for Win2k driver if "Windows NT x86" */
2106 if ( version
== 2 ) {
2109 status
= winreg_get_driver(p
->mem_ctx
, b
,
2113 if (!W_ERROR_IS_OK(status
)) {
2114 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2118 /* otherwise it was a failure */
2120 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2126 if (printer_driver_in_use(p
->mem_ctx
,
2127 get_session_info_system(),
2130 status
= WERR_PRINTER_DRIVER_IN_USE
;
2135 status
= winreg_get_driver(p
->mem_ctx
, b
,
2137 r
->in
.driver
, 3, &info_win2k
);
2138 if (W_ERROR_IS_OK(status
)) {
2139 /* if we get to here, we now have 2 driver info structures to remove */
2140 /* remove the Win2k driver first*/
2142 status
= winreg_del_driver(p
->mem_ctx
, b
,
2144 talloc_free(info_win2k
);
2146 /* this should not have failed---if it did, report to client */
2147 if (!W_ERROR_IS_OK(status
)) {
2153 status
= winreg_del_driver(p
->mem_ctx
, b
,
2162 /****************************************************************
2163 _spoolss_DeletePrinterDriverEx
2164 ****************************************************************/
2166 WERROR
_spoolss_DeletePrinterDriverEx(struct pipes_struct
*p
,
2167 struct spoolss_DeletePrinterDriverEx
*r
)
2169 struct spoolss_DriverInfo8
*info
= NULL
;
2170 struct spoolss_DriverInfo8
*info_win2k
= NULL
;
2174 struct dcerpc_binding_handle
*b
;
2176 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2177 and not a printer admin, then fail */
2179 if ( (p
->session_info
->utok
.uid
!= sec_initial_uid())
2180 && !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
)
2181 && !token_contains_name_in_list(
2182 uidtoname(p
->session_info
->utok
.uid
),
2183 p
->session_info
->info3
->base
.domain
.string
,
2185 p
->session_info
->security_token
, lp_printer_admin(-1)) )
2187 return WERR_ACCESS_DENIED
;
2190 /* check that we have a valid driver name first */
2191 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
2192 /* this is what NT returns */
2193 return WERR_INVALID_ENVIRONMENT
;
2196 if (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
2197 version
= r
->in
.version
;
2199 status
= winreg_printer_binding_handle(p
->mem_ctx
,
2200 get_session_info_system(),
2203 if (!W_ERROR_IS_OK(status
)) {
2207 status
= winreg_get_driver(p
->mem_ctx
, b
,
2212 if (!W_ERROR_IS_OK(status
)) {
2213 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2216 * if the client asked for a specific version,
2217 * or this is something other than Windows NT x86,
2221 if ( (r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) || (version
!=2) )
2224 /* try for Win2k driver if "Windows NT x86" */
2227 status
= winreg_get_driver(info
, b
,
2231 if (!W_ERROR_IS_OK(status
)) {
2232 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2237 if (printer_driver_in_use(info
,
2238 get_session_info_system(),
2241 status
= WERR_PRINTER_DRIVER_IN_USE
;
2246 * we have a couple of cases to consider.
2247 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2248 * then the delete should fail if **any** files overlap with
2250 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2251 * non-overlapping files
2252 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2253 * is set, the do not delete any files
2254 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2257 delete_files
= r
->in
.delete_flags
& (DPD_DELETE_ALL_FILES
|DPD_DELETE_UNUSED_FILES
);
2259 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2262 (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) &&
2263 printer_driver_files_in_use(info
,
2264 get_session_info_system(),
2267 /* no idea of the correct error here */
2268 status
= WERR_ACCESS_DENIED
;
2273 /* also check for W32X86/3 if necessary; maybe we already have? */
2275 if ( (version
== 2) && ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
) != DPD_DELETE_SPECIFIC_VERSION
) ) {
2276 status
= winreg_get_driver(info
, b
,
2278 r
->in
.driver
, 3, &info_win2k
);
2279 if (W_ERROR_IS_OK(status
)) {
2282 (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
) &&
2283 printer_driver_files_in_use(info
,
2284 get_session_info_system(),
2287 /* no idea of the correct error here */
2288 talloc_free(info_win2k
);
2289 status
= WERR_ACCESS_DENIED
;
2293 /* if we get to here, we now have 2 driver info structures to remove */
2294 /* remove the Win2k driver first*/
2296 status
= winreg_del_driver(info
, b
,
2300 /* this should not have failed---if it did, report to client */
2302 if (!W_ERROR_IS_OK(status
)) {
2307 * now delete any associated files if delete_files is
2308 * true. Even if this part failes, we return succes
2309 * because the driver doesn not exist any more
2312 delete_driver_files(get_session_info_system(),
2318 status
= winreg_del_driver(info
, b
,
2321 if (!W_ERROR_IS_OK(status
)) {
2326 * now delete any associated files if delete_files is
2327 * true. Even if this part failes, we return succes
2328 * because the driver doesn not exist any more
2331 delete_driver_files(get_session_info_system(), info
);
2340 /********************************************************************
2341 GetPrinterData on a printer server Handle.
2342 ********************************************************************/
2344 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2346 enum winreg_Type
*type
,
2347 union spoolss_PrinterData
*data
)
2349 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2351 if (!StrCaseCmp(value
, "W3SvcInstalled")) {
2357 if (!StrCaseCmp(value
, "BeepEnabled")) {
2363 if (!StrCaseCmp(value
, "EventLog")) {
2365 /* formally was 0x1b */
2370 if (!StrCaseCmp(value
, "NetPopup")) {
2376 if (!StrCaseCmp(value
, "MajorVersion")) {
2379 /* Windows NT 4.0 seems to not allow uploading of drivers
2380 to a server that reports 0x3 as the MajorVersion.
2381 need to investigate more how Win2k gets around this .
2384 if (RA_WINNT
== get_remote_arch()) {
2393 if (!StrCaseCmp(value
, "MinorVersion")) {
2400 * uint32_t size = 0x114
2401 * uint32_t major = 5
2402 * uint32_t minor = [0|1]
2403 * uint32_t build = [2195|2600]
2404 * extra unicode string = e.g. "Service Pack 3"
2406 if (!StrCaseCmp(value
, "OSVersion")) {
2408 enum ndr_err_code ndr_err
;
2409 struct spoolss_OSVersion os
;
2411 os
.major
= 5; /* Windows 2000 == 5.0 */
2413 os
.build
= 2195; /* build */
2414 os
.extra_string
= ""; /* leave extra string empty */
2416 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &os
,
2417 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2418 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2419 return WERR_GENERAL_FAILURE
;
2423 data
->binary
= blob
;
2429 if (!StrCaseCmp(value
, "DefaultSpoolDirectory")) {
2432 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2433 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2438 if (!StrCaseCmp(value
, "Architecture")) {
2440 data
->string
= talloc_strdup(mem_ctx
,
2441 lp_parm_const_string(GLOBAL_SECTION_SNUM
, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86
));
2442 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2447 if (!StrCaseCmp(value
, "DsPresent")) {
2450 /* only show the publish check box if we are a
2451 member of a AD domain */
2453 if (lp_security() == SEC_ADS
) {
2461 if (!StrCaseCmp(value
, "DNSMachineName")) {
2462 const char *hostname
= get_mydnsfullname();
2465 return WERR_BADFILE
;
2469 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2470 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2477 return WERR_INVALID_PARAM
;
2480 /****************************************************************
2481 _spoolss_GetPrinterData
2482 ****************************************************************/
2484 WERROR
_spoolss_GetPrinterData(struct pipes_struct
*p
,
2485 struct spoolss_GetPrinterData
*r
)
2487 struct spoolss_GetPrinterDataEx r2
;
2489 r2
.in
.handle
= r
->in
.handle
;
2490 r2
.in
.key_name
= "PrinterDriverData";
2491 r2
.in
.value_name
= r
->in
.value_name
;
2492 r2
.in
.offered
= r
->in
.offered
;
2493 r2
.out
.type
= r
->out
.type
;
2494 r2
.out
.data
= r
->out
.data
;
2495 r2
.out
.needed
= r
->out
.needed
;
2497 return _spoolss_GetPrinterDataEx(p
, &r2
);
2500 /*********************************************************
2501 Connect to the client machine.
2502 **********************************************************/
2504 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2505 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2508 struct cli_state
*the_cli
;
2509 struct sockaddr_storage rm_addr
;
2510 char addr
[INET6_ADDRSTRLEN
];
2512 if ( is_zero_addr(client_ss
) ) {
2513 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2515 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20, false) ) {
2516 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2519 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2521 rm_addr
= *client_ss
;
2522 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2523 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2527 if (ismyaddr((struct sockaddr
*)(void *)&rm_addr
)) {
2528 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2533 /* setup the connection */
2534 ret
= cli_full_connection( &the_cli
, global_myname(), remote_machine
,
2535 &rm_addr
, 0, "IPC$", "IPC",
2539 0, lp_client_signing());
2541 if ( !NT_STATUS_IS_OK( ret
) ) {
2542 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2547 if ( the_cli
->protocol
!= PROTOCOL_NT1
) {
2548 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2549 cli_shutdown(the_cli
);
2554 * Ok - we have an anonymous connection to the IPC$ share.
2555 * Now start the NT Domain stuff :-).
2558 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2559 if (!NT_STATUS_IS_OK(ret
)) {
2560 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2561 remote_machine
, nt_errstr(ret
)));
2562 cli_shutdown(the_cli
);
2569 /***************************************************************************
2570 Connect to the client.
2571 ****************************************************************************/
2573 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2574 uint32_t localprinter
,
2575 enum winreg_Type type
,
2576 struct policy_handle
*handle
,
2577 struct notify_back_channel
**_chan
,
2578 struct sockaddr_storage
*client_ss
,
2579 struct messaging_context
*msg_ctx
)
2583 struct notify_back_channel
*chan
;
2585 for (chan
= back_channels
; chan
; chan
= chan
->next
) {
2586 if (memcmp(&chan
->client_address
, client_ss
,
2587 sizeof(struct sockaddr_storage
)) == 0) {
2593 * If it's the first connection, contact the client
2594 * and connect to the IPC$ share anonymously
2597 fstring unix_printer
;
2599 /* the +2 is to strip the leading 2 backslashs */
2600 fstrcpy(unix_printer
, printer
+ 2);
2602 chan
= talloc_zero(back_channels
, struct notify_back_channel
);
2606 chan
->client_address
= *client_ss
;
2608 if (!spoolss_connect_to_client(&chan
->cli_pipe
, client_ss
, unix_printer
)) {
2612 chan
->binding_handle
= chan
->cli_pipe
->binding_handle
;
2614 DLIST_ADD(back_channels
, chan
);
2616 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_NOTIFY2
,
2617 receive_notify2_message_list
);
2618 /* Tell the connections db we're now interested in printer
2619 * notify messages. */
2620 serverid_register_msg_flags(messaging_server_id(msg_ctx
),
2621 true, FLAG_MSG_PRINT_NOTIFY
);
2625 * Tell the specific printing tdb we want messages for this printer
2626 * by registering our PID.
2629 if (!print_notify_register_pid(snum
)) {
2630 DEBUG(0, ("Failed to register our pid for printer %s\n",
2634 status
= dcerpc_spoolss_ReplyOpenPrinter(chan
->binding_handle
,
2643 if (!NT_STATUS_IS_OK(status
)) {
2644 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status
)));
2645 result
= ntstatus_to_werror(status
);
2646 } else if (!W_ERROR_IS_OK(result
)) {
2647 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result
)));
2650 chan
->active_connections
++;
2653 return (W_ERROR_IS_OK(result
));
2656 /****************************************************************
2657 ****************************************************************/
2659 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2660 const struct spoolss_NotifyOption
*r
)
2662 struct spoolss_NotifyOption
*option
;
2669 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2676 if (!option
->count
) {
2680 option
->types
= talloc_zero_array(option
,
2681 struct spoolss_NotifyOptionType
, option
->count
);
2682 if (!option
->types
) {
2683 talloc_free(option
);
2687 for (i
=0; i
< option
->count
; i
++) {
2688 option
->types
[i
] = r
->types
[i
];
2690 if (option
->types
[i
].count
) {
2691 option
->types
[i
].fields
= talloc_zero_array(option
,
2692 union spoolss_Field
, option
->types
[i
].count
);
2693 if (!option
->types
[i
].fields
) {
2694 talloc_free(option
);
2697 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2698 option
->types
[i
].fields
[k
] =
2699 r
->types
[i
].fields
[k
];
2707 /****************************************************************
2708 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2710 * before replying OK: status=0 a rpc call is made to the workstation
2711 * asking ReplyOpenPrinter
2713 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2714 * called from api_spoolss_rffpcnex
2715 ****************************************************************/
2717 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct
*p
,
2718 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2721 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2722 struct sockaddr_storage client_ss
;
2724 /* store the notify value in the printer struct */
2726 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2729 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2730 "Invalid handle (%s:%u:%u).\n",
2731 OUR_HANDLE(r
->in
.handle
)));
2735 Printer
->notify
.flags
= r
->in
.flags
;
2736 Printer
->notify
.options
= r
->in
.options
;
2737 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2738 Printer
->notify
.msg_ctx
= p
->msg_ctx
;
2740 TALLOC_FREE(Printer
->notify
.option
);
2741 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2743 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2745 /* Connect to the client machine and send a ReplyOpenPrinter */
2747 if ( Printer
->printer_type
== SPLHND_SERVER
)
2749 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2750 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2753 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2754 "client_address is %s\n", p
->client_id
->addr
));
2756 if (!lp_print_notify_backchannel(snum
)) {
2757 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2758 "backchannel disabled\n"));
2759 return WERR_SERVER_UNAVAILABLE
;
2762 if (!interpret_string_addr(&client_ss
, p
->client_id
->addr
,
2764 return WERR_SERVER_UNAVAILABLE
;
2767 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2768 Printer
->notify
.printerlocal
, REG_SZ
,
2769 &Printer
->notify
.cli_hnd
,
2770 &Printer
->notify
.cli_chan
,
2771 &client_ss
, p
->msg_ctx
)) {
2772 return WERR_SERVER_UNAVAILABLE
;
2778 /*******************************************************************
2779 * fill a notify_info_data with the servername
2780 ********************************************************************/
2782 static void spoolss_notify_server_name(struct messaging_context
*msg_ctx
,
2784 struct spoolss_Notify
*data
,
2785 print_queue_struct
*queue
,
2786 struct spoolss_PrinterInfo2
*pinfo2
,
2787 TALLOC_CTX
*mem_ctx
)
2789 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->servername
);
2792 /*******************************************************************
2793 * fill a notify_info_data with the printername (not including the servername).
2794 ********************************************************************/
2796 static void spoolss_notify_printer_name(struct messaging_context
*msg_ctx
,
2798 struct spoolss_Notify
*data
,
2799 print_queue_struct
*queue
,
2800 struct spoolss_PrinterInfo2
*pinfo2
,
2801 TALLOC_CTX
*mem_ctx
)
2803 /* the notify name should not contain the \\server\ part */
2804 const char *p
= strrchr(pinfo2
->printername
, '\\');
2807 p
= pinfo2
->printername
;
2812 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2815 /*******************************************************************
2816 * fill a notify_info_data with the servicename
2817 ********************************************************************/
2819 static void spoolss_notify_share_name(struct messaging_context
*msg_ctx
,
2821 struct spoolss_Notify
*data
,
2822 print_queue_struct
*queue
,
2823 struct spoolss_PrinterInfo2
*pinfo2
,
2824 TALLOC_CTX
*mem_ctx
)
2826 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2829 /*******************************************************************
2830 * fill a notify_info_data with the port name
2831 ********************************************************************/
2833 static void spoolss_notify_port_name(struct messaging_context
*msg_ctx
,
2835 struct spoolss_Notify
*data
,
2836 print_queue_struct
*queue
,
2837 struct spoolss_PrinterInfo2
*pinfo2
,
2838 TALLOC_CTX
*mem_ctx
)
2840 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->portname
);
2843 /*******************************************************************
2844 * fill a notify_info_data with the printername
2845 * but it doesn't exist, have to see what to do
2846 ********************************************************************/
2848 static void spoolss_notify_driver_name(struct messaging_context
*msg_ctx
,
2850 struct spoolss_Notify
*data
,
2851 print_queue_struct
*queue
,
2852 struct spoolss_PrinterInfo2
*pinfo2
,
2853 TALLOC_CTX
*mem_ctx
)
2855 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->drivername
);
2858 /*******************************************************************
2859 * fill a notify_info_data with the comment
2860 ********************************************************************/
2862 static void spoolss_notify_comment(struct messaging_context
*msg_ctx
,
2864 struct spoolss_Notify
*data
,
2865 print_queue_struct
*queue
,
2866 struct spoolss_PrinterInfo2
*pinfo2
,
2867 TALLOC_CTX
*mem_ctx
)
2871 if (*pinfo2
->comment
== '\0') {
2872 p
= lp_comment(snum
);
2874 p
= pinfo2
->comment
;
2877 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2880 /*******************************************************************
2881 * fill a notify_info_data with the comment
2882 * location = "Room 1, floor 2, building 3"
2883 ********************************************************************/
2885 static void spoolss_notify_location(struct messaging_context
*msg_ctx
,
2887 struct spoolss_Notify
*data
,
2888 print_queue_struct
*queue
,
2889 struct spoolss_PrinterInfo2
*pinfo2
,
2890 TALLOC_CTX
*mem_ctx
)
2892 const char *loc
= pinfo2
->location
;
2895 status
= printer_list_get_printer(mem_ctx
,
2900 if (NT_STATUS_IS_OK(status
)) {
2902 loc
= pinfo2
->location
;
2906 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, loc
);
2909 /*******************************************************************
2910 * fill a notify_info_data with the device mode
2911 * jfm:xxxx don't to it for know but that's a real problem !!!
2912 ********************************************************************/
2914 static void spoolss_notify_devmode(struct messaging_context
*msg_ctx
,
2916 struct spoolss_Notify
*data
,
2917 print_queue_struct
*queue
,
2918 struct spoolss_PrinterInfo2
*pinfo2
,
2919 TALLOC_CTX
*mem_ctx
)
2921 /* for a dummy implementation we have to zero the fields */
2922 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2925 /*******************************************************************
2926 * fill a notify_info_data with the separator file name
2927 ********************************************************************/
2929 static void spoolss_notify_sepfile(struct messaging_context
*msg_ctx
,
2931 struct spoolss_Notify
*data
,
2932 print_queue_struct
*queue
,
2933 struct spoolss_PrinterInfo2
*pinfo2
,
2934 TALLOC_CTX
*mem_ctx
)
2936 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->sepfile
);
2939 /*******************************************************************
2940 * fill a notify_info_data with the print processor
2941 * jfm:xxxx return always winprint to indicate we don't do anything to it
2942 ********************************************************************/
2944 static void spoolss_notify_print_processor(struct messaging_context
*msg_ctx
,
2946 struct spoolss_Notify
*data
,
2947 print_queue_struct
*queue
,
2948 struct spoolss_PrinterInfo2
*pinfo2
,
2949 TALLOC_CTX
*mem_ctx
)
2951 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->printprocessor
);
2954 /*******************************************************************
2955 * fill a notify_info_data with the print processor options
2956 * jfm:xxxx send an empty string
2957 ********************************************************************/
2959 static void spoolss_notify_parameters(struct messaging_context
*msg_ctx
,
2961 struct spoolss_Notify
*data
,
2962 print_queue_struct
*queue
,
2963 struct spoolss_PrinterInfo2
*pinfo2
,
2964 TALLOC_CTX
*mem_ctx
)
2966 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->parameters
);
2969 /*******************************************************************
2970 * fill a notify_info_data with the data type
2971 * jfm:xxxx always send RAW as data type
2972 ********************************************************************/
2974 static void spoolss_notify_datatype(struct messaging_context
*msg_ctx
,
2976 struct spoolss_Notify
*data
,
2977 print_queue_struct
*queue
,
2978 struct spoolss_PrinterInfo2
*pinfo2
,
2979 TALLOC_CTX
*mem_ctx
)
2981 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->datatype
);
2984 /*******************************************************************
2985 * fill a notify_info_data with the security descriptor
2986 * jfm:xxxx send an null pointer to say no security desc
2987 * have to implement security before !
2988 ********************************************************************/
2990 static void spoolss_notify_security_desc(struct messaging_context
*msg_ctx
,
2992 struct spoolss_Notify
*data
,
2993 print_queue_struct
*queue
,
2994 struct spoolss_PrinterInfo2
*pinfo2
,
2995 TALLOC_CTX
*mem_ctx
)
2997 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
, pinfo2
->secdesc
);
3000 /*******************************************************************
3001 * fill a notify_info_data with the attributes
3002 * jfm:xxxx a samba printer is always shared
3003 ********************************************************************/
3005 static void spoolss_notify_attributes(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
->attributes
);
3015 /*******************************************************************
3016 * fill a notify_info_data with the priority
3017 ********************************************************************/
3019 static void spoolss_notify_priority(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 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->priority
);
3029 /*******************************************************************
3030 * fill a notify_info_data with the default priority
3031 ********************************************************************/
3033 static void spoolss_notify_default_priority(struct messaging_context
*msg_ctx
,
3035 struct spoolss_Notify
*data
,
3036 print_queue_struct
*queue
,
3037 struct spoolss_PrinterInfo2
*pinfo2
,
3038 TALLOC_CTX
*mem_ctx
)
3040 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->defaultpriority
);
3043 /*******************************************************************
3044 * fill a notify_info_data with the start time
3045 ********************************************************************/
3047 static void spoolss_notify_start_time(struct messaging_context
*msg_ctx
,
3049 struct spoolss_Notify
*data
,
3050 print_queue_struct
*queue
,
3051 struct spoolss_PrinterInfo2
*pinfo2
,
3052 TALLOC_CTX
*mem_ctx
)
3054 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->starttime
);
3057 /*******************************************************************
3058 * fill a notify_info_data with the until time
3059 ********************************************************************/
3061 static void spoolss_notify_until_time(struct messaging_context
*msg_ctx
,
3063 struct spoolss_Notify
*data
,
3064 print_queue_struct
*queue
,
3065 struct spoolss_PrinterInfo2
*pinfo2
,
3066 TALLOC_CTX
*mem_ctx
)
3068 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->untiltime
);
3071 /*******************************************************************
3072 * fill a notify_info_data with the status
3073 ********************************************************************/
3075 static void spoolss_notify_status(struct messaging_context
*msg_ctx
,
3077 struct spoolss_Notify
*data
,
3078 print_queue_struct
*queue
,
3079 struct spoolss_PrinterInfo2
*pinfo2
,
3080 TALLOC_CTX
*mem_ctx
)
3082 print_status_struct status
;
3084 print_queue_length(msg_ctx
, snum
, &status
);
3085 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
3088 /*******************************************************************
3089 * fill a notify_info_data with the number of jobs queued
3090 ********************************************************************/
3092 static void spoolss_notify_cjobs(struct messaging_context
*msg_ctx
,
3094 struct spoolss_Notify
*data
,
3095 print_queue_struct
*queue
,
3096 struct spoolss_PrinterInfo2
*pinfo2
,
3097 TALLOC_CTX
*mem_ctx
)
3099 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3100 data
, print_queue_length(msg_ctx
, snum
, NULL
));
3103 /*******************************************************************
3104 * fill a notify_info_data with the average ppm
3105 ********************************************************************/
3107 static void spoolss_notify_average_ppm(struct messaging_context
*msg_ctx
,
3109 struct spoolss_Notify
*data
,
3110 print_queue_struct
*queue
,
3111 struct spoolss_PrinterInfo2
*pinfo2
,
3112 TALLOC_CTX
*mem_ctx
)
3114 /* always respond 8 pages per minutes */
3115 /* a little hard ! */
3116 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->averageppm
);
3119 /*******************************************************************
3120 * fill a notify_info_data with username
3121 ********************************************************************/
3123 static void spoolss_notify_username(struct messaging_context
*msg_ctx
,
3125 struct spoolss_Notify
*data
,
3126 print_queue_struct
*queue
,
3127 struct spoolss_PrinterInfo2
*pinfo2
,
3128 TALLOC_CTX
*mem_ctx
)
3130 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
3133 /*******************************************************************
3134 * fill a notify_info_data with job status
3135 ********************************************************************/
3137 static void spoolss_notify_job_status(struct messaging_context
*msg_ctx
,
3139 struct spoolss_Notify
*data
,
3140 print_queue_struct
*queue
,
3141 struct spoolss_PrinterInfo2
*pinfo2
,
3142 TALLOC_CTX
*mem_ctx
)
3144 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
3147 /*******************************************************************
3148 * fill a notify_info_data with job name
3149 ********************************************************************/
3151 static void spoolss_notify_job_name(struct messaging_context
*msg_ctx
,
3153 struct spoolss_Notify
*data
,
3154 print_queue_struct
*queue
,
3155 struct spoolss_PrinterInfo2
*pinfo2
,
3156 TALLOC_CTX
*mem_ctx
)
3158 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
3161 /*******************************************************************
3162 * fill a notify_info_data with job status
3163 ********************************************************************/
3165 static void spoolss_notify_job_status_string(struct messaging_context
*msg_ctx
,
3167 struct spoolss_Notify
*data
,
3168 print_queue_struct
*queue
,
3169 struct spoolss_PrinterInfo2
*pinfo2
,
3170 TALLOC_CTX
*mem_ctx
)
3173 * Now we're returning job status codes we just return a "" here. JRA.
3178 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3181 switch (queue
->status
) {
3186 p
= ""; /* NT provides the paused string */
3195 #endif /* NO LONGER NEEDED. */
3197 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
3200 /*******************************************************************
3201 * fill a notify_info_data with job time
3202 ********************************************************************/
3204 static void spoolss_notify_job_time(struct messaging_context
*msg_ctx
,
3206 struct spoolss_Notify
*data
,
3207 print_queue_struct
*queue
,
3208 struct spoolss_PrinterInfo2
*pinfo2
,
3209 TALLOC_CTX
*mem_ctx
)
3211 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3214 /*******************************************************************
3215 * fill a notify_info_data with job size
3216 ********************************************************************/
3218 static void spoolss_notify_job_size(struct messaging_context
*msg_ctx
,
3220 struct spoolss_Notify
*data
,
3221 print_queue_struct
*queue
,
3222 struct spoolss_PrinterInfo2
*pinfo2
,
3223 TALLOC_CTX
*mem_ctx
)
3225 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
3228 /*******************************************************************
3229 * fill a notify_info_data with page info
3230 ********************************************************************/
3231 static void spoolss_notify_total_pages(struct messaging_context
*msg_ctx
,
3233 struct spoolss_Notify
*data
,
3234 print_queue_struct
*queue
,
3235 struct spoolss_PrinterInfo2
*pinfo2
,
3236 TALLOC_CTX
*mem_ctx
)
3238 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
3241 /*******************************************************************
3242 * fill a notify_info_data with pages printed info.
3243 ********************************************************************/
3244 static void spoolss_notify_pages_printed(struct messaging_context
*msg_ctx
,
3246 struct spoolss_Notify
*data
,
3247 print_queue_struct
*queue
,
3248 struct spoolss_PrinterInfo2
*pinfo2
,
3249 TALLOC_CTX
*mem_ctx
)
3251 /* Add code when back-end tracks this */
3252 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3255 /*******************************************************************
3256 Fill a notify_info_data with job position.
3257 ********************************************************************/
3259 static void spoolss_notify_job_position(struct messaging_context
*msg_ctx
,
3261 struct spoolss_Notify
*data
,
3262 print_queue_struct
*queue
,
3263 struct spoolss_PrinterInfo2
*pinfo2
,
3264 TALLOC_CTX
*mem_ctx
)
3266 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->job
);
3269 /*******************************************************************
3270 Fill a notify_info_data with submitted time.
3271 ********************************************************************/
3273 static void spoolss_notify_submitted_time(struct messaging_context
*msg_ctx
,
3275 struct spoolss_Notify
*data
,
3276 print_queue_struct
*queue
,
3277 struct spoolss_PrinterInfo2
*pinfo2
,
3278 TALLOC_CTX
*mem_ctx
)
3280 data
->data
.string
.string
= NULL
;
3281 data
->data
.string
.size
= 0;
3283 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
3284 &data
->data
.string
.string
,
3285 &data
->data
.string
.size
);
3289 struct s_notify_info_data_table
3291 enum spoolss_NotifyType type
;
3294 enum spoolss_NotifyTable variable_type
;
3295 void (*fn
) (struct messaging_context
*msg_ctx
,
3296 int snum
, struct spoolss_Notify
*data
,
3297 print_queue_struct
*queue
,
3298 struct spoolss_PrinterInfo2
*pinfo2
,
3299 TALLOC_CTX
*mem_ctx
);
3302 /* A table describing the various print notification constants and
3303 whether the notification data is a pointer to a variable sized
3304 buffer, a one value uint32_t or a two value uint32_t. */
3306 static const struct s_notify_info_data_table notify_info_data_table
[] =
3308 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3309 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3310 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
3311 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3312 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3313 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
3314 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
3315 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3316 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
3317 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3318 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3319 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3320 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
3321 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
3322 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3323 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
3324 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3325 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3326 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
3327 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
3328 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
3329 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3330 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3331 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3332 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3333 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3334 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3335 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3336 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3337 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3338 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3339 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3340 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3341 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3342 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3343 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3344 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3345 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3346 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3347 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3348 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3349 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3350 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3351 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3352 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3353 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3354 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3355 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3356 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3359 /*******************************************************************
3360 Return the variable_type of info_data structure.
3361 ********************************************************************/
3363 static enum spoolss_NotifyTable
variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3368 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3369 if ( (notify_info_data_table
[i
].type
== type
) &&
3370 (notify_info_data_table
[i
].field
== field
) ) {
3371 return notify_info_data_table
[i
].variable_type
;
3375 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3377 return (enum spoolss_NotifyTable
) 0;
3380 /****************************************************************************
3381 ****************************************************************************/
3383 static bool search_notify(enum spoolss_NotifyType type
,
3389 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3390 if (notify_info_data_table
[i
].type
== type
&&
3391 notify_info_data_table
[i
].field
== field
&&
3392 notify_info_data_table
[i
].fn
!= NULL
) {
3401 /****************************************************************************
3402 ****************************************************************************/
3404 static void construct_info_data(struct spoolss_Notify
*info_data
,
3405 enum spoolss_NotifyType type
,
3406 uint16_t field
, int id
)
3408 info_data
->type
= type
;
3409 info_data
->field
.field
= field
;
3410 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3411 info_data
->job_id
= id
;
3414 /*******************************************************************
3416 * fill a notify_info struct with info asked
3418 ********************************************************************/
3420 static bool construct_notify_printer_info(struct messaging_context
*msg_ctx
,
3421 struct printer_handle
*print_hnd
,
3422 struct spoolss_NotifyInfo
*info
,
3423 struct spoolss_PrinterInfo2
*pinfo2
,
3425 const struct spoolss_NotifyOptionType
*option_type
,
3427 TALLOC_CTX
*mem_ctx
)
3430 enum spoolss_NotifyType type
;
3433 struct spoolss_Notify
*current_data
;
3435 type
= option_type
->type
;
3437 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3438 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3439 option_type
->count
, lp_servicename(snum
)));
3441 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3442 field
= option_type
->fields
[field_num
].field
;
3444 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3446 if (!search_notify(type
, field
, &j
) )
3449 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3450 struct spoolss_Notify
,
3452 if (info
->notifies
== NULL
) {
3453 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3457 current_data
= &info
->notifies
[info
->count
];
3459 construct_info_data(current_data
, type
, field
, id
);
3461 DEBUG(10, ("construct_notify_printer_info: "
3462 "calling [%s] snum=%d printername=[%s])\n",
3463 notify_info_data_table
[j
].name
, snum
,
3464 pinfo2
->printername
));
3466 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3467 NULL
, pinfo2
, mem_ctx
);
3475 /*******************************************************************
3477 * fill a notify_info struct with info asked
3479 ********************************************************************/
3481 static bool construct_notify_jobs_info(struct messaging_context
*msg_ctx
,
3482 print_queue_struct
*queue
,
3483 struct spoolss_NotifyInfo
*info
,
3484 struct spoolss_PrinterInfo2
*pinfo2
,
3486 const struct spoolss_NotifyOptionType
*option_type
,
3488 TALLOC_CTX
*mem_ctx
)
3491 enum spoolss_NotifyType type
;
3493 struct spoolss_Notify
*current_data
;
3495 DEBUG(4,("construct_notify_jobs_info\n"));
3497 type
= option_type
->type
;
3499 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3500 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3501 option_type
->count
));
3503 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3504 field
= option_type
->fields
[field_num
].field
;
3506 if (!search_notify(type
, field
, &j
) )
3509 info
->notifies
= TALLOC_REALLOC_ARRAY(info
, info
->notifies
,
3510 struct spoolss_Notify
,
3512 if (info
->notifies
== NULL
) {
3513 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3517 current_data
=&(info
->notifies
[info
->count
]);
3519 construct_info_data(current_data
, type
, field
, id
);
3520 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3521 queue
, pinfo2
, mem_ctx
);
3529 * JFM: The enumeration is not that simple, it's even non obvious.
3531 * let's take an example: I want to monitor the PRINTER SERVER for
3532 * the printer's name and the number of jobs currently queued.
3533 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3534 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3536 * I have 3 printers on the back of my server.
3538 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3541 * 1 printer 1 name 1
3542 * 2 printer 1 cjob 1
3543 * 3 printer 2 name 2
3544 * 4 printer 2 cjob 2
3545 * 5 printer 3 name 3
3546 * 6 printer 3 name 3
3548 * that's the print server case, the printer case is even worse.
3551 /*******************************************************************
3553 * enumerate all printers on the printserver
3554 * fill a notify_info struct with info asked
3556 ********************************************************************/
3558 static WERROR
printserver_notify_info(struct pipes_struct
*p
,
3559 struct policy_handle
*hnd
,
3560 struct spoolss_NotifyInfo
*info
,
3561 TALLOC_CTX
*mem_ctx
)
3564 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3565 int n_services
=lp_numservices();
3567 struct spoolss_NotifyOption
*option
;
3568 struct spoolss_NotifyOptionType option_type
;
3569 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3572 DEBUG(4,("printserver_notify_info\n"));
3577 option
= Printer
->notify
.option
;
3580 info
->notifies
= NULL
;
3583 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3584 sending a ffpcn() request first */
3589 for (i
=0; i
<option
->count
; i
++) {
3590 option_type
= option
->types
[i
];
3592 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3595 for (snum
= 0; snum
< n_services
; snum
++) {
3596 if (!lp_browseable(snum
) ||
3597 !lp_snum_ok(snum
) ||
3598 !lp_print_ok(snum
)) {
3599 continue; /* skip */
3602 /* Maybe we should use the SYSTEM session_info here... */
3603 result
= winreg_get_printer_internal(mem_ctx
,
3604 get_session_info_system(),
3606 lp_servicename(snum
),
3608 if (!W_ERROR_IS_OK(result
)) {
3609 DEBUG(4, ("printserver_notify_info: "
3610 "Failed to get printer [%s]\n",
3611 lp_servicename(snum
)));
3616 construct_notify_printer_info(p
->msg_ctx
,
3622 TALLOC_FREE(pinfo2
);
3628 * Debugging information, don't delete.
3631 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3632 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3633 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3635 for (i
=0; i
<info
->count
; i
++) {
3636 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3637 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3638 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3645 /*******************************************************************
3647 * fill a notify_info struct with info asked
3649 ********************************************************************/
3651 static WERROR
printer_notify_info(struct pipes_struct
*p
,
3652 struct policy_handle
*hnd
,
3653 struct spoolss_NotifyInfo
*info
,
3654 TALLOC_CTX
*mem_ctx
)
3657 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3660 struct spoolss_NotifyOption
*option
;
3661 struct spoolss_NotifyOptionType option_type
;
3663 print_queue_struct
*queue
=NULL
;
3664 print_status_struct status
;
3665 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3668 DEBUG(4,("printer_notify_info\n"));
3673 option
= Printer
->notify
.option
;
3677 info
->notifies
= NULL
;
3680 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3681 sending a ffpcn() request first */
3686 if (!get_printer_snum(p
, hnd
, &snum
, NULL
)) {
3690 /* Maybe we should use the SYSTEM session_info here... */
3691 result
= winreg_get_printer_internal(mem_ctx
,
3692 get_session_info_system(),
3694 lp_servicename(snum
), &pinfo2
);
3695 if (!W_ERROR_IS_OK(result
)) {
3700 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3701 * correct servername.
3703 pinfo2
->servername
= talloc_strdup(pinfo2
, Printer
->servername
);
3704 if (pinfo2
->servername
== NULL
) {
3708 for (i
=0; i
<option
->count
; i
++) {
3709 option_type
= option
->types
[i
];
3711 switch (option_type
.type
) {
3712 case PRINTER_NOTIFY_TYPE
:
3713 if (construct_notify_printer_info(p
->msg_ctx
,
3722 case JOB_NOTIFY_TYPE
:
3724 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
,
3727 for (j
=0; j
<count
; j
++) {
3728 construct_notify_jobs_info(p
->msg_ctx
,
3742 * Debugging information, don't delete.
3745 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3746 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3747 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3749 for (i=0; i<info->count; i++) {
3750 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3751 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3752 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3756 talloc_free(pinfo2
);
3760 /****************************************************************
3761 _spoolss_RouterRefreshPrinterChangeNotify
3762 ****************************************************************/
3764 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct
*p
,
3765 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3767 struct spoolss_NotifyInfo
*info
;
3769 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3770 WERROR result
= WERR_BADFID
;
3772 /* we always have a spoolss_NotifyInfo struct */
3773 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3775 result
= WERR_NOMEM
;
3779 *r
->out
.info
= info
;
3782 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3783 "Invalid handle (%s:%u:%u).\n",
3784 OUR_HANDLE(r
->in
.handle
)));
3788 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3791 * We are now using the change value, and
3792 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3793 * I don't have a global notification system, I'm sending back all the
3794 * information even when _NOTHING_ has changed.
3797 /* We need to keep track of the change value to send back in
3798 RRPCN replies otherwise our updates are ignored. */
3800 Printer
->notify
.fnpcn
= true;
3802 if (Printer
->notify
.cli_chan
!= NULL
&&
3803 Printer
->notify
.cli_chan
->active_connections
> 0) {
3804 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3805 "Saving change value in request [%x]\n",
3807 Printer
->notify
.change
= r
->in
.change_low
;
3810 /* just ignore the spoolss_NotifyOption */
3812 switch (Printer
->printer_type
) {
3814 result
= printserver_notify_info(p
, r
->in
.handle
,
3818 case SPLHND_PRINTER
:
3819 result
= printer_notify_info(p
, r
->in
.handle
,
3824 Printer
->notify
.fnpcn
= false;
3830 /********************************************************************
3831 ********************************************************************/
3833 static WERROR
create_printername(TALLOC_CTX
*mem_ctx
,
3834 const char *servername
,
3835 const char *printername
,
3836 const char **printername_p
)
3838 /* FIXME: add lp_force_printername() */
3840 if (servername
== NULL
) {
3841 *printername_p
= talloc_strdup(mem_ctx
, printername
);
3842 W_ERROR_HAVE_NO_MEMORY(*printername_p
);
3846 if (servername
[0] == '\\' && servername
[1] == '\\') {
3850 *printername_p
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s", servername
, printername
);
3851 W_ERROR_HAVE_NO_MEMORY(*printername_p
);
3856 /********************************************************************
3857 ********************************************************************/
3859 static void compose_devicemode_devicename(struct spoolss_DeviceMode
*dm
,
3860 const char *printername
)
3866 dm
->devicename
= talloc_strndup(dm
, printername
,
3867 MIN(strlen(printername
), 31));
3870 /********************************************************************
3871 * construct_printer_info_0
3872 * fill a printer_info_0 struct
3873 ********************************************************************/
3875 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3876 const struct auth_serversupplied_info
*session_info
,
3877 struct messaging_context
*msg_ctx
,
3878 struct spoolss_PrinterInfo2
*info2
,
3879 const char *servername
,
3880 struct spoolss_PrinterInfo0
*r
,
3884 struct printer_session_counter
*session_counter
;
3885 struct timeval setuptime
;
3886 print_status_struct status
;
3889 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
3890 if (!W_ERROR_IS_OK(result
)) {
3895 r
->servername
= talloc_strdup(mem_ctx
, servername
);
3896 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3898 r
->servername
= NULL
;
3901 count
= print_queue_length(msg_ctx
, snum
, &status
);
3903 /* check if we already have a counter for this printer */
3904 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3905 if (session_counter
->snum
== snum
)
3909 /* it's the first time, add it to the list */
3910 if (session_counter
== NULL
) {
3911 session_counter
= talloc_zero(counter_list
, struct printer_session_counter
);
3912 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3913 session_counter
->snum
= snum
;
3914 session_counter
->counter
= 0;
3915 DLIST_ADD(counter_list
, session_counter
);
3919 session_counter
->counter
++;
3925 get_startup_time(&setuptime
);
3926 init_systemtime(&r
->time
, gmtime(&setuptime
.tv_sec
));
3929 * the global_counter should be stored in a TDB as it's common to all the clients
3930 * and should be zeroed on samba startup
3932 r
->global_counter
= session_counter
->counter
;
3934 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3935 SSVAL(&r
->version
, 0, 0x0005); /* NT 5 */
3936 SSVAL(&r
->version
, 2, 0x0893); /* build 2195 */
3937 r
->free_build
= SPOOLSS_RELEASE_BUILD
;
3939 r
->max_spooling
= 0;
3940 r
->session_counter
= session_counter
->counter
;
3941 r
->num_error_out_of_paper
= 0x0;
3942 r
->num_error_not_ready
= 0x0; /* number of print failure */
3944 r
->number_of_processors
= 0x1;
3945 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3946 r
->high_part_total_bytes
= 0x0;
3948 /* ChangeID in milliseconds*/
3949 winreg_printer_get_changeid_internal(mem_ctx
, session_info
, msg_ctx
,
3950 info2
->sharename
, &r
->change_id
);
3952 r
->last_error
= WERR_OK
;
3953 r
->status
= nt_printq_status(status
.status
);
3954 r
->enumerate_network_printers
= 0x0;
3955 r
->c_setprinter
= 0x0;
3956 r
->processor_architecture
= PROCESSOR_ARCHITECTURE_INTEL
;
3957 r
->processor_level
= 0x6; /* 6 ???*/
3966 /********************************************************************
3967 * construct_printer_info1
3968 * fill a spoolss_PrinterInfo1 struct
3969 ********************************************************************/
3971 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
3972 const struct spoolss_PrinterInfo2
*info2
,
3974 const char *servername
,
3975 struct spoolss_PrinterInfo1
*r
,
3982 if (info2
->comment
== NULL
|| info2
->comment
[0] == '\0') {
3983 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3985 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
); /* saved comment */
3987 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3989 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->name
);
3990 if (!W_ERROR_IS_OK(result
)) {
3994 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
3998 W_ERROR_HAVE_NO_MEMORY(r
->description
);
4003 /********************************************************************
4004 * construct_printer_info2
4005 * fill a spoolss_PrinterInfo2 struct
4006 ********************************************************************/
4008 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
4009 struct messaging_context
*msg_ctx
,
4010 const struct spoolss_PrinterInfo2
*info2
,
4011 const char *servername
,
4012 struct spoolss_PrinterInfo2
*r
,
4016 print_status_struct status
;
4019 count
= print_queue_length(msg_ctx
, snum
, &status
);
4022 r
->servername
= talloc_strdup(mem_ctx
, servername
);
4023 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4025 r
->servername
= NULL
;
4028 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4029 if (!W_ERROR_IS_OK(result
)) {
4033 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
4034 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
4035 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
4036 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4037 r
->drivername
= talloc_strdup(mem_ctx
, info2
->drivername
);
4038 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
4040 if (info2
->comment
[0] == '\0') {
4041 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
4043 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
);
4045 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
4047 r
->location
= talloc_strdup(mem_ctx
, info2
->location
);
4048 if (info2
->location
[0] == '\0') {
4049 const char *loc
= NULL
;
4052 nt_status
= printer_list_get_printer(mem_ctx
,
4057 if (NT_STATUS_IS_OK(nt_status
)) {
4059 r
->location
= talloc_strdup(mem_ctx
, loc
);
4063 W_ERROR_HAVE_NO_MEMORY(r
->location
);
4065 r
->sepfile
= talloc_strdup(mem_ctx
, info2
->sepfile
);
4066 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
4067 r
->printprocessor
= talloc_strdup(mem_ctx
, info2
->printprocessor
);
4068 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
4069 r
->datatype
= talloc_strdup(mem_ctx
, info2
->datatype
);
4070 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
4071 r
->parameters
= talloc_strdup(mem_ctx
, info2
->parameters
);
4072 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
4074 r
->attributes
= info2
->attributes
;
4076 r
->priority
= info2
->priority
;
4077 r
->defaultpriority
= info2
->defaultpriority
;
4078 r
->starttime
= info2
->starttime
;
4079 r
->untiltime
= info2
->untiltime
;
4080 r
->status
= nt_printq_status(status
.status
);
4082 r
->averageppm
= info2
->averageppm
;
4084 copy_devicemode(mem_ctx
, info2
->devmode
, &r
->devmode
);
4086 DEBUG(8,("Returning NULL Devicemode!\n"));
4089 compose_devicemode_devicename(r
->devmode
, r
->printername
);
4093 if (info2
->secdesc
!= NULL
) {
4094 /* don't use talloc_steal() here unless you do a deep steal of all
4095 the SEC_DESC members */
4097 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
4103 /********************************************************************
4104 * construct_printer_info3
4105 * fill a spoolss_PrinterInfo3 struct
4106 ********************************************************************/
4108 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
4109 const struct spoolss_PrinterInfo2
*info2
,
4110 const char *servername
,
4111 struct spoolss_PrinterInfo3
*r
,
4114 /* These are the components of the SD we are returning. */
4116 if (info2
->secdesc
!= NULL
) {
4117 /* don't use talloc_steal() here unless you do a deep steal of all
4118 the SEC_DESC members */
4120 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
4121 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
4127 /********************************************************************
4128 * construct_printer_info4
4129 * fill a spoolss_PrinterInfo4 struct
4130 ********************************************************************/
4132 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
4133 const struct spoolss_PrinterInfo2
*info2
,
4134 const char *servername
,
4135 struct spoolss_PrinterInfo4
*r
,
4140 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4141 if (!W_ERROR_IS_OK(result
)) {
4146 r
->servername
= talloc_strdup(mem_ctx
, servername
);
4147 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4149 r
->servername
= NULL
;
4152 r
->attributes
= info2
->attributes
;
4157 /********************************************************************
4158 * construct_printer_info5
4159 * fill a spoolss_PrinterInfo5 struct
4160 ********************************************************************/
4162 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
4163 const struct spoolss_PrinterInfo2
*info2
,
4164 const char *servername
,
4165 struct spoolss_PrinterInfo5
*r
,
4170 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4171 if (!W_ERROR_IS_OK(result
)) {
4175 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
4176 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4178 r
->attributes
= info2
->attributes
;
4180 /* these two are not used by NT+ according to MSDN */
4181 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4182 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4187 /********************************************************************
4188 * construct_printer_info_6
4189 * fill a spoolss_PrinterInfo6 struct
4190 ********************************************************************/
4192 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
4193 struct messaging_context
*msg_ctx
,
4194 const struct spoolss_PrinterInfo2
*info2
,
4195 const char *servername
,
4196 struct spoolss_PrinterInfo6
*r
,
4200 print_status_struct status
;
4202 count
= print_queue_length(msg_ctx
, snum
, &status
);
4204 r
->status
= nt_printq_status(status
.status
);
4209 /********************************************************************
4210 * construct_printer_info7
4211 * fill a spoolss_PrinterInfo7 struct
4212 ********************************************************************/
4214 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
4215 struct messaging_context
*msg_ctx
,
4216 const char *servername
,
4217 struct spoolss_PrinterInfo7
*r
,
4220 struct auth_serversupplied_info
*session_info
;
4224 status
= make_session_info_system(mem_ctx
, &session_info
);
4225 if (!NT_STATUS_IS_OK(status
)) {
4226 DEBUG(0, ("construct_printer_info7: "
4227 "Could not create system session_info\n"));
4231 if (is_printer_published(mem_ctx
, session_info
, msg_ctx
,
4233 lp_servicename(snum
), &guid
, NULL
)) {
4234 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
4235 r
->action
= DSPRINT_PUBLISH
;
4237 r
->guid
= talloc_strdup(mem_ctx
, "");
4238 r
->action
= DSPRINT_UNPUBLISH
;
4240 W_ERROR_HAVE_NO_MEMORY(r
->guid
);
4242 TALLOC_FREE(session_info
);
4246 /********************************************************************
4247 * construct_printer_info8
4248 * fill a spoolss_PrinterInfo8 struct
4249 ********************************************************************/
4251 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
4252 const struct spoolss_PrinterInfo2
*info2
,
4253 const char *servername
,
4254 struct spoolss_DeviceModeInfo
*r
,
4258 const char *printername
;
4260 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &printername
);
4261 if (!W_ERROR_IS_OK(result
)) {
4265 copy_devicemode(mem_ctx
, info2
->devmode
, &r
->devmode
);
4267 DEBUG(8,("Returning NULL Devicemode!\n"));
4270 compose_devicemode_devicename(r
->devmode
, printername
);
4276 /********************************************************************
4277 ********************************************************************/
4279 static bool snum_is_shared_printer(int snum
)
4281 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
4284 /********************************************************************
4285 Spoolss_enumprinters.
4286 ********************************************************************/
4288 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
4289 const struct auth_serversupplied_info
*session_info
,
4290 struct messaging_context
*msg_ctx
,
4291 const char *servername
,
4294 union spoolss_PrinterInfo
**info_p
,
4298 int n_services
= lp_numservices();
4299 union spoolss_PrinterInfo
*info
= NULL
;
4301 WERROR result
= WERR_OK
;
4302 struct dcerpc_binding_handle
*b
= NULL
;
4307 for (snum
= 0; snum
< n_services
; snum
++) {
4309 const char *printer
;
4310 struct spoolss_PrinterInfo2
*info2
;
4312 if (!snum_is_shared_printer(snum
)) {
4316 printer
= lp_const_servicename(snum
);
4318 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4322 result
= winreg_printer_binding_handle(mem_ctx
,
4326 if (!W_ERROR_IS_OK(result
)) {
4331 result
= winreg_create_printer(mem_ctx
, b
,
4333 if (!W_ERROR_IS_OK(result
)) {
4337 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
4338 union spoolss_PrinterInfo
,
4341 result
= WERR_NOMEM
;
4345 result
= winreg_get_printer(mem_ctx
, b
,
4347 if (!W_ERROR_IS_OK(result
)) {
4353 result
= construct_printer_info0(info
, session_info
,
4356 &info
[count
].info0
, snum
);
4359 result
= construct_printer_info1(info
, info2
, flags
,
4361 &info
[count
].info1
, snum
);
4364 result
= construct_printer_info2(info
, msg_ctx
, info2
,
4366 &info
[count
].info2
, snum
);
4369 result
= construct_printer_info4(info
, info2
,
4371 &info
[count
].info4
, snum
);
4374 result
= construct_printer_info5(info
, info2
,
4376 &info
[count
].info5
, snum
);
4380 result
= WERR_UNKNOWN_LEVEL
;
4384 if (!W_ERROR_IS_OK(result
)) {
4395 if (!W_ERROR_IS_OK(result
)) {
4405 /********************************************************************
4406 * handle enumeration of printers at level 0
4407 ********************************************************************/
4409 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
4410 const struct auth_serversupplied_info
*session_info
,
4411 struct messaging_context
*msg_ctx
,
4413 const char *servername
,
4414 union spoolss_PrinterInfo
**info
,
4417 DEBUG(4,("enum_all_printers_info_0\n"));
4419 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4420 servername
, 0, flags
, info
, count
);
4424 /********************************************************************
4425 ********************************************************************/
4427 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4428 const struct auth_serversupplied_info
*session_info
,
4429 struct messaging_context
*msg_ctx
,
4430 const char *servername
,
4432 union spoolss_PrinterInfo
**info
,
4435 DEBUG(4,("enum_all_printers_info_1\n"));
4437 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4438 servername
, 1, flags
, info
, count
);
4441 /********************************************************************
4442 enum_all_printers_info_1_local.
4443 *********************************************************************/
4445 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4446 const struct auth_serversupplied_info
*session_info
,
4447 struct messaging_context
*msg_ctx
,
4448 const char *servername
,
4449 union spoolss_PrinterInfo
**info
,
4452 DEBUG(4,("enum_all_printers_info_1_local\n"));
4454 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4455 servername
, PRINTER_ENUM_ICON8
, info
, count
);
4458 /********************************************************************
4459 enum_all_printers_info_1_name.
4460 *********************************************************************/
4462 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4463 const struct auth_serversupplied_info
*session_info
,
4464 struct messaging_context
*msg_ctx
,
4465 const char *servername
,
4466 union spoolss_PrinterInfo
**info
,
4469 const char *s
= servername
;
4471 DEBUG(4,("enum_all_printers_info_1_name\n"));
4473 if ((servername
[0] == '\\') && (servername
[1] == '\\')) {
4477 if (!is_myname_or_ipaddr(s
)) {
4478 return WERR_INVALID_NAME
;
4481 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4482 servername
, PRINTER_ENUM_ICON8
, info
, count
);
4485 /********************************************************************
4486 enum_all_printers_info_1_network.
4487 *********************************************************************/
4489 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4490 const struct auth_serversupplied_info
*session_info
,
4491 struct messaging_context
*msg_ctx
,
4492 const char *servername
,
4493 union spoolss_PrinterInfo
**info
,
4496 const char *s
= servername
;
4498 DEBUG(4,("enum_all_printers_info_1_network\n"));
4500 /* If we respond to a enum_printers level 1 on our name with flags
4501 set to PRINTER_ENUM_REMOTE with a list of printers then these
4502 printers incorrectly appear in the APW browse list.
4503 Specifically the printers for the server appear at the workgroup
4504 level where all the other servers in the domain are
4505 listed. Windows responds to this call with a
4506 WERR_CAN_NOT_COMPLETE so we should do the same. */
4508 if (servername
[0] == '\\' && servername
[1] == '\\') {
4512 if (is_myname_or_ipaddr(s
)) {
4513 return WERR_CAN_NOT_COMPLETE
;
4516 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4517 servername
, PRINTER_ENUM_NAME
, info
, count
);
4520 /********************************************************************
4521 * api_spoolss_enumprinters
4523 * called from api_spoolss_enumprinters (see this to understand)
4524 ********************************************************************/
4526 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4527 const struct auth_serversupplied_info
*session_info
,
4528 struct messaging_context
*msg_ctx
,
4529 const char *servername
,
4530 union spoolss_PrinterInfo
**info
,
4533 DEBUG(4,("enum_all_printers_info_2\n"));
4535 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4536 servername
, 2, 0, info
, count
);
4539 /********************************************************************
4540 * handle enumeration of printers at level 1
4541 ********************************************************************/
4543 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4544 const struct auth_serversupplied_info
*session_info
,
4545 struct messaging_context
*msg_ctx
,
4547 const char *servername
,
4548 union spoolss_PrinterInfo
**info
,
4551 /* Not all the flags are equals */
4553 if (flags
& PRINTER_ENUM_LOCAL
) {
4554 return enum_all_printers_info_1_local(mem_ctx
, session_info
,
4555 msg_ctx
, servername
, info
, count
);
4558 if (flags
& PRINTER_ENUM_NAME
) {
4559 return enum_all_printers_info_1_name(mem_ctx
, session_info
,
4560 msg_ctx
, servername
, info
,
4564 if (flags
& PRINTER_ENUM_NETWORK
) {
4565 return enum_all_printers_info_1_network(mem_ctx
, session_info
,
4566 msg_ctx
, servername
, info
,
4570 return WERR_OK
; /* NT4sp5 does that */
4573 /********************************************************************
4574 * handle enumeration of printers at level 2
4575 ********************************************************************/
4577 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4578 const struct auth_serversupplied_info
*session_info
,
4579 struct messaging_context
*msg_ctx
,
4581 const char *servername
,
4582 union spoolss_PrinterInfo
**info
,
4585 if (flags
& PRINTER_ENUM_LOCAL
) {
4587 return enum_all_printers_info_2(mem_ctx
, session_info
, msg_ctx
,
4592 if (flags
& PRINTER_ENUM_NAME
) {
4593 if (servername
&& !is_myname_or_ipaddr(canon_servername(servername
))) {
4594 return WERR_INVALID_NAME
;
4597 return enum_all_printers_info_2(mem_ctx
, session_info
, msg_ctx
,
4602 if (flags
& PRINTER_ENUM_REMOTE
) {
4603 return WERR_UNKNOWN_LEVEL
;
4609 /********************************************************************
4610 * handle enumeration of printers at level 4
4611 ********************************************************************/
4613 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4614 const struct auth_serversupplied_info
*session_info
,
4615 struct messaging_context
*msg_ctx
,
4617 const char *servername
,
4618 union spoolss_PrinterInfo
**info
,
4621 DEBUG(4,("enum_all_printers_info_4\n"));
4623 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4624 servername
, 4, flags
, info
, count
);
4628 /********************************************************************
4629 * handle enumeration of printers at level 5
4630 ********************************************************************/
4632 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4633 const struct auth_serversupplied_info
*session_info
,
4634 struct messaging_context
*msg_ctx
,
4636 const char *servername
,
4637 union spoolss_PrinterInfo
**info
,
4640 DEBUG(4,("enum_all_printers_info_5\n"));
4642 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4643 servername
, 5, flags
, info
, count
);
4646 /****************************************************************
4647 _spoolss_EnumPrinters
4648 ****************************************************************/
4650 WERROR
_spoolss_EnumPrinters(struct pipes_struct
*p
,
4651 struct spoolss_EnumPrinters
*r
)
4653 const struct auth_serversupplied_info
*session_info
= get_session_info_system();
4656 /* that's an [in out] buffer */
4658 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4659 return WERR_INVALID_PARAM
;
4662 DEBUG(4,("_spoolss_EnumPrinters\n"));
4666 *r
->out
.info
= NULL
;
4670 * flags==PRINTER_ENUM_NAME
4671 * if name=="" then enumerates all printers
4672 * if name!="" then enumerate the printer
4673 * flags==PRINTER_ENUM_REMOTE
4674 * name is NULL, enumerate printers
4675 * Level 2: name!="" enumerates printers, name can't be NULL
4676 * Level 3: doesn't exist
4677 * Level 4: does a local registry lookup
4678 * Level 5: same as Level 2
4681 if (r
->in
.server
&& r
->in
.server
[0] == '\0') {
4682 r
->in
.server
= NULL
;
4685 switch (r
->in
.level
) {
4687 result
= enumprinters_level0(p
->mem_ctx
, session_info
,
4688 p
->msg_ctx
, r
->in
.flags
,
4690 r
->out
.info
, r
->out
.count
);
4693 result
= enumprinters_level1(p
->mem_ctx
, session_info
,
4694 p
->msg_ctx
, r
->in
.flags
,
4696 r
->out
.info
, r
->out
.count
);
4699 result
= enumprinters_level2(p
->mem_ctx
, session_info
,
4700 p
->msg_ctx
, r
->in
.flags
,
4702 r
->out
.info
, r
->out
.count
);
4705 result
= enumprinters_level4(p
->mem_ctx
, session_info
,
4706 p
->msg_ctx
, r
->in
.flags
,
4708 r
->out
.info
, r
->out
.count
);
4711 result
= enumprinters_level5(p
->mem_ctx
, session_info
,
4712 p
->msg_ctx
, r
->in
.flags
,
4714 r
->out
.info
, r
->out
.count
);
4717 return WERR_UNKNOWN_LEVEL
;
4720 if (!W_ERROR_IS_OK(result
)) {
4724 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4725 spoolss_EnumPrinters
,
4726 *r
->out
.info
, r
->in
.level
,
4728 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4729 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4731 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4734 /****************************************************************
4736 ****************************************************************/
4738 WERROR
_spoolss_GetPrinter(struct pipes_struct
*p
,
4739 struct spoolss_GetPrinter
*r
)
4741 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4742 struct spoolss_PrinterInfo2
*info2
= NULL
;
4743 WERROR result
= WERR_OK
;
4746 /* that's an [in out] buffer */
4748 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4749 return WERR_INVALID_PARAM
;
4754 if (Printer
== NULL
) {
4758 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4762 result
= winreg_get_printer_internal(p
->mem_ctx
,
4763 get_session_info_system(),
4765 lp_const_servicename(snum
),
4767 if (!W_ERROR_IS_OK(result
)) {
4771 switch (r
->in
.level
) {
4773 result
= construct_printer_info0(p
->mem_ctx
,
4774 get_session_info_system(),
4777 Printer
->servername
,
4778 &r
->out
.info
->info0
,
4782 result
= construct_printer_info1(p
->mem_ctx
, info2
,
4784 Printer
->servername
,
4785 &r
->out
.info
->info1
, snum
);
4788 result
= construct_printer_info2(p
->mem_ctx
, p
->msg_ctx
, info2
,
4789 Printer
->servername
,
4790 &r
->out
.info
->info2
, snum
);
4793 result
= construct_printer_info3(p
->mem_ctx
, info2
,
4794 Printer
->servername
,
4795 &r
->out
.info
->info3
, snum
);
4798 result
= construct_printer_info4(p
->mem_ctx
, info2
,
4799 Printer
->servername
,
4800 &r
->out
.info
->info4
, snum
);
4803 result
= construct_printer_info5(p
->mem_ctx
, info2
,
4804 Printer
->servername
,
4805 &r
->out
.info
->info5
, snum
);
4808 result
= construct_printer_info6(p
->mem_ctx
, p
->msg_ctx
, info2
,
4809 Printer
->servername
,
4810 &r
->out
.info
->info6
, snum
);
4813 result
= construct_printer_info7(p
->mem_ctx
, p
->msg_ctx
,
4814 Printer
->servername
,
4815 &r
->out
.info
->info7
, snum
);
4818 result
= construct_printer_info8(p
->mem_ctx
, info2
,
4819 Printer
->servername
,
4820 &r
->out
.info
->info8
, snum
);
4823 result
= WERR_UNKNOWN_LEVEL
;
4828 if (!W_ERROR_IS_OK(result
)) {
4829 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4830 r
->in
.level
, win_errstr(result
)));
4831 TALLOC_FREE(r
->out
.info
);
4835 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
,
4836 r
->out
.info
, r
->in
.level
);
4837 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4839 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4842 /********************************************************************
4843 ********************************************************************/
4845 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4847 if (in && strlen(in)) { \
4848 out = talloc_strdup(mem_ctx, in); \
4850 out = talloc_strdup(mem_ctx, ""); \
4852 W_ERROR_HAVE_NO_MEMORY(out); \
4855 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4857 if (in && strlen(in)) { \
4858 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4860 out = talloc_strdup(mem_ctx, ""); \
4862 W_ERROR_HAVE_NO_MEMORY(out); \
4865 static WERROR
string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4866 const char **string_array
,
4867 const char ***presult
,
4868 const char *cservername
,
4872 int i
, num_strings
= 0;
4873 const char **array
= NULL
;
4875 if (string_array
== NULL
) {
4876 return WERR_INVALID_PARAMETER
;
4879 for (i
=0; string_array
[i
] && string_array
[i
][0] != '\0'; i
++) {
4880 const char *str
= NULL
;
4882 if (cservername
== NULL
|| arch
== NULL
) {
4883 FILL_DRIVER_STRING(mem_ctx
, string_array
[i
], str
);
4885 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
, arch
, version
, string_array
[i
], str
);
4888 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4895 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4896 &array
, &num_strings
);
4906 /********************************************************************
4907 * fill a spoolss_DriverInfo1 struct
4908 ********************************************************************/
4910 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4911 struct spoolss_DriverInfo1
*r
,
4912 const struct spoolss_DriverInfo8
*driver
,
4913 const char *servername
)
4915 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4916 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4921 /********************************************************************
4922 * fill a spoolss_DriverInfo2 struct
4923 ********************************************************************/
4925 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4926 struct spoolss_DriverInfo2
*r
,
4927 const struct spoolss_DriverInfo8
*driver
,
4928 const char *servername
)
4931 const char *cservername
= canon_servername(servername
);
4933 r
->version
= driver
->version
;
4935 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4936 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4937 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4938 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4940 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4941 driver
->architecture
,
4943 driver
->driver_path
,
4946 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4947 driver
->architecture
,
4952 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4953 driver
->architecture
,
4955 driver
->config_file
,
4961 /********************************************************************
4962 * fill a spoolss_DriverInfo3 struct
4963 ********************************************************************/
4965 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4966 struct spoolss_DriverInfo3
*r
,
4967 const struct spoolss_DriverInfo8
*driver
,
4968 const char *servername
)
4970 const char *cservername
= canon_servername(servername
);
4972 r
->version
= driver
->version
;
4974 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4975 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4976 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4977 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4979 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4980 driver
->architecture
,
4982 driver
->driver_path
,
4985 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4986 driver
->architecture
,
4991 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4992 driver
->architecture
,
4994 driver
->config_file
,
4997 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4998 driver
->architecture
,
5003 FILL_DRIVER_STRING(mem_ctx
,
5004 driver
->monitor_name
,
5007 FILL_DRIVER_STRING(mem_ctx
,
5008 driver
->default_datatype
,
5009 r
->default_datatype
);
5011 return string_array_from_driver_info(mem_ctx
,
5012 driver
->dependent_files
,
5013 &r
->dependent_files
,
5015 driver
->architecture
,
5019 /********************************************************************
5020 * fill a spoolss_DriverInfo4 struct
5021 ********************************************************************/
5023 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
5024 struct spoolss_DriverInfo4
*r
,
5025 const struct spoolss_DriverInfo8
*driver
,
5026 const char *servername
)
5028 const char *cservername
= canon_servername(servername
);
5031 r
->version
= driver
->version
;
5033 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5034 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5035 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5036 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5038 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5039 driver
->architecture
,
5041 driver
->driver_path
,
5044 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5045 driver
->architecture
,
5050 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5051 driver
->architecture
,
5053 driver
->config_file
,
5056 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5057 driver
->architecture
,
5062 result
= string_array_from_driver_info(mem_ctx
,
5063 driver
->dependent_files
,
5064 &r
->dependent_files
,
5066 driver
->architecture
,
5068 if (!W_ERROR_IS_OK(result
)) {
5072 FILL_DRIVER_STRING(mem_ctx
,
5073 driver
->monitor_name
,
5076 FILL_DRIVER_STRING(mem_ctx
,
5077 driver
->default_datatype
,
5078 r
->default_datatype
);
5081 result
= string_array_from_driver_info(mem_ctx
,
5082 driver
->previous_names
,
5089 /********************************************************************
5090 * fill a spoolss_DriverInfo5 struct
5091 ********************************************************************/
5093 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
5094 struct spoolss_DriverInfo5
*r
,
5095 const struct spoolss_DriverInfo8
*driver
,
5096 const char *servername
)
5098 const char *cservername
= canon_servername(servername
);
5100 r
->version
= driver
->version
;
5102 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5103 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5104 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5105 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5107 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5108 driver
->architecture
,
5110 driver
->driver_path
,
5113 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5114 driver
->architecture
,
5119 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5120 driver
->architecture
,
5122 driver
->config_file
,
5125 r
->driver_attributes
= 0;
5126 r
->config_version
= 0;
5127 r
->driver_version
= 0;
5131 /********************************************************************
5132 * fill a spoolss_DriverInfo6 struct
5133 ********************************************************************/
5135 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
5136 struct spoolss_DriverInfo6
*r
,
5137 const struct spoolss_DriverInfo8
*driver
,
5138 const char *servername
)
5140 const char *cservername
= canon_servername(servername
);
5143 r
->version
= driver
->version
;
5145 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5146 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5147 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5148 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5150 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5151 driver
->architecture
,
5153 driver
->driver_path
,
5156 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5157 driver
->architecture
,
5162 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5163 driver
->architecture
,
5165 driver
->config_file
,
5168 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5169 driver
->architecture
,
5174 FILL_DRIVER_STRING(mem_ctx
,
5175 driver
->monitor_name
,
5178 FILL_DRIVER_STRING(mem_ctx
,
5179 driver
->default_datatype
,
5180 r
->default_datatype
);
5182 result
= string_array_from_driver_info(mem_ctx
,
5183 driver
->dependent_files
,
5184 &r
->dependent_files
,
5186 driver
->architecture
,
5188 if (!W_ERROR_IS_OK(result
)) {
5192 result
= string_array_from_driver_info(mem_ctx
,
5193 driver
->previous_names
,
5196 if (!W_ERROR_IS_OK(result
)) {
5200 r
->driver_date
= driver
->driver_date
;
5201 r
->driver_version
= driver
->driver_version
;
5203 FILL_DRIVER_STRING(mem_ctx
,
5204 driver
->manufacturer_name
,
5205 r
->manufacturer_name
);
5206 FILL_DRIVER_STRING(mem_ctx
,
5207 driver
->manufacturer_url
,
5208 r
->manufacturer_url
);
5209 FILL_DRIVER_STRING(mem_ctx
,
5210 driver
->hardware_id
,
5212 FILL_DRIVER_STRING(mem_ctx
,
5219 /********************************************************************
5220 * fill a spoolss_DriverInfo8 struct
5221 ********************************************************************/
5223 static WERROR
fill_printer_driver_info8(TALLOC_CTX
*mem_ctx
,
5224 struct spoolss_DriverInfo8
*r
,
5225 const struct spoolss_DriverInfo8
*driver
,
5226 const char *servername
)
5228 const char *cservername
= canon_servername(servername
);
5231 r
->version
= driver
->version
;
5233 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5234 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5235 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5236 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5238 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5239 driver
->architecture
,
5241 driver
->driver_path
,
5244 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5245 driver
->architecture
,
5250 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5251 driver
->architecture
,
5253 driver
->config_file
,
5256 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5257 driver
->architecture
,
5262 FILL_DRIVER_STRING(mem_ctx
,
5263 driver
->monitor_name
,
5266 FILL_DRIVER_STRING(mem_ctx
,
5267 driver
->default_datatype
,
5268 r
->default_datatype
);
5270 result
= string_array_from_driver_info(mem_ctx
,
5271 driver
->dependent_files
,
5272 &r
->dependent_files
,
5274 driver
->architecture
,
5276 if (!W_ERROR_IS_OK(result
)) {
5280 result
= string_array_from_driver_info(mem_ctx
,
5281 driver
->previous_names
,
5284 if (!W_ERROR_IS_OK(result
)) {
5288 r
->driver_date
= driver
->driver_date
;
5289 r
->driver_version
= driver
->driver_version
;
5291 FILL_DRIVER_STRING(mem_ctx
,
5292 driver
->manufacturer_name
,
5293 r
->manufacturer_name
);
5294 FILL_DRIVER_STRING(mem_ctx
,
5295 driver
->manufacturer_url
,
5296 r
->manufacturer_url
);
5297 FILL_DRIVER_STRING(mem_ctx
,
5298 driver
->hardware_id
,
5300 FILL_DRIVER_STRING(mem_ctx
,
5304 FILL_DRIVER_STRING(mem_ctx
,
5305 driver
->print_processor
,
5306 r
->print_processor
);
5307 FILL_DRIVER_STRING(mem_ctx
,
5308 driver
->vendor_setup
,
5311 result
= string_array_from_driver_info(mem_ctx
,
5312 driver
->color_profiles
,
5315 if (!W_ERROR_IS_OK(result
)) {
5319 FILL_DRIVER_STRING(mem_ctx
,
5323 r
->printer_driver_attributes
= driver
->printer_driver_attributes
;
5325 result
= string_array_from_driver_info(mem_ctx
,
5326 driver
->core_driver_dependencies
,
5327 &r
->core_driver_dependencies
,
5329 if (!W_ERROR_IS_OK(result
)) {
5333 r
->min_inbox_driver_ver_date
= driver
->min_inbox_driver_ver_date
;
5334 r
->min_inbox_driver_ver_version
= driver
->min_inbox_driver_ver_version
;
5339 #if 0 /* disabled until marshalling issues are resolved - gd */
5340 /********************************************************************
5341 ********************************************************************/
5343 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
5344 struct spoolss_DriverFileInfo
*r
,
5345 const char *cservername
,
5346 const char *file_name
,
5347 enum spoolss_DriverFileType file_type
,
5348 uint32_t file_version
)
5350 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
5351 cservername
, file_name
);
5352 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
5353 r
->file_type
= file_type
;
5354 r
->file_version
= file_version
;
5359 /********************************************************************
5360 ********************************************************************/
5362 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
5363 const struct spoolss_DriverInfo8
*driver
,
5364 const char *cservername
,
5365 struct spoolss_DriverFileInfo
**info_p
,
5368 struct spoolss_DriverFileInfo
*info
= NULL
;
5376 if (strlen(driver
->driver_path
)) {
5377 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5378 struct spoolss_DriverFileInfo
,
5380 W_ERROR_HAVE_NO_MEMORY(info
);
5381 result
= fill_spoolss_DriverFileInfo(info
,
5384 driver
->driver_path
,
5385 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
5387 W_ERROR_NOT_OK_RETURN(result
);
5391 if (strlen(driver
->config_file
)) {
5392 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5393 struct spoolss_DriverFileInfo
,
5395 W_ERROR_HAVE_NO_MEMORY(info
);
5396 result
= fill_spoolss_DriverFileInfo(info
,
5399 driver
->config_file
,
5400 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
5402 W_ERROR_NOT_OK_RETURN(result
);
5406 if (strlen(driver
->data_file
)) {
5407 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5408 struct spoolss_DriverFileInfo
,
5410 W_ERROR_HAVE_NO_MEMORY(info
);
5411 result
= fill_spoolss_DriverFileInfo(info
,
5415 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
5417 W_ERROR_NOT_OK_RETURN(result
);
5421 if (strlen(driver
->help_file
)) {
5422 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5423 struct spoolss_DriverFileInfo
,
5425 W_ERROR_HAVE_NO_MEMORY(info
);
5426 result
= fill_spoolss_DriverFileInfo(info
,
5430 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
5432 W_ERROR_NOT_OK_RETURN(result
);
5436 for (i
=0; driver
->dependent_files
[i
] && driver
->dependent_files
[i
][0] != '\0'; i
++) {
5437 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
5438 struct spoolss_DriverFileInfo
,
5440 W_ERROR_HAVE_NO_MEMORY(info
);
5441 result
= fill_spoolss_DriverFileInfo(info
,
5444 driver
->dependent_files
[i
],
5445 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
5447 W_ERROR_NOT_OK_RETURN(result
);
5457 /********************************************************************
5458 * fill a spoolss_DriverInfo101 struct
5459 ********************************************************************/
5461 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
5462 struct spoolss_DriverInfo101
*r
,
5463 const struct spoolss_DriverInfo8
*driver
,
5464 const char *servername
)
5466 const char *cservername
= canon_servername(servername
);
5469 r
->version
= driver
->version
;
5471 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5472 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5473 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5474 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5476 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
5480 if (!W_ERROR_IS_OK(result
)) {
5484 FILL_DRIVER_STRING(mem_ctx
,
5485 driver
->monitor_name
,
5488 FILL_DRIVER_STRING(mem_ctx
,
5489 driver
->default_datatype
,
5490 r
->default_datatype
);
5492 result
= string_array_from_driver_info(mem_ctx
,
5493 driver
->previous_names
,
5496 if (!W_ERROR_IS_OK(result
)) {
5500 r
->driver_date
= driver
->driver_date
;
5501 r
->driver_version
= driver
->driver_version
;
5503 FILL_DRIVER_STRING(mem_ctx
,
5504 driver
->manufacturer_name
,
5505 r
->manufacturer_name
);
5506 FILL_DRIVER_STRING(mem_ctx
,
5507 driver
->manufacturer_url
,
5508 r
->manufacturer_url
);
5509 FILL_DRIVER_STRING(mem_ctx
,
5510 driver
->hardware_id
,
5512 FILL_DRIVER_STRING(mem_ctx
,
5519 /********************************************************************
5520 ********************************************************************/
5522 static WERROR
construct_printer_driver_info_level(TALLOC_CTX
*mem_ctx
,
5523 const struct auth_serversupplied_info
*session_info
,
5524 struct messaging_context
*msg_ctx
,
5526 union spoolss_DriverInfo
*r
,
5528 const char *servername
,
5529 const char *architecture
,
5532 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
5533 struct spoolss_DriverInfo8
*driver
;
5535 struct dcerpc_binding_handle
*b
;
5538 return WERR_UNKNOWN_LEVEL
;
5541 result
= winreg_printer_binding_handle(mem_ctx
,
5545 if (!W_ERROR_IS_OK(result
)) {
5549 result
= winreg_get_printer(mem_ctx
, b
,
5550 lp_const_servicename(snum
),
5553 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5554 win_errstr(result
)));
5556 if (!W_ERROR_IS_OK(result
)) {
5557 return WERR_INVALID_PRINTER_NAME
;
5560 result
= winreg_get_driver(mem_ctx
, b
,
5562 pinfo2
->drivername
, version
, &driver
);
5564 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5565 win_errstr(result
)));
5567 if (!W_ERROR_IS_OK(result
)) {
5569 * Is this a W2k client ?
5573 talloc_free(pinfo2
);
5574 return WERR_UNKNOWN_PRINTER_DRIVER
;
5577 /* Yes - try again with a WinNT driver. */
5579 result
= winreg_get_driver(mem_ctx
, b
,
5583 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5584 win_errstr(result
)));
5585 if (!W_ERROR_IS_OK(result
)) {
5586 talloc_free(pinfo2
);
5587 return WERR_UNKNOWN_PRINTER_DRIVER
;
5593 result
= fill_printer_driver_info1(mem_ctx
, &r
->info1
, driver
, servername
);
5596 result
= fill_printer_driver_info2(mem_ctx
, &r
->info2
, driver
, servername
);
5599 result
= fill_printer_driver_info3(mem_ctx
, &r
->info3
, driver
, servername
);
5602 result
= fill_printer_driver_info4(mem_ctx
, &r
->info4
, driver
, servername
);
5605 result
= fill_printer_driver_info5(mem_ctx
, &r
->info5
, driver
, servername
);
5608 result
= fill_printer_driver_info6(mem_ctx
, &r
->info6
, driver
, servername
);
5611 result
= fill_printer_driver_info8(mem_ctx
, &r
->info8
, driver
, servername
);
5613 #if 0 /* disabled until marshalling issues are resolved - gd */
5615 result
= fill_printer_driver_info101(mem_ctx
, &r
->info101
, driver
, servername
);
5619 result
= WERR_UNKNOWN_LEVEL
;
5623 talloc_free(pinfo2
);
5624 talloc_free(driver
);
5629 /****************************************************************
5630 _spoolss_GetPrinterDriver2
5631 ****************************************************************/
5633 WERROR
_spoolss_GetPrinterDriver2(struct pipes_struct
*p
,
5634 struct spoolss_GetPrinterDriver2
*r
)
5636 struct printer_handle
*printer
;
5641 /* that's an [in out] buffer */
5643 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5644 return WERR_INVALID_PARAM
;
5647 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5649 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5650 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5651 return WERR_INVALID_PRINTER_NAME
;
5655 *r
->out
.server_major_version
= 0;
5656 *r
->out
.server_minor_version
= 0;
5658 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5662 result
= construct_printer_driver_info_level(p
->mem_ctx
,
5663 get_session_info_system(),
5665 r
->in
.level
, r
->out
.info
,
5666 snum
, printer
->servername
,
5668 r
->in
.client_major_version
);
5669 if (!W_ERROR_IS_OK(result
)) {
5670 TALLOC_FREE(r
->out
.info
);
5674 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
,
5675 r
->out
.info
, r
->in
.level
);
5676 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5678 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5682 /****************************************************************
5683 _spoolss_StartPagePrinter
5684 ****************************************************************/
5686 WERROR
_spoolss_StartPagePrinter(struct pipes_struct
*p
,
5687 struct spoolss_StartPagePrinter
*r
)
5689 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5692 DEBUG(3,("_spoolss_StartPagePrinter: "
5693 "Error in startpageprinter printer handle\n"));
5697 Printer
->page_started
= true;
5701 /****************************************************************
5702 _spoolss_EndPagePrinter
5703 ****************************************************************/
5705 WERROR
_spoolss_EndPagePrinter(struct pipes_struct
*p
,
5706 struct spoolss_EndPagePrinter
*r
)
5710 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5713 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5714 OUR_HANDLE(r
->in
.handle
)));
5718 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5721 Printer
->page_started
= false;
5722 print_job_endpage(p
->msg_ctx
, snum
, Printer
->jobid
);
5727 /****************************************************************
5728 _spoolss_StartDocPrinter
5729 ****************************************************************/
5731 WERROR
_spoolss_StartDocPrinter(struct pipes_struct
*p
,
5732 struct spoolss_StartDocPrinter
*r
)
5734 struct spoolss_DocumentInfo1
*info_1
;
5736 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5740 DEBUG(2,("_spoolss_StartDocPrinter: "
5741 "Invalid handle (%s:%u:%u)\n",
5742 OUR_HANDLE(r
->in
.handle
)));
5746 if (Printer
->jobid
) {
5747 DEBUG(2, ("_spoolss_StartDocPrinter: "
5748 "StartDocPrinter called twice! "
5749 "(existing jobid = %d)\n", Printer
->jobid
));
5750 return WERR_INVALID_HANDLE
;
5753 if (r
->in
.level
!= 1) {
5754 return WERR_UNKNOWN_LEVEL
;
5757 info_1
= r
->in
.info
.info1
;
5760 * a nice thing with NT is it doesn't listen to what you tell it.
5761 * when asked to send _only_ RAW datas, it tries to send datas
5764 * So I add checks like in NT Server ...
5767 if (info_1
->datatype
) {
5768 if (strcmp(info_1
->datatype
, "RAW") != 0) {
5770 return WERR_INVALID_DATATYPE
;
5774 /* get the share number of the printer */
5775 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5779 werr
= print_job_start(p
->session_info
,
5783 info_1
->document_name
,
5784 info_1
->output_file
,
5788 /* An error occured in print_job_start() so return an appropriate
5791 if (!W_ERROR_IS_OK(werr
)) {
5795 Printer
->document_started
= true;
5796 *r
->out
.job_id
= Printer
->jobid
;
5801 /****************************************************************
5802 _spoolss_EndDocPrinter
5803 ****************************************************************/
5805 WERROR
_spoolss_EndDocPrinter(struct pipes_struct
*p
,
5806 struct spoolss_EndDocPrinter
*r
)
5808 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5813 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5814 OUR_HANDLE(r
->in
.handle
)));
5818 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5822 Printer
->document_started
= false;
5823 status
= print_job_end(p
->msg_ctx
, snum
, Printer
->jobid
, NORMAL_CLOSE
);
5824 if (!NT_STATUS_IS_OK(status
)) {
5825 DEBUG(2, ("_spoolss_EndDocPrinter: "
5826 "print_job_end failed [%s]\n",
5827 nt_errstr(status
)));
5831 return ntstatus_to_werror(status
);
5834 /****************************************************************
5835 _spoolss_WritePrinter
5836 ****************************************************************/
5838 WERROR
_spoolss_WritePrinter(struct pipes_struct
*p
,
5839 struct spoolss_WritePrinter
*r
)
5841 ssize_t buffer_written
;
5843 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5846 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5847 OUR_HANDLE(r
->in
.handle
)));
5848 *r
->out
.num_written
= r
->in
._data_size
;
5852 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5855 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5856 buffer_written
= print_job_write(server_event_context(),p
->msg_ctx
,
5857 snum
, Printer
->jobid
,
5858 (const char *)r
->in
.data
.data
,
5859 (size_t)r
->in
._data_size
);
5860 if (buffer_written
== (ssize_t
)-1) {
5861 *r
->out
.num_written
= 0;
5862 if (errno
== ENOSPC
)
5863 return WERR_NO_SPOOL_SPACE
;
5865 return WERR_ACCESS_DENIED
;
5868 *r
->out
.num_written
= r
->in
._data_size
;
5873 /********************************************************************
5874 * api_spoolss_getprinter
5875 * called from the spoolss dispatcher
5877 ********************************************************************/
5879 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5880 struct pipes_struct
*p
)
5882 const struct auth_serversupplied_info
*session_info
= p
->session_info
;
5884 WERROR errcode
= WERR_BADFUNC
;
5885 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
5888 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5889 OUR_HANDLE(handle
)));
5893 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5897 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5898 errcode
= print_queue_pause(session_info
, p
->msg_ctx
, snum
);
5900 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5901 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5902 errcode
= print_queue_resume(session_info
, p
->msg_ctx
, snum
);
5904 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5905 errcode
= print_queue_purge(session_info
, p
->msg_ctx
, snum
);
5908 return WERR_UNKNOWN_LEVEL
;
5915 /****************************************************************
5916 _spoolss_AbortPrinter
5917 * From MSDN: "Deletes printer's spool file if printer is configured
5919 ****************************************************************/
5921 WERROR
_spoolss_AbortPrinter(struct pipes_struct
*p
,
5922 struct spoolss_AbortPrinter
*r
)
5924 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5926 WERROR errcode
= WERR_OK
;
5929 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5930 OUR_HANDLE(r
->in
.handle
)));
5934 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5937 if (!Printer
->document_started
) {
5938 return WERR_SPL_NO_STARTDOC
;
5941 errcode
= print_job_delete(p
->session_info
,
5949 /********************************************************************
5950 * called by spoolss_api_setprinter
5951 * when updating a printer description
5952 ********************************************************************/
5954 static WERROR
update_printer_sec(struct policy_handle
*handle
,
5955 struct pipes_struct
*p
,
5956 struct sec_desc_buf
*secdesc_ctr
)
5958 struct spoolss_security_descriptor
*new_secdesc
= NULL
;
5959 struct spoolss_security_descriptor
*old_secdesc
= NULL
;
5960 const char *printer
;
5963 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
5964 struct dcerpc_binding_handle
*b
;
5966 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5967 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5968 OUR_HANDLE(handle
)));
5970 result
= WERR_BADFID
;
5974 if (secdesc_ctr
== NULL
) {
5975 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5976 result
= WERR_INVALID_PARAM
;
5979 printer
= lp_const_servicename(snum
);
5981 /* Check the user has permissions to change the security
5982 descriptor. By experimentation with two NT machines, the user
5983 requires Full Access to the printer to change security
5986 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5987 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5988 result
= WERR_ACCESS_DENIED
;
5992 result
= winreg_printer_binding_handle(p
->mem_ctx
,
5993 get_session_info_system(),
5996 if (!W_ERROR_IS_OK(result
)) {
6000 /* NT seems to like setting the security descriptor even though
6001 nothing may have actually changed. */
6002 result
= winreg_get_printer_secdesc(p
->mem_ctx
, b
,
6005 if (!W_ERROR_IS_OK(result
)) {
6006 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6007 result
= WERR_BADFID
;
6011 if (DEBUGLEVEL
>= 10) {
6012 struct security_acl
*the_acl
;
6015 the_acl
= old_secdesc
->dacl
;
6016 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6017 printer
, the_acl
->num_aces
));
6019 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6020 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6021 &the_acl
->aces
[i
].trustee
),
6022 the_acl
->aces
[i
].access_mask
));
6025 the_acl
= secdesc_ctr
->sd
->dacl
;
6028 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6029 printer
, the_acl
->num_aces
));
6031 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6032 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6033 &the_acl
->aces
[i
].trustee
),
6034 the_acl
->aces
[i
].access_mask
));
6037 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6041 new_secdesc
= sec_desc_merge(p
->mem_ctx
, secdesc_ctr
->sd
, old_secdesc
);
6042 if (new_secdesc
== NULL
) {
6043 result
= WERR_NOMEM
;
6047 if (security_descriptor_equal(new_secdesc
, old_secdesc
)) {
6052 result
= winreg_set_printer_secdesc(p
->mem_ctx
, b
,
6060 /********************************************************************
6061 Canonicalize printer info from a client
6062 ********************************************************************/
6064 static bool check_printer_ok(TALLOC_CTX
*mem_ctx
,
6065 struct spoolss_SetPrinterInfo2
*info2
,
6068 fstring printername
;
6071 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6072 "portname=%s drivername=%s comment=%s location=%s\n",
6073 info2
->servername
, info2
->printername
, info2
->sharename
,
6074 info2
->portname
, info2
->drivername
, info2
->comment
,
6077 /* we force some elements to "correct" values */
6078 info2
->servername
= talloc_asprintf(mem_ctx
, "\\\\%s", global_myname());
6079 if (info2
->servername
== NULL
) {
6082 info2
->sharename
= talloc_strdup(mem_ctx
, lp_const_servicename(snum
));
6083 if (info2
->sharename
== NULL
) {
6087 /* check to see if we allow printername != sharename */
6088 if (lp_force_printername(snum
)) {
6089 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6090 global_myname(), info2
->sharename
);
6092 /* make sure printername is in \\server\printername format */
6093 fstrcpy(printername
, info2
->printername
);
6095 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
6096 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
6100 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6101 global_myname(), p
);
6103 if (info2
->printername
== NULL
) {
6107 info2
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
6108 info2
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
6113 /****************************************************************************
6114 ****************************************************************************/
6116 static WERROR
add_port_hook(TALLOC_CTX
*ctx
, struct security_token
*token
, const char *portname
, const char *uri
)
6118 char *cmd
= lp_addport_cmd();
6119 char *command
= NULL
;
6121 bool is_print_op
= false;
6124 return WERR_ACCESS_DENIED
;
6127 command
= talloc_asprintf(ctx
,
6128 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
6134 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
6136 DEBUG(10,("Running [%s]\n", command
));
6138 /********* BEGIN SePrintOperatorPrivilege **********/
6143 ret
= smbrun(command
, NULL
);
6148 /********* END SePrintOperatorPrivilege **********/
6150 DEBUGADD(10,("returned [%d]\n", ret
));
6152 TALLOC_FREE(command
);
6155 return WERR_ACCESS_DENIED
;
6161 /****************************************************************************
6162 ****************************************************************************/
6164 static bool add_printer_hook(TALLOC_CTX
*ctx
, struct security_token
*token
,
6165 struct spoolss_SetPrinterInfo2
*info2
,
6166 const char *remote_machine
,
6167 struct messaging_context
*msg_ctx
)
6169 char *cmd
= lp_addprinter_cmd();
6171 char *command
= NULL
;
6175 bool is_print_op
= false;
6177 if (!remote_machine
) {
6181 command
= talloc_asprintf(ctx
,
6182 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6183 cmd
, info2
->printername
, info2
->sharename
,
6184 info2
->portname
, info2
->drivername
,
6185 info2
->location
, info2
->comment
, remote_machine
);
6191 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
6193 DEBUG(10,("Running [%s]\n", command
));
6195 /********* BEGIN SePrintOperatorPrivilege **********/
6200 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6201 /* Tell everyone we updated smb.conf. */
6202 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
6208 /********* END SePrintOperatorPrivilege **********/
6210 DEBUGADD(10,("returned [%d]\n", ret
));
6212 TALLOC_FREE(command
);
6220 /* reload our services immediately */
6222 reload_services(msg_ctx
, -1, false);
6226 /* Get lines and convert them back to dos-codepage */
6227 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
6228 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6231 /* Set the portname to what the script says the portname should be. */
6232 /* but don't require anything to be return from the script exit a good error code */
6235 /* Set the portname to what the script says the portname should be. */
6236 info2
->portname
= talloc_strdup(ctx
, qlines
[0]);
6237 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6240 TALLOC_FREE(qlines
);
6244 static WERROR
update_dsspooler(TALLOC_CTX
*mem_ctx
,
6245 const struct auth_serversupplied_info
*session_info
,
6246 struct messaging_context
*msg_ctx
,
6248 struct spoolss_SetPrinterInfo2
*printer
,
6249 struct spoolss_PrinterInfo2
*old_printer
)
6251 bool force_update
= (old_printer
== NULL
);
6252 const char *dnsdomname
;
6253 const char *longname
;
6254 const char *uncname
;
6255 const char *spooling
;
6257 WERROR result
= WERR_OK
;
6258 struct dcerpc_binding_handle
*b
;
6260 result
= winreg_printer_binding_handle(mem_ctx
,
6264 if (!W_ERROR_IS_OK(result
)) {
6268 if (force_update
|| !strequal(printer
->drivername
, old_printer
->drivername
)) {
6269 push_reg_sz(mem_ctx
, &buffer
, printer
->drivername
);
6270 winreg_set_printer_dataex(mem_ctx
, b
,
6272 SPOOL_DSSPOOLER_KEY
,
6273 SPOOL_REG_DRIVERNAME
,
6278 if (!force_update
) {
6279 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6280 printer
->drivername
));
6282 notify_printer_driver(server_event_context(), msg_ctx
,
6283 snum
, printer
->drivername
?
6284 printer
->drivername
: "");
6288 if (force_update
|| !strequal(printer
->comment
, old_printer
->comment
)) {
6289 push_reg_sz(mem_ctx
, &buffer
, printer
->comment
);
6290 winreg_set_printer_dataex(mem_ctx
, b
,
6292 SPOOL_DSSPOOLER_KEY
,
6293 SPOOL_REG_DESCRIPTION
,
6298 if (!force_update
) {
6299 notify_printer_comment(server_event_context(), msg_ctx
,
6300 snum
, printer
->comment
?
6301 printer
->comment
: "");
6305 if (force_update
|| !strequal(printer
->sharename
, old_printer
->sharename
)) {
6306 push_reg_sz(mem_ctx
, &buffer
, printer
->sharename
);
6307 winreg_set_printer_dataex(mem_ctx
, b
,
6309 SPOOL_DSSPOOLER_KEY
,
6310 SPOOL_REG_PRINTSHARENAME
,
6315 if (!force_update
) {
6316 notify_printer_sharename(server_event_context(),
6318 snum
, printer
->sharename
?
6319 printer
->sharename
: "");
6323 if (force_update
|| !strequal(printer
->printername
, old_printer
->printername
)) {
6326 p
= strrchr(printer
->printername
, '\\' );
6330 p
= printer
->printername
;
6333 push_reg_sz(mem_ctx
, &buffer
, p
);
6334 winreg_set_printer_dataex(mem_ctx
, b
,
6336 SPOOL_DSSPOOLER_KEY
,
6337 SPOOL_REG_PRINTERNAME
,
6342 if (!force_update
) {
6343 notify_printer_printername(server_event_context(),
6344 msg_ctx
, snum
, p
? p
: "");
6348 if (force_update
|| !strequal(printer
->portname
, old_printer
->portname
)) {
6349 push_reg_sz(mem_ctx
, &buffer
, printer
->portname
);
6350 winreg_set_printer_dataex(mem_ctx
, b
,
6352 SPOOL_DSSPOOLER_KEY
,
6358 if (!force_update
) {
6359 notify_printer_port(server_event_context(),
6360 msg_ctx
, snum
, printer
->portname
?
6361 printer
->portname
: "");
6365 if (force_update
|| !strequal(printer
->location
, old_printer
->location
)) {
6366 push_reg_sz(mem_ctx
, &buffer
, printer
->location
);
6367 winreg_set_printer_dataex(mem_ctx
, b
,
6369 SPOOL_DSSPOOLER_KEY
,
6375 if (!force_update
) {
6376 notify_printer_location(server_event_context(),
6379 printer
->location
: "");
6383 if (force_update
|| !strequal(printer
->sepfile
, old_printer
->sepfile
)) {
6384 push_reg_sz(mem_ctx
, &buffer
, printer
->sepfile
);
6385 winreg_set_printer_dataex(mem_ctx
, b
,
6387 SPOOL_DSSPOOLER_KEY
,
6388 SPOOL_REG_PRINTSEPARATORFILE
,
6393 if (!force_update
) {
6394 notify_printer_sepfile(server_event_context(),
6397 printer
->sepfile
: "");
6401 if (force_update
|| printer
->starttime
!= old_printer
->starttime
) {
6402 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
6403 SIVAL(buffer
.data
, 0, printer
->starttime
);
6404 winreg_set_printer_dataex(mem_ctx
, b
,
6406 SPOOL_DSSPOOLER_KEY
,
6407 SPOOL_REG_PRINTSTARTTIME
,
6413 if (force_update
|| printer
->untiltime
!= old_printer
->untiltime
) {
6414 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
6415 SIVAL(buffer
.data
, 0, printer
->untiltime
);
6416 winreg_set_printer_dataex(mem_ctx
, b
,
6418 SPOOL_DSSPOOLER_KEY
,
6419 SPOOL_REG_PRINTENDTIME
,
6425 if (force_update
|| printer
->priority
!= old_printer
->priority
) {
6426 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
6427 SIVAL(buffer
.data
, 0, printer
->priority
);
6428 winreg_set_printer_dataex(mem_ctx
, b
,
6430 SPOOL_DSSPOOLER_KEY
,
6437 if (force_update
|| printer
->attributes
!= old_printer
->attributes
) {
6438 buffer
= data_blob_talloc(mem_ctx
, NULL
, 4);
6439 SIVAL(buffer
.data
, 0, (printer
->attributes
&
6440 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
6441 winreg_set_printer_dataex(mem_ctx
, b
,
6443 SPOOL_DSSPOOLER_KEY
,
6444 SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
6449 switch (printer
->attributes
& 0x3) {
6451 spooling
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
6454 spooling
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
6457 spooling
= SPOOL_REGVAL_PRINTDIRECT
;
6460 spooling
= "unknown";
6462 push_reg_sz(mem_ctx
, &buffer
, spooling
);
6463 winreg_set_printer_dataex(mem_ctx
, b
,
6465 SPOOL_DSSPOOLER_KEY
,
6466 SPOOL_REG_PRINTSPOOLING
,
6472 push_reg_sz(mem_ctx
, &buffer
, global_myname());
6473 winreg_set_printer_dataex(mem_ctx
, b
,
6475 SPOOL_DSSPOOLER_KEY
,
6476 SPOOL_REG_SHORTSERVERNAME
,
6481 dnsdomname
= get_mydnsfullname();
6482 if (dnsdomname
!= NULL
&& dnsdomname
[0] != '\0') {
6483 longname
= talloc_strdup(mem_ctx
, dnsdomname
);
6485 longname
= talloc_strdup(mem_ctx
, global_myname());
6487 if (longname
== NULL
) {
6488 result
= WERR_NOMEM
;
6492 push_reg_sz(mem_ctx
, &buffer
, longname
);
6493 winreg_set_printer_dataex(mem_ctx
, b
,
6495 SPOOL_DSSPOOLER_KEY
,
6496 SPOOL_REG_SERVERNAME
,
6501 uncname
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6502 global_myname(), printer
->sharename
);
6503 push_reg_sz(mem_ctx
, &buffer
, uncname
);
6504 winreg_set_printer_dataex(mem_ctx
, b
,
6506 SPOOL_DSSPOOLER_KEY
,
6516 /********************************************************************
6517 * Called by spoolss_api_setprinter
6518 * when updating a printer description.
6519 ********************************************************************/
6521 static WERROR
update_printer(struct pipes_struct
*p
,
6522 struct policy_handle
*handle
,
6523 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
6524 struct spoolss_DeviceMode
*devmode
)
6526 uint32_t printer_mask
= SPOOLSS_PRINTER_INFO_ALL
;
6527 struct spoolss_SetPrinterInfo2
*printer
= info_ctr
->info
.info2
;
6528 struct spoolss_PrinterInfo2
*old_printer
;
6529 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6531 WERROR result
= WERR_OK
;
6532 TALLOC_CTX
*tmp_ctx
;
6533 struct dcerpc_binding_handle
*b
;
6535 DEBUG(8,("update_printer\n"));
6537 tmp_ctx
= talloc_new(p
->mem_ctx
);
6538 if (tmp_ctx
== NULL
) {
6543 result
= WERR_BADFID
;
6547 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6548 result
= WERR_BADFID
;
6552 result
= winreg_printer_binding_handle(tmp_ctx
,
6553 get_session_info_system(),
6556 if (!W_ERROR_IS_OK(result
)) {
6560 result
= winreg_get_printer(tmp_ctx
, b
,
6561 lp_const_servicename(snum
),
6563 if (!W_ERROR_IS_OK(result
)) {
6564 result
= WERR_BADFID
;
6568 /* Do sanity check on the requested changes for Samba */
6569 if (!check_printer_ok(tmp_ctx
, printer
, snum
)) {
6570 result
= WERR_INVALID_PARAM
;
6574 /* FIXME!!! If the driver has changed we really should verify that
6575 it is installed before doing much else --jerry */
6577 /* Check calling user has permission to update printer description */
6578 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6579 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6580 result
= WERR_ACCESS_DENIED
;
6584 /* Call addprinter hook */
6585 /* Check changes to see if this is really needed */
6587 if (*lp_addprinter_cmd() &&
6588 (!strequal(printer
->drivername
, old_printer
->drivername
) ||
6589 !strequal(printer
->comment
, old_printer
->comment
) ||
6590 !strequal(printer
->portname
, old_printer
->portname
) ||
6591 !strequal(printer
->location
, old_printer
->location
)) )
6593 /* add_printer_hook() will call reload_services() */
6594 if (!add_printer_hook(tmp_ctx
, p
->session_info
->security_token
,
6595 printer
, p
->client_id
->addr
,
6597 result
= WERR_ACCESS_DENIED
;
6602 update_dsspooler(tmp_ctx
,
6603 get_session_info_system(),
6609 printer_mask
&= ~SPOOLSS_PRINTER_INFO_SECDESC
;
6611 if (devmode
== NULL
) {
6612 printer_mask
&= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
6614 result
= winreg_update_printer(tmp_ctx
, b
,
6622 talloc_free(tmp_ctx
);
6627 /****************************************************************************
6628 ****************************************************************************/
6629 static WERROR
publish_or_unpublish_printer(struct pipes_struct
*p
,
6630 struct policy_handle
*handle
,
6631 struct spoolss_SetPrinterInfo7
*info7
)
6634 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
6637 struct printer_handle
*Printer
;
6639 if ( lp_security() != SEC_ADS
) {
6640 return WERR_UNKNOWN_LEVEL
;
6643 Printer
= find_printer_index_by_hnd(p
, handle
);
6645 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6650 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6653 result
= winreg_get_printer_internal(p
->mem_ctx
,
6654 get_session_info_system(),
6656 lp_servicename(snum
),
6658 if (!W_ERROR_IS_OK(result
)) {
6662 nt_printer_publish(pinfo2
,
6663 get_session_info_system(),
6668 TALLOC_FREE(pinfo2
);
6671 return WERR_UNKNOWN_LEVEL
;
6675 /********************************************************************
6676 ********************************************************************/
6678 static WERROR
update_printer_devmode(struct pipes_struct
*p
,
6679 struct policy_handle
*handle
,
6680 struct spoolss_DeviceMode
*devmode
)
6683 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6684 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_DEVMODE
;
6686 DEBUG(8,("update_printer_devmode\n"));
6692 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6696 /* Check calling user has permission to update printer description */
6697 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6698 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6699 return WERR_ACCESS_DENIED
;
6702 return winreg_update_printer_internal(p
->mem_ctx
,
6703 get_session_info_system(),
6705 lp_const_servicename(snum
),
6713 /****************************************************************
6715 ****************************************************************/
6717 WERROR
_spoolss_SetPrinter(struct pipes_struct
*p
,
6718 struct spoolss_SetPrinter
*r
)
6722 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6725 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6726 OUR_HANDLE(r
->in
.handle
)));
6730 /* check the level */
6731 switch (r
->in
.info_ctr
->level
) {
6733 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
6735 result
= update_printer(p
, r
->in
.handle
,
6737 r
->in
.devmode_ctr
->devmode
);
6738 if (!W_ERROR_IS_OK(result
))
6740 if (r
->in
.secdesc_ctr
->sd
)
6741 result
= update_printer_sec(r
->in
.handle
, p
,
6745 return update_printer_sec(r
->in
.handle
, p
,
6748 return publish_or_unpublish_printer(p
, r
->in
.handle
,
6749 r
->in
.info_ctr
->info
.info7
);
6751 return update_printer_devmode(p
, r
->in
.handle
,
6752 r
->in
.devmode_ctr
->devmode
);
6754 return WERR_UNKNOWN_LEVEL
;
6758 /****************************************************************
6759 _spoolss_FindClosePrinterNotify
6760 ****************************************************************/
6762 WERROR
_spoolss_FindClosePrinterNotify(struct pipes_struct
*p
,
6763 struct spoolss_FindClosePrinterNotify
*r
)
6765 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6768 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6769 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
6773 if (Printer
->notify
.cli_chan
!= NULL
&&
6774 Printer
->notify
.cli_chan
->active_connections
> 0) {
6777 if (Printer
->printer_type
== SPLHND_PRINTER
) {
6778 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6783 srv_spoolss_replycloseprinter(snum
, Printer
);
6786 Printer
->notify
.flags
=0;
6787 Printer
->notify
.options
=0;
6788 Printer
->notify
.localmachine
[0]='\0';
6789 Printer
->notify
.printerlocal
=0;
6790 TALLOC_FREE(Printer
->notify
.option
);
6795 /****************************************************************
6797 ****************************************************************/
6799 WERROR
_spoolss_AddJob(struct pipes_struct
*p
,
6800 struct spoolss_AddJob
*r
)
6802 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6803 return WERR_INVALID_PARAM
;
6806 /* this is what a NT server returns for AddJob. AddJob must fail on
6807 * non-local printers */
6809 if (r
->in
.level
!= 1) {
6810 return WERR_UNKNOWN_LEVEL
;
6813 return WERR_INVALID_PARAM
;
6816 /****************************************************************************
6818 ****************************************************************************/
6820 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
6821 struct spoolss_JobInfo1
*r
,
6822 const print_queue_struct
*queue
,
6823 int position
, int snum
,
6824 struct spoolss_PrinterInfo2
*pinfo2
)
6828 t
= gmtime(&queue
->time
);
6830 r
->job_id
= queue
->job
;
6832 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6833 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6834 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
6835 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6836 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6837 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6838 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6839 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6840 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6841 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6842 r
->text_status
= talloc_strdup(mem_ctx
, "");
6843 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6845 r
->status
= nt_printj_status(queue
->status
);
6846 r
->priority
= queue
->priority
;
6847 r
->position
= position
;
6848 r
->total_pages
= queue
->page_count
;
6849 r
->pages_printed
= 0; /* ??? */
6851 init_systemtime(&r
->submitted
, t
);
6856 /****************************************************************************
6858 ****************************************************************************/
6860 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6861 struct spoolss_JobInfo2
*r
,
6862 const print_queue_struct
*queue
,
6863 int position
, int snum
,
6864 struct spoolss_PrinterInfo2
*pinfo2
,
6865 struct spoolss_DeviceMode
*devmode
)
6869 t
= gmtime(&queue
->time
);
6871 r
->job_id
= queue
->job
;
6873 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6874 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6875 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
6876 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6877 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6878 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6879 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6880 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6881 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6882 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6883 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6884 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6885 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6886 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6887 r
->parameters
= talloc_strdup(mem_ctx
, "");
6888 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6889 r
->driver_name
= talloc_strdup(mem_ctx
, pinfo2
->drivername
);
6890 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6892 r
->devmode
= devmode
;
6894 r
->text_status
= talloc_strdup(mem_ctx
, "");
6895 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6899 r
->status
= nt_printj_status(queue
->status
);
6900 r
->priority
= queue
->priority
;
6901 r
->position
= position
;
6904 r
->total_pages
= queue
->page_count
;
6905 r
->size
= queue
->size
;
6906 init_systemtime(&r
->submitted
, t
);
6908 r
->pages_printed
= 0; /* ??? */
6913 /****************************************************************************
6915 ****************************************************************************/
6917 static WERROR
fill_job_info3(TALLOC_CTX
*mem_ctx
,
6918 struct spoolss_JobInfo3
*r
,
6919 const print_queue_struct
*queue
,
6920 const print_queue_struct
*next_queue
,
6921 int position
, int snum
,
6922 struct spoolss_PrinterInfo2
*pinfo2
)
6924 r
->job_id
= queue
->job
;
6927 r
->next_job_id
= next_queue
->job
;
6934 /****************************************************************************
6935 Enumjobs at level 1.
6936 ****************************************************************************/
6938 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6939 const print_queue_struct
*queue
,
6940 uint32_t num_queues
, int snum
,
6941 struct spoolss_PrinterInfo2
*pinfo2
,
6942 union spoolss_JobInfo
**info_p
,
6945 union spoolss_JobInfo
*info
;
6947 WERROR result
= WERR_OK
;
6949 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6950 W_ERROR_HAVE_NO_MEMORY(info
);
6952 *count
= num_queues
;
6954 for (i
=0; i
<*count
; i
++) {
6955 result
= fill_job_info1(info
,
6961 if (!W_ERROR_IS_OK(result
)) {
6967 if (!W_ERROR_IS_OK(result
)) {
6978 /****************************************************************************
6979 Enumjobs at level 2.
6980 ****************************************************************************/
6982 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6983 const print_queue_struct
*queue
,
6984 uint32_t num_queues
, int snum
,
6985 struct spoolss_PrinterInfo2
*pinfo2
,
6986 union spoolss_JobInfo
**info_p
,
6989 union spoolss_JobInfo
*info
;
6991 WERROR result
= WERR_OK
;
6993 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6994 W_ERROR_HAVE_NO_MEMORY(info
);
6996 *count
= num_queues
;
6998 for (i
=0; i
<*count
; i
++) {
6999 struct spoolss_DeviceMode
*devmode
;
7001 result
= spoolss_create_default_devmode(info
,
7002 pinfo2
->printername
,
7004 if (!W_ERROR_IS_OK(result
)) {
7005 DEBUG(3, ("Can't proceed w/o a devmode!"));
7009 result
= fill_job_info2(info
,
7016 if (!W_ERROR_IS_OK(result
)) {
7022 if (!W_ERROR_IS_OK(result
)) {
7033 /****************************************************************************
7034 Enumjobs at level 3.
7035 ****************************************************************************/
7037 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
7038 const print_queue_struct
*queue
,
7039 uint32_t num_queues
, int snum
,
7040 struct spoolss_PrinterInfo2
*pinfo2
,
7041 union spoolss_JobInfo
**info_p
,
7044 union spoolss_JobInfo
*info
;
7046 WERROR result
= WERR_OK
;
7048 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7049 W_ERROR_HAVE_NO_MEMORY(info
);
7051 *count
= num_queues
;
7053 for (i
=0; i
<*count
; i
++) {
7054 const print_queue_struct
*next_queue
= NULL
;
7057 next_queue
= &queue
[i
+1];
7060 result
= fill_job_info3(info
,
7067 if (!W_ERROR_IS_OK(result
)) {
7073 if (!W_ERROR_IS_OK(result
)) {
7084 /****************************************************************
7086 ****************************************************************/
7088 WERROR
_spoolss_EnumJobs(struct pipes_struct
*p
,
7089 struct spoolss_EnumJobs
*r
)
7092 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
7094 print_status_struct prt_status
;
7095 print_queue_struct
*queue
= NULL
;
7098 /* that's an [in out] buffer */
7100 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7101 return WERR_INVALID_PARAM
;
7104 DEBUG(4,("_spoolss_EnumJobs\n"));
7108 *r
->out
.info
= NULL
;
7110 /* lookup the printer snum and tdb entry */
7112 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7116 result
= winreg_get_printer_internal(p
->mem_ctx
,
7117 get_session_info_system(),
7119 lp_const_servicename(snum
),
7121 if (!W_ERROR_IS_OK(result
)) {
7125 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
7126 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7127 count
, prt_status
.status
, prt_status
.message
));
7131 TALLOC_FREE(pinfo2
);
7135 switch (r
->in
.level
) {
7137 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
7138 pinfo2
, r
->out
.info
, r
->out
.count
);
7141 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
7142 pinfo2
, r
->out
.info
, r
->out
.count
);
7145 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
7146 pinfo2
, r
->out
.info
, r
->out
.count
);
7149 result
= WERR_UNKNOWN_LEVEL
;
7154 TALLOC_FREE(pinfo2
);
7156 if (!W_ERROR_IS_OK(result
)) {
7160 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7162 *r
->out
.info
, r
->in
.level
,
7164 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7165 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7167 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7170 /****************************************************************
7171 _spoolss_ScheduleJob
7172 ****************************************************************/
7174 WERROR
_spoolss_ScheduleJob(struct pipes_struct
*p
,
7175 struct spoolss_ScheduleJob
*r
)
7180 /****************************************************************
7181 ****************************************************************/
7183 static WERROR
spoolss_setjob_1(TALLOC_CTX
*mem_ctx
,
7184 struct messaging_context
*msg_ctx
,
7185 const char *printer_name
,
7187 struct spoolss_SetJobInfo1
*r
)
7191 if (!print_job_get_name(mem_ctx
, printer_name
, job_id
, &old_doc_name
)) {
7195 if (strequal(old_doc_name
, r
->document_name
)) {
7199 if (!print_job_set_name(server_event_context(), msg_ctx
,
7200 printer_name
, job_id
, r
->document_name
)) {
7207 /****************************************************************
7209 ****************************************************************/
7211 WERROR
_spoolss_SetJob(struct pipes_struct
*p
,
7212 struct spoolss_SetJob
*r
)
7214 const struct auth_serversupplied_info
*session_info
= p
->session_info
;
7216 WERROR errcode
= WERR_BADFUNC
;
7218 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7222 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
7223 return WERR_INVALID_PRINTER_NAME
;
7226 switch (r
->in
.command
) {
7227 case SPOOLSS_JOB_CONTROL_CANCEL
:
7228 case SPOOLSS_JOB_CONTROL_DELETE
:
7229 errcode
= print_job_delete(session_info
, p
->msg_ctx
,
7230 snum
, r
->in
.job_id
);
7231 if (W_ERROR_EQUAL(errcode
, WERR_PRINTER_HAS_JOBS_QUEUED
)) {
7235 case SPOOLSS_JOB_CONTROL_PAUSE
:
7236 if (print_job_pause(session_info
, p
->msg_ctx
,
7237 snum
, r
->in
.job_id
, &errcode
)) {
7241 case SPOOLSS_JOB_CONTROL_RESTART
:
7242 case SPOOLSS_JOB_CONTROL_RESUME
:
7243 if (print_job_resume(session_info
, p
->msg_ctx
,
7244 snum
, r
->in
.job_id
, &errcode
)) {
7252 return WERR_UNKNOWN_LEVEL
;
7255 if (!W_ERROR_IS_OK(errcode
)) {
7259 if (r
->in
.ctr
== NULL
) {
7263 switch (r
->in
.ctr
->level
) {
7265 errcode
= spoolss_setjob_1(p
->mem_ctx
, p
->msg_ctx
,
7266 lp_const_servicename(snum
),
7268 r
->in
.ctr
->info
.info1
);
7274 return WERR_UNKNOWN_LEVEL
;
7280 /****************************************************************************
7281 Enumerates all printer drivers by level and architecture.
7282 ****************************************************************************/
7284 static WERROR
enumprinterdrivers_level_by_architecture(TALLOC_CTX
*mem_ctx
,
7285 const struct auth_serversupplied_info
*session_info
,
7286 struct messaging_context
*msg_ctx
,
7287 const char *servername
,
7288 const char *architecture
,
7290 union spoolss_DriverInfo
**info_p
,
7295 struct spoolss_DriverInfo8
*driver
;
7296 union spoolss_DriverInfo
*info
= NULL
;
7298 WERROR result
= WERR_OK
;
7299 uint32_t num_drivers
;
7300 const char **drivers
;
7301 struct dcerpc_binding_handle
*b
;
7306 result
= winreg_printer_binding_handle(mem_ctx
,
7310 if (!W_ERROR_IS_OK(result
)) {
7314 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
7315 result
= winreg_get_driver_list(mem_ctx
, b
,
7316 architecture
, version
,
7317 &num_drivers
, &drivers
);
7318 if (!W_ERROR_IS_OK(result
)) {
7321 DEBUG(4, ("we have:[%d] drivers in environment"
7322 " [%s] and version [%d]\n",
7323 num_drivers
, architecture
, version
));
7325 if (num_drivers
!= 0) {
7326 info
= TALLOC_REALLOC_ARRAY(mem_ctx
, info
,
7327 union spoolss_DriverInfo
,
7328 count
+ num_drivers
);
7330 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7331 "failed to enlarge driver info buffer!\n"));
7332 result
= WERR_NOMEM
;
7337 for (i
= 0; i
< num_drivers
; i
++) {
7338 DEBUG(5, ("\tdriver: [%s]\n", drivers
[i
]));
7340 result
= winreg_get_driver(mem_ctx
, b
,
7341 architecture
, drivers
[i
],
7343 if (!W_ERROR_IS_OK(result
)) {
7349 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
7350 driver
, servername
);
7353 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
7354 driver
, servername
);
7357 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
7358 driver
, servername
);
7361 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
7362 driver
, servername
);
7365 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
7366 driver
, servername
);
7369 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
7370 driver
, servername
);
7373 result
= fill_printer_driver_info8(info
, &info
[count
+i
].info8
,
7374 driver
, servername
);
7377 result
= WERR_UNKNOWN_LEVEL
;
7381 TALLOC_FREE(driver
);
7383 if (!W_ERROR_IS_OK(result
)) {
7388 count
+= num_drivers
;
7389 TALLOC_FREE(drivers
);
7393 TALLOC_FREE(drivers
);
7395 if (!W_ERROR_IS_OK(result
)) {
7406 /****************************************************************************
7407 Enumerates all printer drivers by level.
7408 ****************************************************************************/
7410 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
7411 const struct auth_serversupplied_info
*session_info
,
7412 struct messaging_context
*msg_ctx
,
7413 const char *servername
,
7414 const char *architecture
,
7416 union spoolss_DriverInfo
**info_p
,
7420 WERROR result
= WERR_OK
;
7422 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_ALL
)) {
7424 for (a
=0; archi_table
[a
].long_archi
!= NULL
; a
++) {
7426 union spoolss_DriverInfo
*info
= NULL
;
7429 result
= enumprinterdrivers_level_by_architecture(mem_ctx
,
7433 archi_table
[a
].long_archi
,
7437 if (!W_ERROR_IS_OK(result
)) {
7441 for (i
=0; i
< count
; i
++) {
7442 ADD_TO_ARRAY(mem_ctx
, union spoolss_DriverInfo
,
7443 info
[i
], info_p
, count_p
);
7450 return enumprinterdrivers_level_by_architecture(mem_ctx
,
7460 /****************************************************************
7461 _spoolss_EnumPrinterDrivers
7462 ****************************************************************/
7464 WERROR
_spoolss_EnumPrinterDrivers(struct pipes_struct
*p
,
7465 struct spoolss_EnumPrinterDrivers
*r
)
7467 const char *cservername
;
7470 /* that's an [in out] buffer */
7472 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7473 return WERR_INVALID_PARAM
;
7476 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7480 *r
->out
.info
= NULL
;
7482 cservername
= canon_servername(r
->in
.server
);
7484 if (!is_myname_or_ipaddr(cservername
)) {
7485 return WERR_UNKNOWN_PRINTER_DRIVER
;
7488 result
= enumprinterdrivers_level(p
->mem_ctx
,
7489 get_session_info_system(),
7496 if (!W_ERROR_IS_OK(result
)) {
7500 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7501 spoolss_EnumPrinterDrivers
,
7502 *r
->out
.info
, r
->in
.level
,
7504 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7505 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7507 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7510 /****************************************************************
7512 ****************************************************************/
7514 WERROR
_spoolss_EnumForms(struct pipes_struct
*p
,
7515 struct spoolss_EnumForms
*r
)
7521 *r
->out
.info
= NULL
;
7523 /* that's an [in out] buffer */
7525 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
7526 return WERR_INVALID_PARAM
;
7529 DEBUG(4,("_spoolss_EnumForms\n"));
7530 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7531 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7533 switch (r
->in
.level
) {
7535 result
= winreg_printer_enumforms1_internal(p
->mem_ctx
,
7536 get_session_info_system(),
7542 result
= WERR_UNKNOWN_LEVEL
;
7546 if (!W_ERROR_IS_OK(result
)) {
7550 if (*r
->out
.count
== 0) {
7551 return WERR_NO_MORE_ITEMS
;
7554 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7556 *r
->out
.info
, r
->in
.level
,
7558 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7559 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7561 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7564 /****************************************************************
7566 ****************************************************************/
7568 WERROR
_spoolss_GetForm(struct pipes_struct
*p
,
7569 struct spoolss_GetForm
*r
)
7573 /* that's an [in out] buffer */
7575 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7576 return WERR_INVALID_PARAM
;
7579 DEBUG(4,("_spoolss_GetForm\n"));
7580 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7581 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7583 switch (r
->in
.level
) {
7585 result
= winreg_printer_getform1_internal(p
->mem_ctx
,
7586 get_session_info_system(),
7589 &r
->out
.info
->info1
);
7592 result
= WERR_UNKNOWN_LEVEL
;
7596 if (!W_ERROR_IS_OK(result
)) {
7597 TALLOC_FREE(r
->out
.info
);
7601 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
,
7602 r
->out
.info
, r
->in
.level
);
7603 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7605 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7608 /****************************************************************************
7609 ****************************************************************************/
7611 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
7612 struct spoolss_PortInfo1
*r
,
7615 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7616 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7621 /****************************************************************************
7622 TODO: This probably needs distinguish between TCP/IP and Local ports
7624 ****************************************************************************/
7626 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
7627 struct spoolss_PortInfo2
*r
,
7630 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7631 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7633 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
7634 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
7636 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
7637 W_ERROR_HAVE_NO_MEMORY(r
->description
);
7639 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
7646 /****************************************************************************
7647 wrapper around the enumer ports command
7648 ****************************************************************************/
7650 static WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
7652 char *cmd
= lp_enumports_cmd();
7653 char **qlines
= NULL
;
7654 char *command
= NULL
;
7662 /* if no hook then just fill in the default port */
7665 if (!(qlines
= TALLOC_ARRAY( NULL
, char*, 2 ))) {
7668 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
7669 TALLOC_FREE(qlines
);
7676 /* we have a valid enumport command */
7678 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
7683 DEBUG(10,("Running [%s]\n", command
));
7684 ret
= smbrun(command
, &fd
);
7685 DEBUG(10,("Returned [%d]\n", ret
));
7686 TALLOC_FREE(command
);
7691 return WERR_ACCESS_DENIED
;
7695 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
7696 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7706 /****************************************************************************
7708 ****************************************************************************/
7710 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
7711 union spoolss_PortInfo
**info_p
,
7714 union spoolss_PortInfo
*info
= NULL
;
7716 WERROR result
= WERR_OK
;
7717 char **qlines
= NULL
;
7720 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7721 if (!W_ERROR_IS_OK(result
)) {
7726 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7728 DEBUG(10,("Returning WERR_NOMEM\n"));
7729 result
= WERR_NOMEM
;
7733 for (i
=0; i
<numlines
; i
++) {
7734 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7735 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7736 if (!W_ERROR_IS_OK(result
)) {
7741 TALLOC_FREE(qlines
);
7744 if (!W_ERROR_IS_OK(result
)) {
7746 TALLOC_FREE(qlines
);
7758 /****************************************************************************
7760 ****************************************************************************/
7762 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7763 union spoolss_PortInfo
**info_p
,
7766 union spoolss_PortInfo
*info
= NULL
;
7768 WERROR result
= WERR_OK
;
7769 char **qlines
= NULL
;
7772 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7773 if (!W_ERROR_IS_OK(result
)) {
7778 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PortInfo
, numlines
);
7780 DEBUG(10,("Returning WERR_NOMEM\n"));
7781 result
= WERR_NOMEM
;
7785 for (i
=0; i
<numlines
; i
++) {
7786 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7787 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7788 if (!W_ERROR_IS_OK(result
)) {
7793 TALLOC_FREE(qlines
);
7796 if (!W_ERROR_IS_OK(result
)) {
7798 TALLOC_FREE(qlines
);
7810 /****************************************************************
7812 ****************************************************************/
7814 WERROR
_spoolss_EnumPorts(struct pipes_struct
*p
,
7815 struct spoolss_EnumPorts
*r
)
7819 /* that's an [in out] buffer */
7821 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7822 return WERR_INVALID_PARAM
;
7825 DEBUG(4,("_spoolss_EnumPorts\n"));
7829 *r
->out
.info
= NULL
;
7831 switch (r
->in
.level
) {
7833 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7837 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7841 return WERR_UNKNOWN_LEVEL
;
7844 if (!W_ERROR_IS_OK(result
)) {
7848 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7850 *r
->out
.info
, r
->in
.level
,
7852 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7853 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7855 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7858 /****************************************************************************
7859 ****************************************************************************/
7861 static WERROR
spoolss_addprinterex_level_2(struct pipes_struct
*p
,
7863 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7864 struct spoolss_DeviceMode
*devmode
,
7865 struct security_descriptor
*secdesc
,
7866 struct spoolss_UserLevelCtr
*user_ctr
,
7867 struct policy_handle
*handle
)
7869 struct spoolss_SetPrinterInfo2
*info2
= info_ctr
->info
.info2
;
7870 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_ALL
;
7872 WERROR err
= WERR_OK
;
7874 /* samba does not have a concept of local, non-shared printers yet, so
7875 * make sure we always setup sharename - gd */
7876 if ((info2
->sharename
== NULL
|| info2
->sharename
[0] == '\0') &&
7877 (info2
->printername
!= NULL
&& info2
->printername
[0] != '\0')) {
7878 DEBUG(5, ("spoolss_addprinterex_level_2: "
7879 "no sharename has been set, setting printername %s as sharename\n",
7880 info2
->printername
));
7881 info2
->sharename
= info2
->printername
;
7884 /* check to see if the printer already exists */
7885 if ((snum
= print_queue_snum(info2
->sharename
)) != -1) {
7886 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7888 return WERR_PRINTER_ALREADY_EXISTS
;
7891 if (!lp_force_printername(GLOBAL_SECTION_SNUM
)) {
7892 if ((snum
= print_queue_snum(info2
->printername
)) != -1) {
7893 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7894 info2
->printername
));
7895 return WERR_PRINTER_ALREADY_EXISTS
;
7899 /* validate printer info struct */
7900 if (!info2
->printername
|| strlen(info2
->printername
) == 0) {
7901 return WERR_INVALID_PRINTER_NAME
;
7903 if (!info2
->portname
|| strlen(info2
->portname
) == 0) {
7904 return WERR_UNKNOWN_PORT
;
7906 if (!info2
->drivername
|| strlen(info2
->drivername
) == 0) {
7907 return WERR_UNKNOWN_PRINTER_DRIVER
;
7909 if (!info2
->printprocessor
|| strlen(info2
->printprocessor
) == 0) {
7910 return WERR_UNKNOWN_PRINTPROCESSOR
;
7913 /* FIXME!!! smbd should check to see if the driver is installed before
7914 trying to add a printer like this --jerry */
7916 if (*lp_addprinter_cmd() ) {
7917 if ( !add_printer_hook(p
->mem_ctx
, p
->session_info
->security_token
,
7918 info2
, p
->client_id
->addr
,
7920 return WERR_ACCESS_DENIED
;
7923 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7924 "smb.conf parameter \"addprinter command\" is defined. This "
7925 "parameter must exist for this call to succeed\n",
7926 info2
->sharename
));
7929 if ((snum
= print_queue_snum(info2
->sharename
)) == -1) {
7930 return WERR_ACCESS_DENIED
;
7933 /* you must be a printer admin to add a new printer */
7934 if (!print_access_check(p
->session_info
,
7937 PRINTER_ACCESS_ADMINISTER
)) {
7938 return WERR_ACCESS_DENIED
;
7942 * Do sanity check on the requested changes for Samba.
7945 if (!check_printer_ok(p
->mem_ctx
, info2
, snum
)) {
7946 return WERR_INVALID_PARAM
;
7949 if (devmode
== NULL
) {
7950 info2_mask
= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
7953 update_dsspooler(p
->mem_ctx
,
7954 get_session_info_system(),
7960 err
= winreg_update_printer_internal(p
->mem_ctx
,
7961 get_session_info_system(),
7968 if (!W_ERROR_IS_OK(err
)) {
7972 err
= open_printer_hnd(p
, handle
, info2
->printername
, PRINTER_ACCESS_ADMINISTER
);
7973 if (!W_ERROR_IS_OK(err
)) {
7974 /* Handle open failed - remove addition. */
7975 ZERO_STRUCTP(handle
);
7982 /****************************************************************
7983 _spoolss_AddPrinterEx
7984 ****************************************************************/
7986 WERROR
_spoolss_AddPrinterEx(struct pipes_struct
*p
,
7987 struct spoolss_AddPrinterEx
*r
)
7989 switch (r
->in
.info_ctr
->level
) {
7991 /* we don't handle yet */
7992 /* but I know what to do ... */
7993 return WERR_UNKNOWN_LEVEL
;
7995 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
7997 r
->in
.devmode_ctr
->devmode
,
7998 r
->in
.secdesc_ctr
->sd
,
7999 r
->in
.userlevel_ctr
,
8002 return WERR_UNKNOWN_LEVEL
;
8006 /****************************************************************
8008 ****************************************************************/
8010 WERROR
_spoolss_AddPrinter(struct pipes_struct
*p
,
8011 struct spoolss_AddPrinter
*r
)
8013 struct spoolss_AddPrinterEx a
;
8014 struct spoolss_UserLevelCtr userlevel_ctr
;
8016 ZERO_STRUCT(userlevel_ctr
);
8018 userlevel_ctr
.level
= 1;
8020 a
.in
.server
= r
->in
.server
;
8021 a
.in
.info_ctr
= r
->in
.info_ctr
;
8022 a
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
8023 a
.in
.secdesc_ctr
= r
->in
.secdesc_ctr
;
8024 a
.in
.userlevel_ctr
= &userlevel_ctr
;
8025 a
.out
.handle
= r
->out
.handle
;
8027 return _spoolss_AddPrinterEx(p
, &a
);
8030 /****************************************************************
8031 _spoolss_AddPrinterDriverEx
8032 ****************************************************************/
8034 WERROR
_spoolss_AddPrinterDriverEx(struct pipes_struct
*p
,
8035 struct spoolss_AddPrinterDriverEx
*r
)
8037 WERROR err
= WERR_OK
;
8038 const char *driver_name
= NULL
;
8043 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
8044 fn
= "_spoolss_AddPrinterDriver";
8046 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
8047 fn
= "_spoolss_AddPrinterDriverEx";
8050 return WERR_INVALID_PARAM
;
8054 * we only support the semantics of AddPrinterDriver()
8055 * i.e. only copy files that are newer than existing ones
8058 if (r
->in
.flags
== 0) {
8059 return WERR_INVALID_PARAM
;
8062 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
8063 return WERR_ACCESS_DENIED
;
8067 if (r
->in
.info_ctr
->level
!= 3 && r
->in
.info_ctr
->level
!= 6) {
8068 /* Clever hack from Martin Zielinski <mz@seh.de>
8069 * to allow downgrade from level 8 (Vista).
8071 DEBUG(0,("%s: level %d not yet implemented\n", fn
,
8072 r
->in
.info_ctr
->level
));
8073 return WERR_UNKNOWN_LEVEL
;
8076 DEBUG(5,("Cleaning driver's information\n"));
8077 err
= clean_up_driver_struct(p
->mem_ctx
, p
->session_info
, r
->in
.info_ctr
);
8078 if (!W_ERROR_IS_OK(err
))
8081 DEBUG(5,("Moving driver to final destination\n"));
8082 err
= move_driver_to_download_area(p
->session_info
, r
->in
.info_ctr
);
8083 if (!W_ERROR_IS_OK(err
)) {
8087 err
= winreg_add_driver_internal(p
->mem_ctx
,
8088 get_session_info_system(),
8093 if (!W_ERROR_IS_OK(err
)) {
8098 * I think this is where he DrvUpgradePrinter() hook would be
8099 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8100 * server. Right now, we just need to send ourselves a message
8101 * to update each printer bound to this driver. --jerry
8104 if (!srv_spoolss_drv_upgrade_printer(driver_name
, p
->msg_ctx
)) {
8105 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8113 /****************************************************************
8114 _spoolss_AddPrinterDriver
8115 ****************************************************************/
8117 WERROR
_spoolss_AddPrinterDriver(struct pipes_struct
*p
,
8118 struct spoolss_AddPrinterDriver
*r
)
8120 struct spoolss_AddPrinterDriverEx a
;
8122 switch (r
->in
.info_ctr
->level
) {
8129 return WERR_UNKNOWN_LEVEL
;
8132 a
.in
.servername
= r
->in
.servername
;
8133 a
.in
.info_ctr
= r
->in
.info_ctr
;
8134 a
.in
.flags
= APD_COPY_NEW_FILES
;
8136 return _spoolss_AddPrinterDriverEx(p
, &a
);
8139 /****************************************************************************
8140 ****************************************************************************/
8142 struct _spoolss_paths
{
8148 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
8150 static const struct _spoolss_paths spoolss_paths
[]= {
8151 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
8152 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
8155 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
8156 const char *servername
,
8157 const char *environment
,
8161 const char *pservername
= NULL
;
8162 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
8163 const char *short_archi
;
8167 /* environment may be empty */
8168 if (environment
&& strlen(environment
)) {
8169 long_archi
= environment
;
8172 /* servername may be empty */
8173 if (servername
&& strlen(servername
)) {
8174 pservername
= canon_servername(servername
);
8176 if (!is_myname_or_ipaddr(pservername
)) {
8177 return WERR_INVALID_PARAM
;
8181 if (!(short_archi
= get_short_archi(long_archi
))) {
8182 return WERR_INVALID_ENVIRONMENT
;
8185 switch (component
) {
8186 case SPOOLSS_PRTPROCS_PATH
:
8187 case SPOOLSS_DRIVER_PATH
:
8189 *path
= talloc_asprintf(mem_ctx
,
8192 spoolss_paths
[component
].share
,
8195 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
8196 SPOOLSS_DEFAULT_SERVER_PATH
,
8197 spoolss_paths
[component
].dir
,
8202 return WERR_INVALID_PARAM
;
8212 /****************************************************************************
8213 ****************************************************************************/
8215 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
8216 const char *servername
,
8217 const char *environment
,
8218 struct spoolss_DriverDirectoryInfo1
*r
)
8223 werr
= compose_spoolss_server_path(mem_ctx
,
8226 SPOOLSS_DRIVER_PATH
,
8228 if (!W_ERROR_IS_OK(werr
)) {
8232 DEBUG(4,("printer driver directory: [%s]\n", path
));
8234 r
->directory_name
= path
;
8239 /****************************************************************
8240 _spoolss_GetPrinterDriverDirectory
8241 ****************************************************************/
8243 WERROR
_spoolss_GetPrinterDriverDirectory(struct pipes_struct
*p
,
8244 struct spoolss_GetPrinterDriverDirectory
*r
)
8248 /* that's an [in out] buffer */
8250 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8251 return WERR_INVALID_PARAM
;
8254 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8259 /* r->in.level is ignored */
8261 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
8264 &r
->out
.info
->info1
);
8265 if (!W_ERROR_IS_OK(werror
)) {
8266 TALLOC_FREE(r
->out
.info
);
8270 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
,
8271 r
->out
.info
, r
->in
.level
);
8272 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8274 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8277 /****************************************************************
8278 _spoolss_EnumPrinterData
8279 ****************************************************************/
8281 WERROR
_spoolss_EnumPrinterData(struct pipes_struct
*p
,
8282 struct spoolss_EnumPrinterData
*r
)
8285 struct spoolss_EnumPrinterDataEx r2
;
8287 struct spoolss_PrinterEnumValues
*info
, *val
= NULL
;
8290 r2
.in
.handle
= r
->in
.handle
;
8291 r2
.in
.key_name
= "PrinterDriverData";
8293 r2
.out
.count
= &count
;
8294 r2
.out
.info
= &info
;
8295 r2
.out
.needed
= &needed
;
8297 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
8298 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
8299 r2
.in
.offered
= needed
;
8300 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
8302 if (!W_ERROR_IS_OK(result
)) {
8307 * The NT machine wants to know the biggest size of value and data
8309 * cf: MSDN EnumPrinterData remark section
8312 if (!r
->in
.value_offered
&& !r
->in
.data_offered
) {
8313 uint32_t biggest_valuesize
= 0;
8314 uint32_t biggest_datasize
= 0;
8317 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8319 for (i
=0; i
<count
; i
++) {
8321 name_length
= strlen(info
[i
].value_name
);
8322 if (strlen(info
[i
].value_name
) > biggest_valuesize
) {
8323 biggest_valuesize
= name_length
;
8326 if (info
[i
].data_length
> biggest_datasize
) {
8327 biggest_datasize
= info
[i
].data_length
;
8330 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
8334 /* the value is an UNICODE string but real_value_size is the length
8335 in bytes including the trailing 0 */
8337 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
8338 *r
->out
.data_needed
= biggest_datasize
;
8340 DEBUG(6,("final values: [%d], [%d]\n",
8341 *r
->out
.value_needed
, *r
->out
.data_needed
));
8346 if (r
->in
.enum_index
< count
) {
8347 val
= &info
[r
->in
.enum_index
];
8351 /* out_value should default to "" or else NT4 has
8352 problems unmarshalling the response */
8354 if (r
->in
.value_offered
) {
8355 *r
->out
.value_needed
= 1;
8356 r
->out
.value_name
= talloc_strdup(r
, "");
8357 if (!r
->out
.value_name
) {
8361 r
->out
.value_name
= NULL
;
8362 *r
->out
.value_needed
= 0;
8365 /* the data is counted in bytes */
8367 *r
->out
.data_needed
= r
->in
.data_offered
;
8369 result
= WERR_NO_MORE_ITEMS
;
8373 * - counted in bytes in the request
8374 * - counted in UNICODE chars in the max reply
8375 * - counted in bytes in the real size
8377 * take a pause *before* coding not *during* coding
8381 if (r
->in
.value_offered
) {
8382 r
->out
.value_name
= talloc_strdup(r
, val
->value_name
);
8383 if (!r
->out
.value_name
) {
8386 *r
->out
.value_needed
= val
->value_name_len
;
8388 r
->out
.value_name
= NULL
;
8389 *r
->out
.value_needed
= 0;
8394 *r
->out
.type
= val
->type
;
8396 /* data - counted in bytes */
8399 * See the section "Dynamically Typed Query Parameters"
8403 if (r
->out
.data
&& val
->data
&& val
->data
->data
&&
8404 val
->data_length
&& r
->in
.data_offered
) {
8405 memcpy(r
->out
.data
, val
->data
->data
,
8406 MIN(val
->data_length
,r
->in
.data_offered
));
8409 *r
->out
.data_needed
= val
->data_length
;
8417 /****************************************************************
8418 _spoolss_SetPrinterData
8419 ****************************************************************/
8421 WERROR
_spoolss_SetPrinterData(struct pipes_struct
*p
,
8422 struct spoolss_SetPrinterData
*r
)
8424 struct spoolss_SetPrinterDataEx r2
;
8426 r2
.in
.handle
= r
->in
.handle
;
8427 r2
.in
.key_name
= "PrinterDriverData";
8428 r2
.in
.value_name
= r
->in
.value_name
;
8429 r2
.in
.type
= r
->in
.type
;
8430 r2
.in
.data
= r
->in
.data
;
8431 r2
.in
.offered
= r
->in
.offered
;
8433 return _spoolss_SetPrinterDataEx(p
, &r2
);
8436 /****************************************************************
8437 _spoolss_ResetPrinter
8438 ****************************************************************/
8440 WERROR
_spoolss_ResetPrinter(struct pipes_struct
*p
,
8441 struct spoolss_ResetPrinter
*r
)
8443 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8446 DEBUG(5,("_spoolss_ResetPrinter\n"));
8449 * All we do is to check to see if the handle and queue is valid.
8450 * This call really doesn't mean anything to us because we only
8451 * support RAW printing. --jerry
8455 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8456 OUR_HANDLE(r
->in
.handle
)));
8460 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8464 /* blindly return success */
8468 /****************************************************************
8469 _spoolss_DeletePrinterData
8470 ****************************************************************/
8472 WERROR
_spoolss_DeletePrinterData(struct pipes_struct
*p
,
8473 struct spoolss_DeletePrinterData
*r
)
8475 struct spoolss_DeletePrinterDataEx r2
;
8477 r2
.in
.handle
= r
->in
.handle
;
8478 r2
.in
.key_name
= "PrinterDriverData";
8479 r2
.in
.value_name
= r
->in
.value_name
;
8481 return _spoolss_DeletePrinterDataEx(p
, &r2
);
8484 /****************************************************************
8486 ****************************************************************/
8488 WERROR
_spoolss_AddForm(struct pipes_struct
*p
,
8489 struct spoolss_AddForm
*r
)
8491 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8493 WERROR status
= WERR_OK
;
8494 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8495 struct dcerpc_binding_handle
*b
;
8497 DEBUG(5,("_spoolss_AddForm\n"));
8500 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8501 OUR_HANDLE(r
->in
.handle
)));
8505 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8506 and not a printer admin, then fail */
8508 if ((p
->session_info
->utok
.uid
!= sec_initial_uid()) &&
8509 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
8510 !token_contains_name_in_list(uidtoname(p
->session_info
->utok
.uid
),
8511 p
->session_info
->info3
->base
.domain
.string
,
8513 p
->session_info
->security_token
,
8514 lp_printer_admin(snum
))) {
8515 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8516 return WERR_ACCESS_DENIED
;
8519 switch (form
->flags
) {
8520 case SPOOLSS_FORM_USER
:
8521 case SPOOLSS_FORM_BUILTIN
:
8522 case SPOOLSS_FORM_PRINTER
:
8525 return WERR_INVALID_PARAM
;
8528 status
= winreg_printer_binding_handle(p
->mem_ctx
,
8529 get_session_info_system(),
8532 if (!W_ERROR_IS_OK(status
)) {
8536 status
= winreg_printer_addform1(p
->mem_ctx
, b
,
8538 if (!W_ERROR_IS_OK(status
)) {
8543 * ChangeID must always be set if this is a printer
8545 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8546 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8550 status
= winreg_printer_update_changeid(p
->mem_ctx
, b
,
8551 lp_const_servicename(snum
));
8552 if (!W_ERROR_IS_OK(status
)) {
8560 /****************************************************************
8562 ****************************************************************/
8564 WERROR
_spoolss_DeleteForm(struct pipes_struct
*p
,
8565 struct spoolss_DeleteForm
*r
)
8567 const char *form_name
= r
->in
.form_name
;
8568 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8570 WERROR status
= WERR_OK
;
8571 struct dcerpc_binding_handle
*b
;
8573 DEBUG(5,("_spoolss_DeleteForm\n"));
8576 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8577 OUR_HANDLE(r
->in
.handle
)));
8581 if ((p
->session_info
->utok
.uid
!= sec_initial_uid()) &&
8582 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
8583 !token_contains_name_in_list(uidtoname(p
->session_info
->utok
.uid
),
8584 p
->session_info
->info3
->base
.domain
.string
,
8586 p
->session_info
->security_token
,
8587 lp_printer_admin(snum
))) {
8588 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8589 return WERR_ACCESS_DENIED
;
8592 status
= winreg_printer_binding_handle(p
->mem_ctx
,
8593 get_session_info_system(),
8596 if (!W_ERROR_IS_OK(status
)) {
8600 status
= winreg_printer_deleteform1(p
->mem_ctx
, b
,
8602 if (!W_ERROR_IS_OK(status
)) {
8607 * ChangeID must always be set if this is a printer
8609 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8610 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8614 status
= winreg_printer_update_changeid(p
->mem_ctx
, b
,
8615 lp_const_servicename(snum
));
8616 if (!W_ERROR_IS_OK(status
)) {
8624 /****************************************************************
8626 ****************************************************************/
8628 WERROR
_spoolss_SetForm(struct pipes_struct
*p
,
8629 struct spoolss_SetForm
*r
)
8631 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8632 const char *form_name
= r
->in
.form_name
;
8634 WERROR status
= WERR_OK
;
8635 struct dcerpc_binding_handle
*b
;
8637 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8639 DEBUG(5,("_spoolss_SetForm\n"));
8642 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8643 OUR_HANDLE(r
->in
.handle
)));
8647 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8648 and not a printer admin, then fail */
8650 if ((p
->session_info
->utok
.uid
!= sec_initial_uid()) &&
8651 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
8652 !token_contains_name_in_list(uidtoname(p
->session_info
->utok
.uid
),
8653 p
->session_info
->info3
->base
.domain
.string
,
8655 p
->session_info
->security_token
,
8656 lp_printer_admin(snum
))) {
8657 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8658 return WERR_ACCESS_DENIED
;
8661 status
= winreg_printer_binding_handle(p
->mem_ctx
,
8662 get_session_info_system(),
8665 if (!W_ERROR_IS_OK(status
)) {
8669 status
= winreg_printer_setform1(p
->mem_ctx
, b
,
8672 if (!W_ERROR_IS_OK(status
)) {
8677 * ChangeID must always be set if this is a printer
8679 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8680 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8684 status
= winreg_printer_update_changeid(p
->mem_ctx
, b
,
8685 lp_const_servicename(snum
));
8686 if (!W_ERROR_IS_OK(status
)) {
8694 /****************************************************************************
8695 fill_print_processor1
8696 ****************************************************************************/
8698 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8699 struct spoolss_PrintProcessorInfo1
*r
,
8700 const char *print_processor_name
)
8702 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8703 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8708 /****************************************************************************
8709 enumprintprocessors level 1.
8710 ****************************************************************************/
8712 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8713 union spoolss_PrintProcessorInfo
**info_p
,
8716 union spoolss_PrintProcessorInfo
*info
;
8719 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8720 W_ERROR_HAVE_NO_MEMORY(info
);
8724 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8725 if (!W_ERROR_IS_OK(result
)) {
8730 if (!W_ERROR_IS_OK(result
)) {
8741 /****************************************************************
8742 _spoolss_EnumPrintProcessors
8743 ****************************************************************/
8745 WERROR
_spoolss_EnumPrintProcessors(struct pipes_struct
*p
,
8746 struct spoolss_EnumPrintProcessors
*r
)
8750 /* that's an [in out] buffer */
8752 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8753 return WERR_INVALID_PARAM
;
8756 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8759 * Enumerate the print processors ...
8761 * Just reply with "winprint", to keep NT happy
8762 * and I can use my nice printer checker.
8767 *r
->out
.info
= NULL
;
8769 if (!get_short_archi(r
->in
.environment
)) {
8770 return WERR_INVALID_ENVIRONMENT
;
8773 switch (r
->in
.level
) {
8775 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8779 return WERR_UNKNOWN_LEVEL
;
8782 if (!W_ERROR_IS_OK(result
)) {
8786 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8787 spoolss_EnumPrintProcessors
,
8788 *r
->out
.info
, r
->in
.level
,
8790 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8791 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8793 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8796 /****************************************************************************
8797 fill_printprocdatatype1
8798 ****************************************************************************/
8800 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8801 struct spoolss_PrintProcDataTypesInfo1
*r
,
8802 const char *name_array
)
8804 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8805 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8810 /****************************************************************************
8811 enumprintprocdatatypes level 1.
8812 ****************************************************************************/
8814 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8815 union spoolss_PrintProcDataTypesInfo
**info_p
,
8819 union spoolss_PrintProcDataTypesInfo
*info
;
8821 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8822 W_ERROR_HAVE_NO_MEMORY(info
);
8826 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8827 if (!W_ERROR_IS_OK(result
)) {
8832 if (!W_ERROR_IS_OK(result
)) {
8843 /****************************************************************
8844 _spoolss_EnumPrintProcDataTypes
8845 ****************************************************************/
8847 WERROR
_spoolss_EnumPrintProcDataTypes(struct pipes_struct
*p
,
8848 struct spoolss_EnumPrintProcDataTypes
*r
)
8852 /* that's an [in out] buffer */
8854 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8855 return WERR_INVALID_PARAM
;
8858 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8862 *r
->out
.info
= NULL
;
8864 if (r
->in
.print_processor_name
== NULL
||
8865 !strequal(r
->in
.print_processor_name
, "winprint")) {
8866 return WERR_UNKNOWN_PRINTPROCESSOR
;
8869 switch (r
->in
.level
) {
8871 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8875 return WERR_UNKNOWN_LEVEL
;
8878 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8879 spoolss_EnumPrintProcDataTypes
,
8880 *r
->out
.info
, r
->in
.level
,
8882 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8883 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8885 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8888 /****************************************************************************
8890 ****************************************************************************/
8892 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8893 struct spoolss_MonitorInfo1
*r
,
8894 const char *monitor_name
)
8896 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8897 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8902 /****************************************************************************
8904 ****************************************************************************/
8906 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8907 struct spoolss_MonitorInfo2
*r
,
8908 const char *monitor_name
,
8909 const char *environment
,
8910 const char *dll_name
)
8912 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8913 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8914 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8915 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8916 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8917 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8922 /****************************************************************************
8923 enumprintmonitors level 1.
8924 ****************************************************************************/
8926 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8927 union spoolss_MonitorInfo
**info_p
,
8930 union spoolss_MonitorInfo
*info
;
8931 WERROR result
= WERR_OK
;
8933 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8934 W_ERROR_HAVE_NO_MEMORY(info
);
8938 result
= fill_monitor_1(info
, &info
[0].info1
,
8940 if (!W_ERROR_IS_OK(result
)) {
8944 result
= fill_monitor_1(info
, &info
[1].info1
,
8946 if (!W_ERROR_IS_OK(result
)) {
8951 if (!W_ERROR_IS_OK(result
)) {
8962 /****************************************************************************
8963 enumprintmonitors level 2.
8964 ****************************************************************************/
8966 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
8967 union spoolss_MonitorInfo
**info_p
,
8970 union spoolss_MonitorInfo
*info
;
8971 WERROR result
= WERR_OK
;
8973 info
= TALLOC_ARRAY(mem_ctx
, union spoolss_MonitorInfo
, 2);
8974 W_ERROR_HAVE_NO_MEMORY(info
);
8978 result
= fill_monitor_2(info
, &info
[0].info2
,
8980 "Windows NT X86", /* FIXME */
8982 if (!W_ERROR_IS_OK(result
)) {
8986 result
= fill_monitor_2(info
, &info
[1].info2
,
8988 "Windows NT X86", /* FIXME */
8990 if (!W_ERROR_IS_OK(result
)) {
8995 if (!W_ERROR_IS_OK(result
)) {
9006 /****************************************************************
9007 _spoolss_EnumMonitors
9008 ****************************************************************/
9010 WERROR
_spoolss_EnumMonitors(struct pipes_struct
*p
,
9011 struct spoolss_EnumMonitors
*r
)
9015 /* that's an [in out] buffer */
9017 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9018 return WERR_INVALID_PARAM
;
9021 DEBUG(5,("_spoolss_EnumMonitors\n"));
9024 * Enumerate the print monitors ...
9026 * Just reply with "Local Port", to keep NT happy
9027 * and I can use my nice printer checker.
9032 *r
->out
.info
= NULL
;
9034 switch (r
->in
.level
) {
9036 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
9040 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
9044 return WERR_UNKNOWN_LEVEL
;
9047 if (!W_ERROR_IS_OK(result
)) {
9051 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
9052 spoolss_EnumMonitors
,
9053 *r
->out
.info
, r
->in
.level
,
9055 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9056 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
9058 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9061 /****************************************************************************
9062 ****************************************************************************/
9064 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
9065 const print_queue_struct
*queue
,
9066 int count
, int snum
,
9067 struct spoolss_PrinterInfo2
*pinfo2
,
9069 struct spoolss_JobInfo1
*r
)
9074 for (i
=0; i
<count
; i
++) {
9075 if (queue
[i
].job
== (int)jobid
) {
9081 if (found
== false) {
9082 /* NT treats not found as bad param... yet another bad choice */
9083 return WERR_INVALID_PARAM
;
9086 return fill_job_info1(mem_ctx
,
9094 /****************************************************************************
9095 ****************************************************************************/
9097 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
9098 const print_queue_struct
*queue
,
9099 int count
, int snum
,
9100 struct spoolss_PrinterInfo2
*pinfo2
,
9102 struct spoolss_JobInfo2
*r
)
9106 struct spoolss_DeviceMode
*devmode
;
9109 for (i
=0; i
<count
; i
++) {
9110 if (queue
[i
].job
== (int)jobid
) {
9116 if (found
== false) {
9117 /* NT treats not found as bad param... yet another bad
9119 return WERR_INVALID_PARAM
;
9123 * if the print job does not have a DEVMODE associated with it,
9124 * just use the one for the printer. A NULL devicemode is not
9125 * a failure condition
9128 devmode
= print_job_devmode(lp_const_servicename(snum
), jobid
);
9130 result
= spoolss_create_default_devmode(mem_ctx
,
9131 pinfo2
->printername
,
9133 if (!W_ERROR_IS_OK(result
)) {
9134 DEBUG(3, ("Can't proceed w/o a devmode!"));
9139 return fill_job_info2(mem_ctx
,
9148 /****************************************************************
9150 ****************************************************************/
9152 WERROR
_spoolss_GetJob(struct pipes_struct
*p
,
9153 struct spoolss_GetJob
*r
)
9155 WERROR result
= WERR_OK
;
9156 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
9159 print_queue_struct
*queue
= NULL
;
9160 print_status_struct prt_status
;
9162 /* that's an [in out] buffer */
9164 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9165 return WERR_INVALID_PARAM
;
9168 DEBUG(5,("_spoolss_GetJob\n"));
9172 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9176 result
= winreg_get_printer_internal(p
->mem_ctx
,
9177 get_session_info_system(),
9179 lp_const_servicename(snum
),
9181 if (!W_ERROR_IS_OK(result
)) {
9185 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
9187 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9188 count
, prt_status
.status
, prt_status
.message
));
9190 switch (r
->in
.level
) {
9192 result
= getjob_level_1(p
->mem_ctx
,
9193 queue
, count
, snum
, pinfo2
,
9194 r
->in
.job_id
, &r
->out
.info
->info1
);
9197 result
= getjob_level_2(p
->mem_ctx
,
9198 queue
, count
, snum
, pinfo2
,
9199 r
->in
.job_id
, &r
->out
.info
->info2
);
9202 result
= WERR_UNKNOWN_LEVEL
;
9207 TALLOC_FREE(pinfo2
);
9209 if (!W_ERROR_IS_OK(result
)) {
9210 TALLOC_FREE(r
->out
.info
);
9214 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, r
->out
.info
,
9216 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9218 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9221 /****************************************************************
9222 _spoolss_GetPrinterDataEx
9223 ****************************************************************/
9225 WERROR
_spoolss_GetPrinterDataEx(struct pipes_struct
*p
,
9226 struct spoolss_GetPrinterDataEx
*r
)
9229 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9230 const char *printer
;
9232 WERROR result
= WERR_OK
;
9234 enum winreg_Type val_type
= REG_NONE
;
9235 uint8_t *val_data
= NULL
;
9236 uint32_t val_size
= 0;
9237 struct dcerpc_binding_handle
*b
;
9239 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9241 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9242 r
->in
.key_name
, r
->in
.value_name
));
9244 /* in case of problem, return some default values */
9247 *r
->out
.type
= REG_NONE
;
9250 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9251 OUR_HANDLE(r
->in
.handle
)));
9252 result
= WERR_BADFID
;
9256 /* Is the handle to a printer or to the server? */
9258 if (Printer
->printer_type
== SPLHND_SERVER
) {
9260 union spoolss_PrinterData data
;
9262 result
= getprinterdata_printer_server(p
->mem_ctx
,
9266 if (!W_ERROR_IS_OK(result
)) {
9270 result
= push_spoolss_PrinterData(p
->mem_ctx
, &blob
,
9271 *r
->out
.type
, &data
);
9272 if (!W_ERROR_IS_OK(result
)) {
9276 *r
->out
.needed
= blob
.length
;
9278 if (r
->in
.offered
>= *r
->out
.needed
) {
9279 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
9282 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9285 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9288 printer
= lp_const_servicename(snum
);
9290 /* check to see if the keyname is valid */
9291 if (!strlen(r
->in
.key_name
)) {
9292 return WERR_INVALID_PARAM
;
9295 result
= winreg_printer_binding_handle(p
->mem_ctx
,
9296 get_session_info_system(),
9299 if (!W_ERROR_IS_OK(result
)) {
9303 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9304 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
9305 strequal(r
->in
.value_name
, "ChangeId")) {
9306 *r
->out
.type
= REG_DWORD
;
9308 if (r
->in
.offered
>= *r
->out
.needed
) {
9309 uint32_t changeid
= 0;
9311 result
= winreg_printer_get_changeid(p
->mem_ctx
, b
,
9314 if (!W_ERROR_IS_OK(result
)) {
9318 SIVAL(r
->out
.data
, 0, changeid
);
9324 result
= winreg_get_printer_dataex(p
->mem_ctx
, b
,
9331 if (!W_ERROR_IS_OK(result
)) {
9335 *r
->out
.needed
= val_size
;
9336 *r
->out
.type
= val_type
;
9338 if (r
->in
.offered
>= *r
->out
.needed
) {
9339 memcpy(r
->out
.data
, val_data
, val_size
);
9343 /* retain type when returning WERR_MORE_DATA */
9344 r
->out
.data
= SPOOLSS_BUFFER_OK(r
->out
.data
, r
->out
.data
);
9346 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9349 /****************************************************************
9350 _spoolss_SetPrinterDataEx
9351 ****************************************************************/
9353 WERROR
_spoolss_SetPrinterDataEx(struct pipes_struct
*p
,
9354 struct spoolss_SetPrinterDataEx
*r
)
9356 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
9358 WERROR result
= WERR_OK
;
9359 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9361 struct dcerpc_binding_handle
*b
;
9363 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9365 /* From MSDN documentation of SetPrinterDataEx: pass request to
9366 SetPrinterData if key is "PrinterDriverData" */
9369 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9370 OUR_HANDLE(r
->in
.handle
)));
9374 if (Printer
->printer_type
== SPLHND_SERVER
) {
9375 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9376 "Not implemented for server handles yet\n"));
9377 return WERR_INVALID_PARAM
;
9380 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9385 * Access check : NT returns "access denied" if you make a
9386 * SetPrinterData call without the necessary privildge.
9387 * we were originally returning OK if nothing changed
9388 * which made Win2k issue **a lot** of SetPrinterData
9389 * when connecting to a printer --jerry
9392 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9393 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9394 "change denied by handle access permissions\n"));
9395 return WERR_ACCESS_DENIED
;
9398 result
= winreg_printer_binding_handle(p
->mem_ctx
,
9399 get_session_info_system(),
9402 if (!W_ERROR_IS_OK(result
)) {
9406 result
= winreg_get_printer(Printer
, b
,
9407 lp_servicename(snum
),
9409 if (!W_ERROR_IS_OK(result
)) {
9413 /* check for OID in valuename */
9415 oid_string
= strchr(r
->in
.value_name
, ',');
9421 /* save the registry data */
9423 result
= winreg_set_printer_dataex(p
->mem_ctx
, b
,
9431 if (W_ERROR_IS_OK(result
)) {
9432 /* save the OID if one was specified */
9434 char *str
= talloc_asprintf(p
->mem_ctx
, "%s\\%s",
9435 r
->in
.key_name
, SPOOL_OID_KEY
);
9437 result
= WERR_NOMEM
;
9442 * I'm not checking the status here on purpose. Don't know
9443 * if this is right, but I'm returning the status from the
9444 * previous set_printer_dataex() call. I have no idea if
9445 * this is right. --jerry
9447 winreg_set_printer_dataex(p
->mem_ctx
, b
,
9452 (uint8_t *) oid_string
,
9453 strlen(oid_string
) + 1);
9456 result
= winreg_printer_update_changeid(p
->mem_ctx
, b
,
9457 lp_const_servicename(snum
));
9462 talloc_free(pinfo2
);
9466 /****************************************************************
9467 _spoolss_DeletePrinterDataEx
9468 ****************************************************************/
9470 WERROR
_spoolss_DeletePrinterDataEx(struct pipes_struct
*p
,
9471 struct spoolss_DeletePrinterDataEx
*r
)
9473 const char *printer
;
9475 WERROR status
= WERR_OK
;
9476 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9478 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9481 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9482 "Invalid handle (%s:%u:%u).\n",
9483 OUR_HANDLE(r
->in
.handle
)));
9487 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9488 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9489 "printer properties change denied by handle\n"));
9490 return WERR_ACCESS_DENIED
;
9493 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
9497 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9500 printer
= lp_const_servicename(snum
);
9502 status
= winreg_delete_printer_dataex_internal(p
->mem_ctx
,
9503 get_session_info_system(),
9508 if (W_ERROR_IS_OK(status
)) {
9509 status
= winreg_printer_update_changeid_internal(p
->mem_ctx
,
9510 get_session_info_system(),
9518 /****************************************************************
9519 _spoolss_EnumPrinterKey
9520 ****************************************************************/
9522 WERROR
_spoolss_EnumPrinterKey(struct pipes_struct
*p
,
9523 struct spoolss_EnumPrinterKey
*r
)
9526 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9528 WERROR result
= WERR_BADFILE
;
9529 const char **array
= NULL
;
9532 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9535 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9536 OUR_HANDLE(r
->in
.handle
)));
9540 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9544 result
= winreg_enum_printer_key_internal(p
->mem_ctx
,
9545 get_session_info_system(),
9547 lp_const_servicename(snum
),
9551 if (!W_ERROR_IS_OK(result
)) {
9555 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
9556 result
= WERR_NOMEM
;
9560 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
9561 *r
->out
.needed
= blob
.length
;
9563 if (r
->in
.offered
< *r
->out
.needed
) {
9564 result
= WERR_MORE_DATA
;
9567 r
->out
.key_buffer
->string_array
= array
;
9571 if (!W_ERROR_IS_OK(result
)) {
9573 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
9581 /****************************************************************
9582 _spoolss_DeletePrinterKey
9583 ****************************************************************/
9585 WERROR
_spoolss_DeletePrinterKey(struct pipes_struct
*p
,
9586 struct spoolss_DeletePrinterKey
*r
)
9588 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9591 const char *printer
;
9592 struct dcerpc_binding_handle
*b
;
9594 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9597 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9598 OUR_HANDLE(r
->in
.handle
)));
9602 /* if keyname == NULL, return error */
9603 if ( !r
->in
.key_name
)
9604 return WERR_INVALID_PARAM
;
9606 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9610 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9611 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9612 "printer properties change denied by handle\n"));
9613 return WERR_ACCESS_DENIED
;
9616 printer
= lp_const_servicename(snum
);
9618 status
= winreg_printer_binding_handle(p
->mem_ctx
,
9619 get_session_info_system(),
9622 if (!W_ERROR_IS_OK(status
)) {
9626 /* delete the key and all subkeys */
9627 status
= winreg_delete_printer_key(p
->mem_ctx
, b
,
9630 if (W_ERROR_IS_OK(status
)) {
9631 status
= winreg_printer_update_changeid(p
->mem_ctx
, b
,
9638 /****************************************************************
9639 _spoolss_EnumPrinterDataEx
9640 ****************************************************************/
9642 WERROR
_spoolss_EnumPrinterDataEx(struct pipes_struct
*p
,
9643 struct spoolss_EnumPrinterDataEx
*r
)
9646 struct spoolss_PrinterEnumValues
*info
= NULL
;
9647 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9651 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9655 *r
->out
.info
= NULL
;
9658 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9659 OUR_HANDLE(r
->in
.handle
)));
9664 * first check for a keyname of NULL or "". Win2k seems to send
9665 * this a lot and we should send back WERR_INVALID_PARAM
9666 * no need to spend time looking up the printer in this case.
9670 if (!strlen(r
->in
.key_name
)) {
9671 result
= WERR_INVALID_PARAM
;
9675 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9679 /* now look for a match on the key name */
9680 result
= winreg_enum_printer_dataex_internal(p
->mem_ctx
,
9681 get_session_info_system(),
9683 lp_const_servicename(snum
),
9687 if (!W_ERROR_IS_OK(result
)) {
9691 #if 0 /* FIXME - gd */
9692 /* housekeeping information in the reply */
9694 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9695 * the hand marshalled container size is a multiple
9696 * of 4 bytes for RPC alignment.
9700 needed
+= 4-(needed
% 4);
9703 *r
->out
.count
= count
;
9704 *r
->out
.info
= info
;
9707 if (!W_ERROR_IS_OK(result
)) {
9711 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
9712 spoolss_EnumPrinterDataEx
,
9715 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9716 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
9718 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9721 /****************************************************************************
9722 ****************************************************************************/
9724 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
9725 const char *servername
,
9726 const char *environment
,
9727 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
9732 werr
= compose_spoolss_server_path(mem_ctx
,
9735 SPOOLSS_PRTPROCS_PATH
,
9737 if (!W_ERROR_IS_OK(werr
)) {
9741 DEBUG(4,("print processor directory: [%s]\n", path
));
9743 r
->directory_name
= path
;
9748 /****************************************************************
9749 _spoolss_GetPrintProcessorDirectory
9750 ****************************************************************/
9752 WERROR
_spoolss_GetPrintProcessorDirectory(struct pipes_struct
*p
,
9753 struct spoolss_GetPrintProcessorDirectory
*r
)
9756 char *prnproc_share
= NULL
;
9757 bool prnproc_share_exists
= false;
9760 /* that's an [in out] buffer */
9762 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9763 return WERR_INVALID_PARAM
;
9766 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9771 /* r->in.level is ignored */
9773 /* We always should reply with a local print processor directory so that
9774 * users are not forced to have a [prnproc$] share on the Samba spoolss
9775 * server, if users decide to do so, lets announce it though - Guenther */
9777 snum
= find_service(talloc_tos(), "prnproc$", &prnproc_share
);
9778 if (!prnproc_share
) {
9782 prnproc_share_exists
= true;
9785 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9786 prnproc_share_exists
? r
->in
.server
: NULL
,
9788 &r
->out
.info
->info1
);
9789 if (!W_ERROR_IS_OK(result
)) {
9790 TALLOC_FREE(r
->out
.info
);
9794 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
,
9795 r
->out
.info
, r
->in
.level
);
9796 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9798 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9801 /*******************************************************************
9802 ********************************************************************/
9804 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9805 const char *dllname
)
9807 enum ndr_err_code ndr_err
;
9808 struct spoolss_MonitorUi ui
;
9810 ui
.dll_name
= dllname
;
9812 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, &ui
,
9813 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9814 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9815 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9817 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9820 /*******************************************************************
9821 Streams the monitor UI DLL name in UNICODE
9822 *******************************************************************/
9824 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9825 struct security_token
*token
, DATA_BLOB
*in
,
9826 DATA_BLOB
*out
, uint32_t *needed
)
9828 const char *dllname
= "tcpmonui.dll";
9830 *needed
= (strlen(dllname
)+1) * 2;
9832 if (out
->length
< *needed
) {
9833 return WERR_INSUFFICIENT_BUFFER
;
9836 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9843 /*******************************************************************
9844 ********************************************************************/
9846 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9847 struct spoolss_PortData1
*port1
,
9848 const DATA_BLOB
*buf
)
9850 enum ndr_err_code ndr_err
;
9851 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port1
,
9852 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9853 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9854 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9856 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9859 /*******************************************************************
9860 ********************************************************************/
9862 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9863 struct spoolss_PortData2
*port2
,
9864 const DATA_BLOB
*buf
)
9866 enum ndr_err_code ndr_err
;
9867 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port2
,
9868 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9869 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9870 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9872 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9875 /*******************************************************************
9876 Create a new TCP/IP port
9877 *******************************************************************/
9879 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9880 struct security_token
*token
, DATA_BLOB
*in
,
9881 DATA_BLOB
*out
, uint32_t *needed
)
9883 struct spoolss_PortData1 port1
;
9884 struct spoolss_PortData2 port2
;
9885 char *device_uri
= NULL
;
9888 const char *portname
;
9889 const char *hostaddress
;
9891 uint32_t port_number
;
9894 /* peek for spoolss_PortData version */
9896 if (!in
|| (in
->length
< (128 + 4))) {
9897 return WERR_GENERAL_FAILURE
;
9900 version
= IVAL(in
->data
, 128);
9906 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9910 portname
= port1
.portname
;
9911 hostaddress
= port1
.hostaddress
;
9912 queue
= port1
.queue
;
9913 protocol
= port1
.protocol
;
9914 port_number
= port1
.port_number
;
9920 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9924 portname
= port2
.portname
;
9925 hostaddress
= port2
.hostaddress
;
9926 queue
= port2
.queue
;
9927 protocol
= port2
.protocol
;
9928 port_number
= port2
.port_number
;
9932 DEBUG(1,("xcvtcp_addport: "
9933 "unknown version of port_data: %d\n", version
));
9934 return WERR_UNKNOWN_PORT
;
9937 /* create the device URI and call the add_port_hook() */
9940 case PROTOCOL_RAWTCP_TYPE
:
9941 device_uri
= talloc_asprintf(mem_ctx
,
9942 "socket://%s:%d/", hostaddress
,
9946 case PROTOCOL_LPR_TYPE
:
9947 device_uri
= talloc_asprintf(mem_ctx
,
9948 "lpr://%s/%s", hostaddress
, queue
);
9952 return WERR_UNKNOWN_PORT
;
9959 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
9962 /*******************************************************************
9963 *******************************************************************/
9965 struct xcv_api_table xcvtcp_cmds
[] = {
9966 { "MonitorUI", xcvtcp_monitorui
},
9967 { "AddPort", xcvtcp_addport
},
9971 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
9972 struct security_token
*token
, const char *command
,
9979 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
9981 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
9982 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
9983 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
9986 return WERR_BADFUNC
;
9989 /*******************************************************************
9990 *******************************************************************/
9991 #if 0 /* don't support management using the "Local Port" monitor */
9993 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
9994 struct security_token
*token
, DATA_BLOB
*in
,
9995 DATA_BLOB
*out
, uint32_t *needed
)
9997 const char *dllname
= "localui.dll";
9999 *needed
= (strlen(dllname
)+1) * 2;
10001 if (out
->length
< *needed
) {
10002 return WERR_INSUFFICIENT_BUFFER
;
10005 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
10012 /*******************************************************************
10013 *******************************************************************/
10015 struct xcv_api_table xcvlocal_cmds
[] = {
10016 { "MonitorUI", xcvlocal_monitorui
},
10020 struct xcv_api_table xcvlocal_cmds
[] = {
10027 /*******************************************************************
10028 *******************************************************************/
10030 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
10031 struct security_token
*token
, const char *command
,
10032 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
10037 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
10039 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
10040 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
10041 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
10043 return WERR_BADFUNC
;
10046 /****************************************************************
10048 ****************************************************************/
10050 WERROR
_spoolss_XcvData(struct pipes_struct
*p
,
10051 struct spoolss_XcvData
*r
)
10053 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
10054 DATA_BLOB out_data
= data_blob_null
;
10058 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10059 OUR_HANDLE(r
->in
.handle
)));
10060 return WERR_BADFID
;
10063 /* Has to be a handle to the TCP/IP port monitor */
10065 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
10066 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10067 return WERR_BADFID
;
10070 /* requires administrative access to the server */
10072 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
10073 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10074 return WERR_ACCESS_DENIED
;
10077 /* Allocate the outgoing buffer */
10079 if (r
->in
.out_data_size
) {
10080 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
10081 if (out_data
.data
== NULL
) {
10086 switch ( Printer
->printer_type
) {
10087 case SPLHND_PORTMON_TCP
:
10088 werror
= process_xcvtcp_command(p
->mem_ctx
,
10089 p
->session_info
->security_token
,
10090 r
->in
.function_name
,
10091 &r
->in
.in_data
, &out_data
,
10094 case SPLHND_PORTMON_LOCAL
:
10095 werror
= process_xcvlocal_command(p
->mem_ctx
,
10096 p
->session_info
->security_token
,
10097 r
->in
.function_name
,
10098 &r
->in
.in_data
, &out_data
,
10102 werror
= WERR_INVALID_PRINT_MONITOR
;
10105 if (!W_ERROR_IS_OK(werror
)) {
10109 *r
->out
.status_code
= 0;
10111 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
10112 memcpy(r
->out
.out_data
, out_data
.data
,
10113 MIN(r
->in
.out_data_size
, out_data
.length
));
10119 /****************************************************************
10120 _spoolss_AddPrintProcessor
10121 ****************************************************************/
10123 WERROR
_spoolss_AddPrintProcessor(struct pipes_struct
*p
,
10124 struct spoolss_AddPrintProcessor
*r
)
10126 /* for now, just indicate success and ignore the add. We'll
10127 automatically set the winprint processor for printer
10128 entries later. Used to debug the LexMark Optra S 1855 PCL
10134 /****************************************************************
10136 ****************************************************************/
10138 WERROR
_spoolss_AddPort(struct pipes_struct
*p
,
10139 struct spoolss_AddPort
*r
)
10141 /* do what w2k3 does */
10143 return WERR_NOT_SUPPORTED
;
10146 /****************************************************************
10147 _spoolss_GetPrinterDriver
10148 ****************************************************************/
10150 WERROR
_spoolss_GetPrinterDriver(struct pipes_struct
*p
,
10151 struct spoolss_GetPrinterDriver
*r
)
10153 p
->rng_fault_state
= true;
10154 return WERR_NOT_SUPPORTED
;
10157 /****************************************************************
10158 _spoolss_ReadPrinter
10159 ****************************************************************/
10161 WERROR
_spoolss_ReadPrinter(struct pipes_struct
*p
,
10162 struct spoolss_ReadPrinter
*r
)
10164 p
->rng_fault_state
= true;
10165 return WERR_NOT_SUPPORTED
;
10168 /****************************************************************
10169 _spoolss_WaitForPrinterChange
10170 ****************************************************************/
10172 WERROR
_spoolss_WaitForPrinterChange(struct pipes_struct
*p
,
10173 struct spoolss_WaitForPrinterChange
*r
)
10175 p
->rng_fault_state
= true;
10176 return WERR_NOT_SUPPORTED
;
10179 /****************************************************************
10180 _spoolss_ConfigurePort
10181 ****************************************************************/
10183 WERROR
_spoolss_ConfigurePort(struct pipes_struct
*p
,
10184 struct spoolss_ConfigurePort
*r
)
10186 p
->rng_fault_state
= true;
10187 return WERR_NOT_SUPPORTED
;
10190 /****************************************************************
10191 _spoolss_DeletePort
10192 ****************************************************************/
10194 WERROR
_spoolss_DeletePort(struct pipes_struct
*p
,
10195 struct spoolss_DeletePort
*r
)
10197 p
->rng_fault_state
= true;
10198 return WERR_NOT_SUPPORTED
;
10201 /****************************************************************
10202 _spoolss_CreatePrinterIC
10203 ****************************************************************/
10205 WERROR
_spoolss_CreatePrinterIC(struct pipes_struct
*p
,
10206 struct spoolss_CreatePrinterIC
*r
)
10208 p
->rng_fault_state
= true;
10209 return WERR_NOT_SUPPORTED
;
10212 /****************************************************************
10213 _spoolss_PlayGDIScriptOnPrinterIC
10214 ****************************************************************/
10216 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct
*p
,
10217 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
10219 p
->rng_fault_state
= true;
10220 return WERR_NOT_SUPPORTED
;
10223 /****************************************************************
10224 _spoolss_DeletePrinterIC
10225 ****************************************************************/
10227 WERROR
_spoolss_DeletePrinterIC(struct pipes_struct
*p
,
10228 struct spoolss_DeletePrinterIC
*r
)
10230 p
->rng_fault_state
= true;
10231 return WERR_NOT_SUPPORTED
;
10234 /****************************************************************
10235 _spoolss_AddPrinterConnection
10236 ****************************************************************/
10238 WERROR
_spoolss_AddPrinterConnection(struct pipes_struct
*p
,
10239 struct spoolss_AddPrinterConnection
*r
)
10241 p
->rng_fault_state
= true;
10242 return WERR_NOT_SUPPORTED
;
10245 /****************************************************************
10246 _spoolss_DeletePrinterConnection
10247 ****************************************************************/
10249 WERROR
_spoolss_DeletePrinterConnection(struct pipes_struct
*p
,
10250 struct spoolss_DeletePrinterConnection
*r
)
10252 p
->rng_fault_state
= true;
10253 return WERR_NOT_SUPPORTED
;
10256 /****************************************************************
10257 _spoolss_PrinterMessageBox
10258 ****************************************************************/
10260 WERROR
_spoolss_PrinterMessageBox(struct pipes_struct
*p
,
10261 struct spoolss_PrinterMessageBox
*r
)
10263 p
->rng_fault_state
= true;
10264 return WERR_NOT_SUPPORTED
;
10267 /****************************************************************
10268 _spoolss_AddMonitor
10269 ****************************************************************/
10271 WERROR
_spoolss_AddMonitor(struct pipes_struct
*p
,
10272 struct spoolss_AddMonitor
*r
)
10274 p
->rng_fault_state
= true;
10275 return WERR_NOT_SUPPORTED
;
10278 /****************************************************************
10279 _spoolss_DeleteMonitor
10280 ****************************************************************/
10282 WERROR
_spoolss_DeleteMonitor(struct pipes_struct
*p
,
10283 struct spoolss_DeleteMonitor
*r
)
10285 p
->rng_fault_state
= true;
10286 return WERR_NOT_SUPPORTED
;
10289 /****************************************************************
10290 _spoolss_DeletePrintProcessor
10291 ****************************************************************/
10293 WERROR
_spoolss_DeletePrintProcessor(struct pipes_struct
*p
,
10294 struct spoolss_DeletePrintProcessor
*r
)
10296 p
->rng_fault_state
= true;
10297 return WERR_NOT_SUPPORTED
;
10300 /****************************************************************
10301 _spoolss_AddPrintProvidor
10302 ****************************************************************/
10304 WERROR
_spoolss_AddPrintProvidor(struct pipes_struct
*p
,
10305 struct spoolss_AddPrintProvidor
*r
)
10307 p
->rng_fault_state
= true;
10308 return WERR_NOT_SUPPORTED
;
10311 /****************************************************************
10312 _spoolss_DeletePrintProvidor
10313 ****************************************************************/
10315 WERROR
_spoolss_DeletePrintProvidor(struct pipes_struct
*p
,
10316 struct spoolss_DeletePrintProvidor
*r
)
10318 p
->rng_fault_state
= true;
10319 return WERR_NOT_SUPPORTED
;
10322 /****************************************************************
10323 _spoolss_FindFirstPrinterChangeNotification
10324 ****************************************************************/
10326 WERROR
_spoolss_FindFirstPrinterChangeNotification(struct pipes_struct
*p
,
10327 struct spoolss_FindFirstPrinterChangeNotification
*r
)
10329 p
->rng_fault_state
= true;
10330 return WERR_NOT_SUPPORTED
;
10333 /****************************************************************
10334 _spoolss_FindNextPrinterChangeNotification
10335 ****************************************************************/
10337 WERROR
_spoolss_FindNextPrinterChangeNotification(struct pipes_struct
*p
,
10338 struct spoolss_FindNextPrinterChangeNotification
*r
)
10340 p
->rng_fault_state
= true;
10341 return WERR_NOT_SUPPORTED
;
10344 /****************************************************************
10345 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10346 ****************************************************************/
10348 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct
*p
,
10349 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
10351 p
->rng_fault_state
= true;
10352 return WERR_NOT_SUPPORTED
;
10355 /****************************************************************
10356 _spoolss_ReplyOpenPrinter
10357 ****************************************************************/
10359 WERROR
_spoolss_ReplyOpenPrinter(struct pipes_struct
*p
,
10360 struct spoolss_ReplyOpenPrinter
*r
)
10362 p
->rng_fault_state
= true;
10363 return WERR_NOT_SUPPORTED
;
10366 /****************************************************************
10367 _spoolss_RouterReplyPrinter
10368 ****************************************************************/
10370 WERROR
_spoolss_RouterReplyPrinter(struct pipes_struct
*p
,
10371 struct spoolss_RouterReplyPrinter
*r
)
10373 p
->rng_fault_state
= true;
10374 return WERR_NOT_SUPPORTED
;
10377 /****************************************************************
10378 _spoolss_ReplyClosePrinter
10379 ****************************************************************/
10381 WERROR
_spoolss_ReplyClosePrinter(struct pipes_struct
*p
,
10382 struct spoolss_ReplyClosePrinter
*r
)
10384 p
->rng_fault_state
= true;
10385 return WERR_NOT_SUPPORTED
;
10388 /****************************************************************
10390 ****************************************************************/
10392 WERROR
_spoolss_AddPortEx(struct pipes_struct
*p
,
10393 struct spoolss_AddPortEx
*r
)
10395 p
->rng_fault_state
= true;
10396 return WERR_NOT_SUPPORTED
;
10399 /****************************************************************
10400 _spoolss_RouterFindFirstPrinterChangeNotification
10401 ****************************************************************/
10403 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct
*p
,
10404 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
10406 p
->rng_fault_state
= true;
10407 return WERR_NOT_SUPPORTED
;
10410 /****************************************************************
10411 _spoolss_SpoolerInit
10412 ****************************************************************/
10414 WERROR
_spoolss_SpoolerInit(struct pipes_struct
*p
,
10415 struct spoolss_SpoolerInit
*r
)
10417 p
->rng_fault_state
= true;
10418 return WERR_NOT_SUPPORTED
;
10421 /****************************************************************
10422 _spoolss_ResetPrinterEx
10423 ****************************************************************/
10425 WERROR
_spoolss_ResetPrinterEx(struct pipes_struct
*p
,
10426 struct spoolss_ResetPrinterEx
*r
)
10428 p
->rng_fault_state
= true;
10429 return WERR_NOT_SUPPORTED
;
10432 /****************************************************************
10433 _spoolss_RouterReplyPrinterEx
10434 ****************************************************************/
10436 WERROR
_spoolss_RouterReplyPrinterEx(struct pipes_struct
*p
,
10437 struct spoolss_RouterReplyPrinterEx
*r
)
10439 p
->rng_fault_state
= true;
10440 return WERR_NOT_SUPPORTED
;
10443 /****************************************************************
10445 ****************************************************************/
10447 WERROR
_spoolss_44(struct pipes_struct
*p
,
10448 struct spoolss_44
*r
)
10450 p
->rng_fault_state
= true;
10451 return WERR_NOT_SUPPORTED
;
10454 /****************************************************************
10456 ****************************************************************/
10458 WERROR
_spoolss_SetPort(struct pipes_struct
*p
,
10459 struct spoolss_SetPort
*r
)
10461 p
->rng_fault_state
= true;
10462 return WERR_NOT_SUPPORTED
;
10465 /****************************************************************
10467 ****************************************************************/
10469 WERROR
_spoolss_4a(struct pipes_struct
*p
,
10470 struct spoolss_4a
*r
)
10472 p
->rng_fault_state
= true;
10473 return WERR_NOT_SUPPORTED
;
10476 /****************************************************************
10478 ****************************************************************/
10480 WERROR
_spoolss_4b(struct pipes_struct
*p
,
10481 struct spoolss_4b
*r
)
10483 p
->rng_fault_state
= true;
10484 return WERR_NOT_SUPPORTED
;
10487 /****************************************************************
10489 ****************************************************************/
10491 WERROR
_spoolss_4c(struct pipes_struct
*p
,
10492 struct spoolss_4c
*r
)
10494 p
->rng_fault_state
= true;
10495 return WERR_NOT_SUPPORTED
;
10498 /****************************************************************
10500 ****************************************************************/
10502 WERROR
_spoolss_53(struct pipes_struct
*p
,
10503 struct spoolss_53
*r
)
10505 p
->rng_fault_state
= true;
10506 return WERR_NOT_SUPPORTED
;
10509 /****************************************************************
10510 _spoolss_AddPerMachineConnection
10511 ****************************************************************/
10513 WERROR
_spoolss_AddPerMachineConnection(struct pipes_struct
*p
,
10514 struct spoolss_AddPerMachineConnection
*r
)
10516 p
->rng_fault_state
= true;
10517 return WERR_NOT_SUPPORTED
;
10520 /****************************************************************
10521 _spoolss_DeletePerMachineConnection
10522 ****************************************************************/
10524 WERROR
_spoolss_DeletePerMachineConnection(struct pipes_struct
*p
,
10525 struct spoolss_DeletePerMachineConnection
*r
)
10527 p
->rng_fault_state
= true;
10528 return WERR_NOT_SUPPORTED
;
10531 /****************************************************************
10532 _spoolss_EnumPerMachineConnections
10533 ****************************************************************/
10535 WERROR
_spoolss_EnumPerMachineConnections(struct pipes_struct
*p
,
10536 struct spoolss_EnumPerMachineConnections
*r
)
10538 p
->rng_fault_state
= true;
10539 return WERR_NOT_SUPPORTED
;
10542 /****************************************************************
10544 ****************************************************************/
10546 WERROR
_spoolss_5a(struct pipes_struct
*p
,
10547 struct spoolss_5a
*r
)
10549 p
->rng_fault_state
= true;
10550 return WERR_NOT_SUPPORTED
;
10553 /****************************************************************
10555 ****************************************************************/
10557 WERROR
_spoolss_5b(struct pipes_struct
*p
,
10558 struct spoolss_5b
*r
)
10560 p
->rng_fault_state
= true;
10561 return WERR_NOT_SUPPORTED
;
10564 /****************************************************************
10566 ****************************************************************/
10568 WERROR
_spoolss_5c(struct pipes_struct
*p
,
10569 struct spoolss_5c
*r
)
10571 p
->rng_fault_state
= true;
10572 return WERR_NOT_SUPPORTED
;
10575 /****************************************************************
10577 ****************************************************************/
10579 WERROR
_spoolss_5d(struct pipes_struct
*p
,
10580 struct spoolss_5d
*r
)
10582 p
->rng_fault_state
= true;
10583 return WERR_NOT_SUPPORTED
;
10586 /****************************************************************
10588 ****************************************************************/
10590 WERROR
_spoolss_5e(struct pipes_struct
*p
,
10591 struct spoolss_5e
*r
)
10593 p
->rng_fault_state
= true;
10594 return WERR_NOT_SUPPORTED
;
10597 /****************************************************************
10599 ****************************************************************/
10601 WERROR
_spoolss_5f(struct pipes_struct
*p
,
10602 struct spoolss_5f
*r
)
10604 p
->rng_fault_state
= true;
10605 return WERR_NOT_SUPPORTED
;
10608 /****************************************************************
10610 ****************************************************************/
10612 WERROR
_spoolss_60(struct pipes_struct
*p
,
10613 struct spoolss_60
*r
)
10615 p
->rng_fault_state
= true;
10616 return WERR_NOT_SUPPORTED
;
10619 /****************************************************************
10621 ****************************************************************/
10623 WERROR
_spoolss_61(struct pipes_struct
*p
,
10624 struct spoolss_61
*r
)
10626 p
->rng_fault_state
= true;
10627 return WERR_NOT_SUPPORTED
;
10630 /****************************************************************
10632 ****************************************************************/
10634 WERROR
_spoolss_62(struct pipes_struct
*p
,
10635 struct spoolss_62
*r
)
10637 p
->rng_fault_state
= true;
10638 return WERR_NOT_SUPPORTED
;
10641 /****************************************************************
10643 ****************************************************************/
10645 WERROR
_spoolss_63(struct pipes_struct
*p
,
10646 struct spoolss_63
*r
)
10648 p
->rng_fault_state
= true;
10649 return WERR_NOT_SUPPORTED
;
10652 /****************************************************************
10654 ****************************************************************/
10656 WERROR
_spoolss_64(struct pipes_struct
*p
,
10657 struct spoolss_64
*r
)
10659 p
->rng_fault_state
= true;
10660 return WERR_NOT_SUPPORTED
;
10663 /****************************************************************
10665 ****************************************************************/
10667 WERROR
_spoolss_65(struct pipes_struct
*p
,
10668 struct spoolss_65
*r
)
10670 p
->rng_fault_state
= true;
10671 return WERR_NOT_SUPPORTED
;
10674 /****************************************************************
10675 _spoolss_GetCorePrinterDrivers
10676 ****************************************************************/
10678 WERROR
_spoolss_GetCorePrinterDrivers(struct pipes_struct
*p
,
10679 struct spoolss_GetCorePrinterDrivers
*r
)
10681 p
->rng_fault_state
= true;
10682 return WERR_NOT_SUPPORTED
;
10685 /****************************************************************
10687 ****************************************************************/
10689 WERROR
_spoolss_67(struct pipes_struct
*p
,
10690 struct spoolss_67
*r
)
10692 p
->rng_fault_state
= true;
10693 return WERR_NOT_SUPPORTED
;
10696 /****************************************************************
10697 _spoolss_GetPrinterDriverPackagePath
10698 ****************************************************************/
10700 WERROR
_spoolss_GetPrinterDriverPackagePath(struct pipes_struct
*p
,
10701 struct spoolss_GetPrinterDriverPackagePath
*r
)
10703 p
->rng_fault_state
= true;
10704 return WERR_NOT_SUPPORTED
;
10707 /****************************************************************
10709 ****************************************************************/
10711 WERROR
_spoolss_69(struct pipes_struct
*p
,
10712 struct spoolss_69
*r
)
10714 p
->rng_fault_state
= true;
10715 return WERR_NOT_SUPPORTED
;
10718 /****************************************************************
10720 ****************************************************************/
10722 WERROR
_spoolss_6a(struct pipes_struct
*p
,
10723 struct spoolss_6a
*r
)
10725 p
->rng_fault_state
= true;
10726 return WERR_NOT_SUPPORTED
;
10729 /****************************************************************
10731 ****************************************************************/
10733 WERROR
_spoolss_6b(struct pipes_struct
*p
,
10734 struct spoolss_6b
*r
)
10736 p
->rng_fault_state
= true;
10737 return WERR_NOT_SUPPORTED
;
10740 /****************************************************************
10742 ****************************************************************/
10744 WERROR
_spoolss_6c(struct pipes_struct
*p
,
10745 struct spoolss_6c
*r
)
10747 p
->rng_fault_state
= true;
10748 return WERR_NOT_SUPPORTED
;
10751 /****************************************************************
10753 ****************************************************************/
10755 WERROR
_spoolss_6d(struct pipes_struct
*p
,
10756 struct spoolss_6d
*r
)
10758 p
->rng_fault_state
= true;
10759 return WERR_NOT_SUPPORTED
;