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 "include/printing.h"
43 #include "../librpc/gen_ndr/netlogon.h"
45 #include "printing/notify.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62 ((info)?ndr_size_##fn(info, level, 0):0)
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
73 #define DBGC_CLASS DBGC_RPC_SRV
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
79 struct notify_back_channel
;
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle
{
86 struct printer_handle
*prev
, *next
;
87 bool document_started
;
89 uint32 jobid
; /* jobid in printing backend */
91 const char *servername
;
94 uint32 access_granted
;
100 struct spoolss_NotifyOption
*option
;
101 struct policy_handle cli_hnd
;
102 struct notify_back_channel
*cli_chan
;
104 /* are we in a FindNextPrinterChangeNotify() call? */
106 struct messaging_context
*msg_ctx
;
113 /* devmode sent in the OpenPrinter() call */
114 struct spoolss_DeviceMode
*devmode
;
116 /* TODO cache the printer info2 structure */
117 struct spoolss_PrinterInfo2
*info2
;
121 static struct printer_handle
*printers_list
;
123 struct printer_session_counter
{
124 struct printer_session_counter
*next
;
125 struct printer_session_counter
*prev
;
131 static struct printer_session_counter
*counter_list
;
133 struct notify_back_channel
{
134 struct notify_back_channel
*prev
, *next
;
136 /* associated client */
137 struct sockaddr_storage client_address
;
139 /* print notify back-channel pipe handle*/
140 struct rpc_pipe_client
*cli_pipe
;
141 uint32_t active_connections
;
144 static struct notify_back_channel
*back_channels
;
146 /* Map generic permissions to printer object specific permissions */
148 const struct standard_mapping printer_std_mapping
= {
155 /* Map generic permissions to print server object specific permissions */
157 const struct standard_mapping printserver_std_mapping
= {
164 /* API table for Xcv Monitor functions */
166 struct xcv_api_table
{
168 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, struct security_token
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
171 static void prune_printername_cache(void);
173 /********************************************************************
174 * Canonicalize servername.
175 ********************************************************************/
177 static const char *canon_servername(const char *servername
)
179 const char *pservername
= servername
;
180 while (*pservername
== '\\') {
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v
)
193 return JOB_STATUS_PAUSED
;
195 return JOB_STATUS_SPOOLING
;
197 return JOB_STATUS_PRINTING
;
199 return JOB_STATUS_ERROR
;
201 return JOB_STATUS_DELETING
;
203 return JOB_STATUS_OFFLINE
;
205 return JOB_STATUS_PAPEROUT
;
207 return JOB_STATUS_PRINTED
;
209 return JOB_STATUS_DELETED
;
211 return JOB_STATUS_BLOCKED_DEVQ
;
212 case LPQ_USER_INTERVENTION
:
213 return JOB_STATUS_USER_INTERVENTION
;
218 static int nt_printq_status(int v
)
222 return PRINTER_STATUS_PAUSED
;
231 /***************************************************************************
232 Disconnect from the client
233 ****************************************************************************/
235 static void srv_spoolss_replycloseprinter(int snum
,
236 struct printer_handle
*prn_hnd
)
242 * Tell the specific printing tdb we no longer want messages for this printer
243 * by deregistering our PID.
246 if (!print_notify_deregister_pid(snum
)) {
247 DEBUG(0, ("Failed to register our pid for printer %s\n",
248 lp_const_servicename(snum
)));
251 /* weird if the test succeeds !!! */
252 if (prn_hnd
->notify
.cli_chan
== NULL
||
253 prn_hnd
->notify
.cli_chan
->cli_pipe
== NULL
||
254 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
== NULL
||
255 prn_hnd
->notify
.cli_chan
->active_connections
== 0) {
256 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257 DLIST_REMOVE(back_channels
, prn_hnd
->notify
.cli_chan
);
258 TALLOC_FREE(prn_hnd
->notify
.cli_chan
);
262 status
= dcerpc_spoolss_ReplyClosePrinter(
263 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
,
265 &prn_hnd
->notify
.cli_hnd
,
267 if (!NT_STATUS_IS_OK(status
)) {
268 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
270 result
= ntstatus_to_werror(status
);
271 } else if (!W_ERROR_IS_OK(result
)) {
272 DEBUG(0, ("reply_close_printer failed [%s].\n",
273 win_errstr(result
)));
276 /* if it's the last connection, deconnect the IPC$ share */
277 if (prn_hnd
->notify
.cli_chan
->active_connections
== 1) {
279 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd
->notify
.cli_chan
->cli_pipe
));
280 DLIST_REMOVE(back_channels
, prn_hnd
->notify
.cli_chan
);
281 TALLOC_FREE(prn_hnd
->notify
.cli_chan
);
283 if (prn_hnd
->notify
.msg_ctx
!= NULL
) {
284 messaging_deregister(prn_hnd
->notify
.msg_ctx
,
285 MSG_PRINTER_NOTIFY2
, NULL
);
289 if (prn_hnd
->notify
.cli_chan
) {
290 prn_hnd
->notify
.cli_chan
->active_connections
--;
291 prn_hnd
->notify
.cli_chan
= NULL
;
295 /****************************************************************************
296 Functions to free a printer entry datastruct.
297 ****************************************************************************/
299 static int printer_entry_destructor(struct printer_handle
*Printer
)
301 if (Printer
->notify
.cli_chan
!= NULL
&&
302 Printer
->notify
.cli_chan
->active_connections
> 0) {
305 switch(Printer
->printer_type
) {
307 srv_spoolss_replycloseprinter(snum
, Printer
);
311 snum
= print_queue_snum(Printer
->sharename
);
313 srv_spoolss_replycloseprinter(snum
, Printer
);
321 Printer
->notify
.flags
=0;
322 Printer
->notify
.options
=0;
323 Printer
->notify
.localmachine
[0]='\0';
324 Printer
->notify
.printerlocal
=0;
325 TALLOC_FREE(Printer
->notify
.option
);
326 TALLOC_FREE(Printer
->devmode
);
328 /* Remove from the internal list. */
329 DLIST_REMOVE(printers_list
, Printer
);
333 /****************************************************************************
334 find printer index by handle
335 ****************************************************************************/
337 static struct printer_handle
*find_printer_index_by_hnd(struct pipes_struct
*p
,
338 struct policy_handle
*hnd
)
340 struct printer_handle
*find_printer
= NULL
;
342 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
343 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
350 /****************************************************************************
351 Close printer index by handle.
352 ****************************************************************************/
354 static bool close_printer_handle(struct pipes_struct
*p
, struct policy_handle
*hnd
)
356 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
359 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
364 close_policy_hnd(p
, hnd
);
369 /****************************************************************************
370 Delete a printer given a handle.
371 ****************************************************************************/
373 static WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, struct security_token
*token
,
374 const char *sharename
,
375 struct messaging_context
*msg_ctx
)
377 char *cmd
= lp_deleteprinter_cmd(talloc_tos());
378 char *command
= NULL
;
380 bool is_print_op
= false;
382 /* can't fail if we don't try */
387 command
= talloc_asprintf(ctx
,
394 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
396 DEBUG(10,("Running [%s]\n", command
));
398 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
403 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
404 /* Tell everyone we updated smb.conf. */
405 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
411 /********** END SePrintOperatorPrivlege BLOCK **********/
413 DEBUGADD(10,("returned [%d]\n", ret
));
415 TALLOC_FREE(command
);
418 return WERR_BADFID
; /* What to return here? */
423 /****************************************************************************
424 Delete a printer given a handle.
425 ****************************************************************************/
427 static WERROR
delete_printer_handle(struct pipes_struct
*p
, struct policy_handle
*hnd
)
429 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
433 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
439 * It turns out that Windows allows delete printer on a handle
440 * opened by an admin user, then used on a pipe handle created
441 * by an anonymous user..... but they're working on security.... riiight !
445 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
446 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447 return WERR_ACCESS_DENIED
;
450 /* this does not need a become root since the access check has been
451 done on the handle already */
453 result
= winreg_delete_printer_key_internal(p
->mem_ctx
,
454 get_session_info_system(),
458 if (!W_ERROR_IS_OK(result
)) {
459 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
463 result
= delete_printer_hook(p
->mem_ctx
, p
->session_info
->security_token
,
464 Printer
->sharename
, p
->msg_ctx
);
465 if (!W_ERROR_IS_OK(result
)) {
468 prune_printername_cache();
472 /****************************************************************************
473 Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
476 static bool get_printer_snum(struct pipes_struct
*p
, struct policy_handle
*hnd
,
477 int *number
, struct share_params
**params
)
479 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
482 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
487 switch (Printer
->printer_type
) {
489 DEBUG(4,("short name:%s\n", Printer
->sharename
));
490 *number
= print_queue_snum(Printer
->sharename
);
491 return (*number
!= -1);
499 /****************************************************************************
500 Set printer handle type.
501 Check if it's \\server or \\server\printer
502 ****************************************************************************/
504 static bool set_printer_hnd_printertype(struct printer_handle
*Printer
, const char *handlename
)
506 DEBUG(3,("Setting printer type=%s\n", handlename
));
508 /* it's a print server */
509 if (handlename
&& *handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
510 DEBUGADD(4,("Printer is a print server\n"));
511 Printer
->printer_type
= SPLHND_SERVER
;
513 /* it's a printer (set_printer_hnd_name() will handle port monitors */
515 DEBUGADD(4,("Printer is a printer\n"));
516 Printer
->printer_type
= SPLHND_PRINTER
;
522 static void prune_printername_cache_fn(const char *key
, const char *value
,
523 time_t timeout
, void *private_data
)
528 static void prune_printername_cache(void)
530 gencache_iterate(prune_printername_cache_fn
, NULL
, "PRINTERNAME/*");
533 /****************************************************************************
534 Set printer handle name.. Accept names like \\server, \\server\printer,
535 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
536 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537 XcvDataPort() interface.
538 ****************************************************************************/
540 static WERROR
set_printer_hnd_name(TALLOC_CTX
*mem_ctx
,
541 const struct auth_session_info
*session_info
,
542 struct messaging_context
*msg_ctx
,
543 struct printer_handle
*Printer
,
544 const char *handlename
)
547 int n_services
=lp_numservices();
549 const char *printername
;
550 const char *servername
= NULL
;
553 struct spoolss_PrinterInfo2
*info2
= NULL
;
558 * Hopefully nobody names his printers like this. Maybe \ or ,
559 * are illegal in printer names even?
561 const char printer_not_found
[] = "Printer \\, !@#$%^&*( not found";
565 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
,
566 (unsigned long)strlen(handlename
)));
568 aprinter
= discard_const_p(char, handlename
);
569 if ( *handlename
== '\\' ) {
570 servername
= canon_servername(handlename
);
571 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
575 if (!is_myname_or_ipaddr(servername
)) {
576 return WERR_INVALID_PRINTER_NAME
;
578 Printer
->servername
= talloc_asprintf(Printer
, "\\\\%s", servername
);
579 if (Printer
->servername
== NULL
) {
584 if (Printer
->printer_type
== SPLHND_SERVER
) {
588 if (Printer
->printer_type
!= SPLHND_PRINTER
) {
589 return WERR_INVALID_HANDLE
;
592 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
594 p
= strchr(aprinter
, ',');
601 if (strncmp(p
, "DrvConvert", strlen("DrvConvert")) == 0) {
603 } else if (strncmp(p
, "LocalOnly", strlen("LocalOnly")) == 0) {
609 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter
));
612 /* check for the Port Monitor Interface */
613 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
614 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
615 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
618 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
619 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
620 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
625 * With hundreds of printers, the "for" loop iterating all
626 * shares can be quite expensive, as it is done on every
627 * OpenPrinter. The loop maps "aprinter" to "sname", the
628 * result of which we cache in gencache.
631 cache_key
= talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
633 if ((cache_key
!= NULL
) && gencache_get(cache_key
, &tmp
, NULL
)) {
635 found
= (strcmp(tmp
, printer_not_found
) != 0);
637 DEBUG(4, ("Printer %s not found\n", aprinter
));
639 return WERR_INVALID_PRINTER_NAME
;
645 /* Search all sharenames first as this is easier than pulling
646 the printer_info_2 off of disk. Don't use find_service() since
647 that calls out to map_username() */
649 /* do another loop to look for printernames */
650 for (snum
= 0; !found
&& snum
< n_services
; snum
++) {
651 const char *printer
= lp_const_servicename(snum
);
653 /* no point going on if this is not a printer */
654 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
))) {
658 /* ignore [printers] share */
659 if (strequal(printer
, "printers")) {
663 fstrcpy(sname
, printer
);
664 if (strequal(aprinter
, printer
)) {
669 /* no point looking up the printer object if
670 we aren't allowing printername != sharename */
671 if (lp_force_printername(snum
)) {
675 result
= winreg_get_printer_internal(mem_ctx
,
680 if ( !W_ERROR_IS_OK(result
) ) {
681 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682 sname
, win_errstr(result
)));
686 printername
= strrchr(info2
->printername
, '\\');
687 if (printername
== NULL
) {
688 printername
= info2
->printername
;
693 if (strequal(printername
, aprinter
)) {
698 DEBUGADD(10, ("printername: %s\n", printername
));
704 if (cache_key
!= NULL
) {
705 gencache_set(cache_key
, printer_not_found
,
707 TALLOC_FREE(cache_key
);
709 DEBUGADD(4,("Printer not found\n"));
710 return WERR_INVALID_PRINTER_NAME
;
713 if (cache_key
!= NULL
) {
714 gencache_set(cache_key
, sname
, time(NULL
)+300);
715 TALLOC_FREE(cache_key
);
718 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
720 strlcpy(Printer
->sharename
, sname
, sizeof(Printer
->sharename
));
725 /****************************************************************************
726 Find first available printer slot. creates a printer handle for you.
727 ****************************************************************************/
729 static WERROR
open_printer_hnd(struct pipes_struct
*p
,
730 struct policy_handle
*hnd
,
732 uint32_t access_granted
)
734 struct printer_handle
*new_printer
;
737 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
739 new_printer
= talloc_zero(p
->mem_ctx
, struct printer_handle
);
740 if (new_printer
== NULL
) {
743 talloc_set_destructor(new_printer
, printer_entry_destructor
);
745 /* This also steals the printer_handle on the policy_handle */
746 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
747 TALLOC_FREE(new_printer
);
748 return WERR_INVALID_HANDLE
;
751 /* Add to the internal list. */
752 DLIST_ADD(printers_list
, new_printer
);
754 new_printer
->notify
.option
=NULL
;
756 if (!set_printer_hnd_printertype(new_printer
, name
)) {
757 close_printer_handle(p
, hnd
);
758 return WERR_INVALID_HANDLE
;
761 result
= set_printer_hnd_name(p
->mem_ctx
,
762 get_session_info_system(),
765 if (!W_ERROR_IS_OK(result
)) {
766 close_printer_handle(p
, hnd
);
770 new_printer
->access_granted
= access_granted
;
772 DEBUG(5, ("%d printer handles active\n",
773 (int)num_pipe_handles(p
)));
778 /***************************************************************************
779 check to see if the client motify handle is monitoring the notification
780 given by (notify_type, notify_field).
781 **************************************************************************/
783 static bool is_monitoring_event_flags(uint32_t flags
, uint16_t notify_type
,
784 uint16_t notify_field
)
789 static bool is_monitoring_event(struct printer_handle
*p
, uint16_t notify_type
,
790 uint16_t notify_field
)
792 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
796 * Flags should always be zero when the change notify
797 * is registered by the client's spooler. A user Win32 app
798 * might use the flags though instead of the NOTIFY_OPTION_INFO
807 return is_monitoring_event_flags(
808 p
->notify
.flags
, notify_type
, notify_field
);
810 for (i
= 0; i
< option
->count
; i
++) {
812 /* Check match for notify_type */
814 if (option
->types
[i
].type
!= notify_type
)
817 /* Check match for field */
819 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
820 if (option
->types
[i
].fields
[j
].field
== notify_field
) {
826 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827 p
->servername
, p
->sharename
, notify_type
, notify_field
));
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833 _data->data.integer[0] = _integer; \
834 _data->data.integer[1] = 0;
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839 if (!_data->data.string.string) {\
840 _data->data.string.size = 0; \
842 _data->data.string.size = strlen_m_term(_p) * 2;
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845 _data->data.devmode.devmode = _devmode;
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849 if (!_data->data.sd.sd) { \
850 _data->data.sd.sd_size = 0; \
852 _data->data.sd.sd_size = \
853 ndr_size_security_descriptor(_data->data.sd.sd, 0);
855 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
860 struct spoolss_Time st
;
864 if (!init_systemtime(&st
, t
)) {
868 p
= talloc_array(mem_ctx
, char, len
);
874 * Systemtime must be linearized as a set of UINT16's.
875 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
878 SSVAL(p
, 0, st
.year
);
879 SSVAL(p
, 2, st
.month
);
880 SSVAL(p
, 4, st
.day_of_week
);
882 SSVAL(p
, 8, st
.hour
);
883 SSVAL(p
, 10, st
.minute
);
884 SSVAL(p
, 12, st
.second
);
885 SSVAL(p
, 14, st
.millisecond
);
891 /* Convert a notification message to a struct spoolss_Notify */
893 static void notify_one_value(struct spoolss_notify_msg
*msg
,
894 struct spoolss_Notify
*data
,
897 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
900 static void notify_string(struct spoolss_notify_msg
*msg
,
901 struct spoolss_Notify
*data
,
904 /* The length of the message includes the trailing \0 */
906 data
->data
.string
.size
= msg
->len
* 2;
907 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
908 if (!data
->data
.string
.string
) {
909 data
->data
.string
.size
= 0;
914 static void notify_system_time(struct spoolss_notify_msg
*msg
,
915 struct spoolss_Notify
*data
,
918 data
->data
.string
.string
= NULL
;
919 data
->data
.string
.size
= 0;
921 if (msg
->len
!= sizeof(time_t)) {
922 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
927 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
928 &data
->data
.string
.string
,
929 &data
->data
.string
.size
);
932 struct notify2_message_table
{
934 void (*fn
)(struct spoolss_notify_msg
*msg
,
935 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
938 static struct notify2_message_table printer_notify_table
[] = {
939 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string
},
940 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string
},
941 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string
},
942 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string
},
943 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string
},
944 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string
},
945 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string
},
946 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL
},
947 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string
},
948 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string
},
949 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL
},
950 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string
},
951 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
952 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value
},
953 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value
},
954 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL
},
955 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL
},
956 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL
},
957 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value
},
960 static struct notify2_message_table job_notify_table
[] = {
961 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL
},
962 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL
},
963 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL
},
964 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string
},
965 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL
},
966 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL
},
967 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL
},
968 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL
},
969 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL
},
970 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL
},
971 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value
},
972 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL
},
973 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
974 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string
},
975 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL
},
976 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL
},
977 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time
},
978 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL
},
979 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL
},
980 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL
},
981 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value
},
982 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL
},
983 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value
},
984 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL
},
988 /***********************************************************************
989 Allocate talloc context for container object
990 **********************************************************************/
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
997 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
1002 /***********************************************************************
1003 release all allocated memory and zero out structure
1004 **********************************************************************/
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1012 talloc_destroy(ctr
->ctx
);
1019 /***********************************************************************
1020 **********************************************************************/
1022 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1030 /***********************************************************************
1031 **********************************************************************/
1033 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
1035 if ( !ctr
|| !ctr
->msg_groups
)
1038 if ( idx
>= ctr
->num_groups
)
1041 return &ctr
->msg_groups
[idx
];
1045 /***********************************************************************
1046 How many groups of change messages do we have ?
1047 **********************************************************************/
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1054 return ctr
->num_groups
;
1057 /***********************************************************************
1058 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059 **********************************************************************/
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
1063 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
1064 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
1065 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
1071 /* loop over all groups looking for a matching printer name */
1073 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
1074 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
1078 /* add a new group? */
1080 if ( i
== ctr
->num_groups
) {
1083 if ( !(groups
= talloc_realloc( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
1084 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1087 ctr
->msg_groups
= groups
;
1089 /* clear the new entry and set the printer name */
1091 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
1092 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
1095 /* add the change messages; 'i' is the correct index now regardless */
1097 msg_grp
= &ctr
->msg_groups
[i
];
1099 msg_grp
->num_msgs
++;
1101 if ( !(msg_list
= talloc_realloc( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
1102 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
1105 msg_grp
->msgs
= msg_list
;
1107 new_slot
= msg_grp
->num_msgs
-1;
1108 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
1110 /* need to allocate own copy of data */
1112 if ( msg
->len
!= 0 )
1113 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
1114 talloc_memdup( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
1116 return ctr
->num_groups
;
1119 static void construct_info_data(struct spoolss_Notify
*info_data
,
1120 enum spoolss_NotifyType type
,
1121 uint16_t field
, int id
);
1123 /***********************************************************************
1124 Send a change notication message on all handles which have a call
1126 **********************************************************************/
1128 static int build_notify2_messages(TALLOC_CTX
*mem_ctx
,
1129 struct printer_handle
*prn_hnd
,
1130 SPOOLSS_NOTIFY_MSG
*messages
,
1132 struct spoolss_Notify
**_notifies
,
1135 struct spoolss_Notify
*notifies
;
1136 SPOOLSS_NOTIFY_MSG
*msg
;
1141 notifies
= talloc_zero_array(mem_ctx
,
1142 struct spoolss_Notify
, num_msgs
);
1147 for (i
= 0; i
< num_msgs
; i
++) {
1151 /* Are we monitoring this event? */
1153 if (!is_monitoring_event(prn_hnd
, msg
->type
, msg
->field
)) {
1157 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158 "for printer [%s]\n",
1159 msg
->type
, msg
->field
, prn_hnd
->sharename
));
1162 * if the is a printer notification handle and not a job
1163 * notification type, then set the id to 0.
1164 * Otherwise just use what was specified in the message.
1166 * When registering change notification on a print server
1167 * handle we always need to send back the id (snum) matching
1168 * the printer for which the change took place.
1169 * For change notify registered on a printer handle,
1170 * this does not matter and the id should be 0.
1175 if ((msg
->type
== PRINTER_NOTIFY_TYPE
) &&
1176 (prn_hnd
->printer_type
== SPLHND_PRINTER
)) {
1182 /* Convert unix jobid to smb jobid */
1184 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1185 id
= sysjob_to_jobid(msg
->id
);
1188 DEBUG(3, ("no such unix jobid %d\n",
1194 construct_info_data(¬ifies
[count
],
1195 msg
->type
, msg
->field
, id
);
1198 case PRINTER_NOTIFY_TYPE
:
1199 if (printer_notify_table
[msg
->field
].fn
) {
1200 printer_notify_table
[msg
->field
].fn(msg
,
1201 ¬ifies
[count
], mem_ctx
);
1205 case JOB_NOTIFY_TYPE
:
1206 if (job_notify_table
[msg
->field
].fn
) {
1207 job_notify_table
[msg
->field
].fn(msg
,
1208 ¬ifies
[count
], mem_ctx
);
1213 DEBUG(5, ("Unknown notification type %d\n",
1221 *_notifies
= notifies
;
1227 static int send_notify2_printer(TALLOC_CTX
*mem_ctx
,
1228 struct printer_handle
*prn_hnd
,
1229 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
)
1231 struct spoolss_Notify
*notifies
;
1233 union spoolss_ReplyPrinterInfo info
;
1234 struct spoolss_NotifyInfo info0
;
1235 uint32_t reply_result
;
1240 /* Is there notification on this handle? */
1241 if (prn_hnd
->notify
.cli_chan
== NULL
||
1242 prn_hnd
->notify
.cli_chan
->cli_pipe
== NULL
||
1243 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
== NULL
||
1244 prn_hnd
->notify
.cli_chan
->active_connections
== 0) {
1248 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249 prn_hnd
->servername
, prn_hnd
->sharename
));
1251 /* For this printer? Print servers always receive notifications. */
1252 if ((prn_hnd
->printer_type
== SPLHND_PRINTER
) &&
1253 (!strequal(msg_group
->printername
, prn_hnd
->sharename
))) {
1257 DEBUG(10,("Our printer\n"));
1259 /* build the array of change notifications */
1260 ret
= build_notify2_messages(mem_ctx
, prn_hnd
,
1262 msg_group
->num_msgs
,
1268 info0
.version
= 0x2;
1269 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1270 info0
.count
= count
;
1271 info0
.notifies
= notifies
;
1273 info
.info0
= &info0
;
1275 status
= dcerpc_spoolss_RouterReplyPrinterEx(
1276 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
,
1278 &prn_hnd
->notify
.cli_hnd
,
1279 prn_hnd
->notify
.change
, /* color */
1280 prn_hnd
->notify
.flags
,
1282 0, /* reply_type, must be 0 */
1284 if (!NT_STATUS_IS_OK(status
)) {
1285 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1287 prn_hnd
->notify
.cli_chan
->cli_pipe
->srv_name_slash
,
1288 nt_errstr(status
)));
1289 werr
= ntstatus_to_werror(status
);
1290 } else if (!W_ERROR_IS_OK(werr
)) {
1291 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1293 prn_hnd
->notify
.cli_chan
->cli_pipe
->srv_name_slash
,
1296 switch (reply_result
) {
1299 case PRINTER_NOTIFY_INFO_DISCARDED
:
1300 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1301 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
1312 struct printer_handle
*p
;
1313 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
1314 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
1318 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1322 if (!msg_group
->msgs
) {
1323 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1327 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
1329 /* loop over all printers */
1331 for (p
= printers_list
; p
; p
= p
->next
) {
1332 ret
= send_notify2_printer(mem_ctx
, p
, msg_group
);
1339 DEBUG(8,("send_notify2_changes: Exit...\n"));
1343 /***********************************************************************
1344 **********************************************************************/
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1349 uint32_t tv_sec
, tv_usec
;
1352 /* Unpack message */
1354 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "f",
1357 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "ddddddd",
1359 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1362 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "dd",
1363 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1365 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "B",
1366 &msg
->len
, &msg
->notify
.data
);
1368 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1371 tv
->tv_sec
= tv_sec
;
1372 tv
->tv_usec
= tv_usec
;
1375 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1376 msg
->notify
.value
[1]));
1378 dump_data(3, (uint8_t *)msg
->notify
.data
, msg
->len
);
1383 /********************************************************************
1384 Receive a notify2 message list
1385 ********************************************************************/
1387 static void receive_notify2_message_list(struct messaging_context
*msg
,
1390 struct server_id server_id
,
1393 size_t msg_count
, i
;
1394 char *buf
= (char *)data
->data
;
1397 SPOOLSS_NOTIFY_MSG notify
;
1398 SPOOLSS_NOTIFY_MSG_CTR messages
;
1401 if (data
->length
< 4) {
1402 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1406 msg_count
= IVAL(buf
, 0);
1409 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1411 if (msg_count
== 0) {
1412 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1416 /* initialize the container */
1418 ZERO_STRUCT( messages
);
1419 notify_msg_ctr_init( &messages
);
1422 * build message groups for each printer identified
1423 * in a change_notify msg. Remember that a PCN message
1424 * includes the handle returned for the srv_spoolss_replyopenprinter()
1425 * call. Therefore messages are grouped according to printer handle.
1428 for ( i
=0; i
<msg_count
; i
++ ) {
1429 struct timeval msg_tv
;
1431 if (msg_ptr
+ 4 - buf
> data
->length
) {
1432 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1436 msg_len
= IVAL(msg_ptr
,0);
1439 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1440 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1444 /* unpack messages */
1446 ZERO_STRUCT( notify
);
1447 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1450 /* add to correct list in container */
1452 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1454 /* free memory that might have been allocated by notify2_unpack_msg() */
1456 if ( notify
.len
!= 0 )
1457 SAFE_FREE( notify
.notify
.data
);
1460 /* process each group of messages */
1462 num_groups
= notify_msg_ctr_numgroups( &messages
);
1463 for ( i
=0; i
<num_groups
; i
++ )
1464 send_notify2_changes( &messages
, i
);
1469 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470 (uint32_t)msg_count
));
1472 notify_msg_ctr_destroy( &messages
);
1477 /********************************************************************
1478 Send a message to ourself about new driver being installed
1479 so we can upgrade the information for each printer bound to this
1481 ********************************************************************/
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername
,
1484 struct messaging_context
*msg_ctx
)
1486 int len
= strlen(drivername
);
1491 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1494 messaging_send_buf(msg_ctx
, messaging_server_id(msg_ctx
),
1495 MSG_PRINTER_DRVUPGRADE
,
1496 (const uint8_t *)drivername
, len
+1);
1501 void srv_spoolss_cleanup(void)
1503 struct printer_session_counter
*session_counter
;
1505 for (session_counter
= counter_list
;
1506 session_counter
!= NULL
;
1507 session_counter
= counter_list
) {
1508 DLIST_REMOVE(counter_list
, session_counter
);
1509 TALLOC_FREE(session_counter
);
1513 /**********************************************************************
1514 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515 over all printers, upgrading ones as necessary
1516 This is now *ONLY* called inside the background lpq updater. JRA.
1517 **********************************************************************/
1519 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1522 struct server_id server_id
,
1525 TALLOC_CTX
*tmp_ctx
;
1526 const struct auth_session_info
*session_info
= get_session_info_system();
1527 struct spoolss_PrinterInfo2
*pinfo2
;
1529 const char *drivername
;
1531 int n_services
= lp_numservices();
1532 struct dcerpc_binding_handle
*b
= NULL
;
1534 tmp_ctx
= talloc_new(NULL
);
1535 if (!tmp_ctx
) return;
1537 drivername
= talloc_strndup(tmp_ctx
, (const char *)data
->data
, data
->length
);
1539 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1543 DEBUG(10, ("do_drv_upgrade_printer: "
1544 "Got message for new driver [%s]\n", drivername
));
1546 /* Iterate the printer list */
1548 for (snum
= 0; snum
< n_services
; snum
++) {
1549 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
1553 /* ignore [printers] share */
1554 if (strequal(lp_const_servicename(snum
), "printers")) {
1559 result
= winreg_printer_binding_handle(tmp_ctx
,
1563 if (!W_ERROR_IS_OK(result
)) {
1568 result
= winreg_get_printer(tmp_ctx
, b
,
1569 lp_const_servicename(snum
),
1572 if (!W_ERROR_IS_OK(result
)) {
1576 if (!pinfo2
->drivername
) {
1580 if (strcmp(drivername
, pinfo2
->drivername
) != 0) {
1584 DEBUG(6,("Updating printer [%s]\n", pinfo2
->printername
));
1586 /* all we care about currently is the change_id */
1587 result
= winreg_printer_update_changeid(tmp_ctx
, b
,
1588 pinfo2
->printername
);
1590 if (!W_ERROR_IS_OK(result
)) {
1591 DEBUG(3, ("do_drv_upgrade_printer: "
1592 "Failed to update changeid [%s]\n",
1593 win_errstr(result
)));
1599 talloc_free(tmp_ctx
);
1602 /********************************************************************
1603 Update the cache for all printq's with a registered client
1605 ********************************************************************/
1607 void update_monitored_printq_cache(struct messaging_context
*msg_ctx
)
1609 struct printer_handle
*printer
= printers_list
;
1612 /* loop through all printers and update the cache where
1613 a client is connected */
1615 if ((printer
->printer_type
== SPLHND_PRINTER
) &&
1616 ((printer
->notify
.cli_chan
!= NULL
) &&
1617 (printer
->notify
.cli_chan
->active_connections
> 0))) {
1618 snum
= print_queue_snum(printer
->sharename
);
1619 print_queue_status(msg_ctx
, snum
, NULL
, NULL
);
1622 printer
= printer
->next
;
1628 /****************************************************************
1629 _spoolss_OpenPrinter
1630 ****************************************************************/
1632 WERROR
_spoolss_OpenPrinter(struct pipes_struct
*p
,
1633 struct spoolss_OpenPrinter
*r
)
1635 struct spoolss_OpenPrinterEx e
;
1636 struct spoolss_UserLevel1 level1
;
1639 ZERO_STRUCT(level1
);
1641 e
.in
.printername
= r
->in
.printername
;
1642 e
.in
.datatype
= r
->in
.datatype
;
1643 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1644 e
.in
.access_mask
= r
->in
.access_mask
;
1645 e
.in
.userlevel_ctr
.level
= 1;
1646 e
.in
.userlevel_ctr
.user_info
.level1
= &level1
;
1648 e
.out
.handle
= r
->out
.handle
;
1650 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1652 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1653 /* OpenPrinterEx returns this for a bad
1654 * printer name. We must return WERR_INVALID_PRINTER_NAME
1657 werr
= WERR_INVALID_PRINTER_NAME
;
1663 static WERROR
copy_devicemode(TALLOC_CTX
*mem_ctx
,
1664 struct spoolss_DeviceMode
*orig
,
1665 struct spoolss_DeviceMode
**dest
)
1667 struct spoolss_DeviceMode
*dm
;
1669 dm
= talloc(mem_ctx
, struct spoolss_DeviceMode
);
1674 /* copy all values, then duplicate strings and structs */
1677 dm
->devicename
= talloc_strdup(dm
, orig
->devicename
);
1678 if (!dm
->devicename
) {
1681 dm
->formname
= talloc_strdup(dm
, orig
->formname
);
1682 if (!dm
->formname
) {
1685 if (orig
->driverextra_data
.data
) {
1686 dm
->driverextra_data
.data
=
1687 (uint8_t *) talloc_memdup(dm
, orig
->driverextra_data
.data
,
1688 orig
->driverextra_data
.length
);
1689 if (!dm
->driverextra_data
.data
) {
1698 /****************************************************************
1699 _spoolss_OpenPrinterEx
1700 ****************************************************************/
1702 WERROR
_spoolss_OpenPrinterEx(struct pipes_struct
*p
,
1703 struct spoolss_OpenPrinterEx
*r
)
1708 struct printer_handle
*Printer
=NULL
;
1712 if (!r
->in
.printername
) {
1713 return WERR_INVALID_PARAM
;
1716 if (!*r
->in
.printername
) {
1717 return WERR_INVALID_PARAM
;
1720 if (r
->in
.userlevel_ctr
.level
> 3) {
1721 return WERR_INVALID_PARAM
;
1723 if ((r
->in
.userlevel_ctr
.level
== 1 && !r
->in
.userlevel_ctr
.user_info
.level1
) ||
1724 (r
->in
.userlevel_ctr
.level
== 2 && !r
->in
.userlevel_ctr
.user_info
.level2
) ||
1725 (r
->in
.userlevel_ctr
.level
== 3 && !r
->in
.userlevel_ctr
.user_info
.level3
)) {
1726 return WERR_INVALID_PARAM
;
1730 * The printcap printer share inventory is updated on client
1731 * enumeration. For clients that do not perform enumeration prior to
1732 * access, such as cupssmbadd, we reinitialise the printer share
1733 * inventory on open as well.
1736 delete_and_reload_printers(server_event_context(), p
->msg_ctx
);
1739 /* some sanity check because you can open a printer or a print server */
1740 /* aka: \\server\printer or \\server */
1742 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1744 result
= open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0);
1745 if (!W_ERROR_IS_OK(result
)) {
1746 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1747 "for printer %s\n", r
->in
.printername
));
1748 ZERO_STRUCTP(r
->out
.handle
);
1752 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1754 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1755 "handle we created for printer %s\n", r
->in
.printername
));
1756 close_printer_handle(p
, r
->out
.handle
);
1757 ZERO_STRUCTP(r
->out
.handle
);
1758 return WERR_INVALID_PARAM
;
1762 * First case: the user is opening the print server:
1764 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1765 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1767 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1768 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1769 * or if the user is listed in the smb.conf printer admin parameter.
1771 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1772 * client view printer folder, but does not show the MSAPW.
1774 * Note: this test needs code to check access rights here too. Jeremy
1775 * could you look at this?
1777 * Second case: the user is opening a printer:
1778 * NT doesn't let us connect to a printer if the connecting user
1779 * doesn't have print permission.
1781 * Third case: user is opening a Port Monitor
1782 * access checks same as opening a handle to the print server.
1785 switch (Printer
->printer_type
)
1788 case SPLHND_PORTMON_TCP
:
1789 case SPLHND_PORTMON_LOCAL
:
1790 /* Printserver handles use global struct... */
1794 /* Map standard access rights to object specific access rights */
1796 se_map_standard(&r
->in
.access_mask
,
1797 &printserver_std_mapping
);
1799 /* Deny any object specific bits that don't apply to print
1800 servers (i.e printer and job specific bits) */
1802 r
->in
.access_mask
&= SEC_MASK_SPECIFIC
;
1804 if (r
->in
.access_mask
&
1805 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1806 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1807 close_printer_handle(p
, r
->out
.handle
);
1808 ZERO_STRUCTP(r
->out
.handle
);
1809 return WERR_ACCESS_DENIED
;
1812 /* Allow admin access */
1814 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1816 if (!lp_ms_add_printer_wizard()) {
1817 close_printer_handle(p
, r
->out
.handle
);
1818 ZERO_STRUCTP(r
->out
.handle
);
1819 return WERR_ACCESS_DENIED
;
1822 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1823 and not a printer admin, then fail */
1825 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
1826 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
1827 !nt_token_check_sid(&global_sid_Builtin_Print_Operators
,
1828 p
->session_info
->security_token
)) {
1829 close_printer_handle(p
, r
->out
.handle
);
1830 ZERO_STRUCTP(r
->out
.handle
);
1831 DEBUG(3,("access DENIED as user is not root, "
1832 "has no printoperator privilege, "
1833 "not a member of the printoperator builtin group and "
1834 "is not in printer admin list"));
1835 return WERR_ACCESS_DENIED
;
1838 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1842 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1845 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1846 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1848 /* We fall through to return WERR_OK */
1851 case SPLHND_PRINTER
:
1852 /* NT doesn't let us connect to a printer if the connecting user
1853 doesn't have print permission. */
1855 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1856 close_printer_handle(p
, r
->out
.handle
);
1857 ZERO_STRUCTP(r
->out
.handle
);
1861 if (r
->in
.access_mask
== SEC_FLAG_MAXIMUM_ALLOWED
) {
1862 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1865 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1867 /* map an empty access mask to the minimum access mask */
1868 if (r
->in
.access_mask
== 0x0)
1869 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1872 * If we are not serving the printer driver for this printer,
1873 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1874 * will keep NT clients happy --jerry
1877 if (lp_use_client_driver(snum
)
1878 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1880 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1883 /* check smb.conf parameters and the the sec_desc */
1884 raddr
= tsocket_address_inet_addr_string(p
->remote_address
,
1886 if (raddr
== NULL
) {
1890 rc
= get_remote_hostname(p
->remote_address
,
1896 if (strequal(rhost
, "UNKNOWN")) {
1900 if (!allow_access(lp_hostsdeny(snum
), lp_hostsallow(snum
),
1902 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1903 ZERO_STRUCTP(r
->out
.handle
);
1904 return WERR_ACCESS_DENIED
;
1907 if (!user_ok_token(uidtoname(p
->session_info
->unix_token
->uid
), NULL
,
1908 p
->session_info
->security_token
, snum
) ||
1909 !print_access_check(p
->session_info
,
1912 r
->in
.access_mask
)) {
1913 DEBUG(3, ("access DENIED for printer open\n"));
1914 close_printer_handle(p
, r
->out
.handle
);
1915 ZERO_STRUCTP(r
->out
.handle
);
1916 return WERR_ACCESS_DENIED
;
1919 if ((r
->in
.access_mask
& SEC_MASK_SPECIFIC
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1920 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1921 close_printer_handle(p
, r
->out
.handle
);
1922 ZERO_STRUCTP(r
->out
.handle
);
1923 return WERR_ACCESS_DENIED
;
1926 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1927 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1929 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1931 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1932 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1934 winreg_create_printer_internal(p
->mem_ctx
,
1935 get_session_info_system(),
1937 lp_const_servicename(snum
));
1942 /* sanity check to prevent programmer error */
1943 ZERO_STRUCTP(r
->out
.handle
);
1947 Printer
->access_granted
= r
->in
.access_mask
;
1950 * If the client sent a devmode in the OpenPrinter() call, then
1951 * save it here in case we get a job submission on this handle
1954 if ((Printer
->printer_type
!= SPLHND_SERVER
)
1955 && (r
->in
.devmode_ctr
.devmode
!= NULL
)) {
1956 copy_devicemode(NULL
, r
->in
.devmode_ctr
.devmode
,
1963 /****************************************************************
1964 _spoolss_ClosePrinter
1965 ****************************************************************/
1967 WERROR
_spoolss_ClosePrinter(struct pipes_struct
*p
,
1968 struct spoolss_ClosePrinter
*r
)
1970 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1972 if (Printer
&& Printer
->document_started
) {
1973 struct spoolss_EndDocPrinter e
;
1975 e
.in
.handle
= r
->in
.handle
;
1977 _spoolss_EndDocPrinter(p
, &e
);
1980 if (!close_printer_handle(p
, r
->in
.handle
))
1983 /* clear the returned printer handle. Observed behavior
1984 from Win2k server. Don't think this really matters.
1985 Previous code just copied the value of the closed
1988 ZERO_STRUCTP(r
->out
.handle
);
1993 /****************************************************************
1994 _spoolss_DeletePrinter
1995 ****************************************************************/
1997 WERROR
_spoolss_DeletePrinter(struct pipes_struct
*p
,
1998 struct spoolss_DeletePrinter
*r
)
2000 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2004 if (Printer
&& Printer
->document_started
) {
2005 struct spoolss_EndDocPrinter e
;
2007 e
.in
.handle
= r
->in
.handle
;
2009 _spoolss_EndDocPrinter(p
, &e
);
2012 if (get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
2013 winreg_delete_printer_key_internal(p
->mem_ctx
,
2014 get_session_info_system(),
2016 lp_const_servicename(snum
),
2020 result
= delete_printer_handle(p
, r
->in
.handle
);
2025 /*******************************************************************
2026 * static function to lookup the version id corresponding to an
2027 * long architecture string
2028 ******************************************************************/
2030 static const struct print_architecture_table_node archi_table
[]= {
2032 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
2033 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
2034 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
2035 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
2036 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
2037 {"Windows IA64", SPL_ARCH_IA64
, 3 },
2038 {"Windows x64", SPL_ARCH_X64
, 3 },
2042 static const int drv_cversion
[] = {SPOOLSS_DRIVER_VERSION_9X
,
2043 SPOOLSS_DRIVER_VERSION_NT35
,
2044 SPOOLSS_DRIVER_VERSION_NT4
,
2045 SPOOLSS_DRIVER_VERSION_200X
,
2048 static int get_version_id(const char *arch
)
2052 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
2054 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
2055 return (archi_table
[i
].version
);
2061 /****************************************************************
2062 _spoolss_DeletePrinterDriver
2063 ****************************************************************/
2065 WERROR
_spoolss_DeletePrinterDriver(struct pipes_struct
*p
,
2066 struct spoolss_DeletePrinterDriver
*r
)
2069 struct spoolss_DriverInfo8
*info
= NULL
;
2072 struct dcerpc_binding_handle
*b
;
2073 TALLOC_CTX
*tmp_ctx
= NULL
;
2077 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2078 and not a printer admin, then fail */
2080 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
2081 !security_token_has_privilege(p
->session_info
->security_token
,
2082 SEC_PRIV_PRINT_OPERATOR
)) {
2083 return WERR_ACCESS_DENIED
;
2086 /* check that we have a valid driver name first */
2088 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
2089 return WERR_INVALID_ENVIRONMENT
;
2092 tmp_ctx
= talloc_new(p
->mem_ctx
);
2097 status
= winreg_printer_binding_handle(tmp_ctx
,
2098 get_session_info_system(),
2101 if (!W_ERROR_IS_OK(status
)) {
2105 for (found
= false, i
= 0; drv_cversion
[i
] >= 0; i
++) {
2106 status
= winreg_get_driver(tmp_ctx
, b
,
2107 r
->in
.architecture
, r
->in
.driver
,
2108 drv_cversion
[i
], &info
);
2109 if (!W_ERROR_IS_OK(status
)) {
2110 DEBUG(5, ("skipping del of driver with version %d\n",
2116 if (printer_driver_in_use(tmp_ctx
, b
, info
)) {
2117 status
= WERR_PRINTER_DRIVER_IN_USE
;
2121 status
= winreg_del_driver(tmp_ctx
, b
, info
, drv_cversion
[i
]);
2122 if (!W_ERROR_IS_OK(status
)) {
2123 DEBUG(0, ("failed del of driver with version %d\n",
2128 if (found
== false) {
2129 DEBUG(0, ("driver %s not found for deletion\n", r
->in
.driver
));
2130 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2136 talloc_free(tmp_ctx
);
2141 static WERROR
spoolss_dpd_version(TALLOC_CTX
*mem_ctx
,
2142 struct pipes_struct
*p
,
2143 struct spoolss_DeletePrinterDriverEx
*r
,
2144 struct dcerpc_binding_handle
*b
,
2145 struct spoolss_DriverInfo8
*info
)
2150 if (printer_driver_in_use(mem_ctx
, b
, info
)) {
2151 status
= WERR_PRINTER_DRIVER_IN_USE
;
2156 * we have a couple of cases to consider.
2157 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2158 * then the delete should fail if **any** files overlap with
2160 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2161 * non-overlapping files
2162 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2163 * are set, then do not delete any files
2164 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2167 delete_files
= r
->in
.delete_flags
2168 & (DPD_DELETE_ALL_FILES
| DPD_DELETE_UNUSED_FILES
);
2172 bool in_use
= printer_driver_files_in_use(mem_ctx
, b
, info
);
2173 if (in_use
&& (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
)) {
2174 status
= WERR_PRINTER_DRIVER_IN_USE
;
2178 * printer_driver_files_in_use() has trimmed overlapping files
2179 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2184 status
= winreg_del_driver(mem_ctx
, b
, info
, info
->version
);
2185 if (!W_ERROR_IS_OK(status
)) {
2190 * now delete any associated files if delete_files is
2191 * true. Even if this part failes, we return succes
2192 * because the driver doesn not exist any more
2195 delete_driver_files(p
->session_info
, info
);
2202 /****************************************************************
2203 _spoolss_DeletePrinterDriverEx
2204 ****************************************************************/
2206 WERROR
_spoolss_DeletePrinterDriverEx(struct pipes_struct
*p
,
2207 struct spoolss_DeletePrinterDriverEx
*r
)
2209 struct spoolss_DriverInfo8
*info
= NULL
;
2211 struct dcerpc_binding_handle
*b
;
2212 TALLOC_CTX
*tmp_ctx
= NULL
;
2216 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2217 and not a printer admin, then fail */
2219 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
2220 !security_token_has_privilege(p
->session_info
->security_token
,
2221 SEC_PRIV_PRINT_OPERATOR
)) {
2222 return WERR_ACCESS_DENIED
;
2225 /* check that we have a valid driver name first */
2226 if (get_version_id(r
->in
.architecture
) == -1) {
2227 /* this is what NT returns */
2228 return WERR_INVALID_ENVIRONMENT
;
2231 tmp_ctx
= talloc_new(p
->mem_ctx
);
2236 status
= winreg_printer_binding_handle(tmp_ctx
,
2237 get_session_info_system(),
2240 if (!W_ERROR_IS_OK(status
)) {
2244 for (found
= false, i
= 0; drv_cversion
[i
] >= 0; i
++) {
2245 if ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
2246 && (drv_cversion
[i
] != r
->in
.version
)) {
2250 /* check if a driver with this version exists before delete */
2251 status
= winreg_get_driver(tmp_ctx
, b
,
2252 r
->in
.architecture
, r
->in
.driver
,
2253 drv_cversion
[i
], &info
);
2254 if (!W_ERROR_IS_OK(status
)) {
2255 DEBUG(5, ("skipping del of driver with version %d\n",
2261 status
= spoolss_dpd_version(tmp_ctx
, p
, r
, b
, info
);
2262 if (!W_ERROR_IS_OK(status
)) {
2263 DEBUG(0, ("failed to delete driver with version %d\n",
2268 if (found
== false) {
2269 DEBUG(0, ("driver %s not found for deletion\n", r
->in
.driver
));
2270 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2276 talloc_free(tmp_ctx
);
2281 /********************************************************************
2282 GetPrinterData on a printer server Handle.
2283 ********************************************************************/
2285 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2287 enum winreg_Type
*type
,
2288 union spoolss_PrinterData
*data
)
2290 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2292 if (!strcasecmp_m(value
, "W3SvcInstalled")) {
2294 SIVAL(&data
->value
, 0, 0x00);
2298 if (!strcasecmp_m(value
, "BeepEnabled")) {
2300 SIVAL(&data
->value
, 0, 0x00);
2304 if (!strcasecmp_m(value
, "EventLog")) {
2306 /* formally was 0x1b */
2307 SIVAL(&data
->value
, 0, 0x00);
2311 if (!strcasecmp_m(value
, "NetPopup")) {
2313 SIVAL(&data
->value
, 0, 0x00);
2317 if (!strcasecmp_m(value
, "MajorVersion")) {
2320 /* Windows NT 4.0 seems to not allow uploading of drivers
2321 to a server that reports 0x3 as the MajorVersion.
2322 need to investigate more how Win2k gets around this .
2325 if (RA_WINNT
== get_remote_arch()) {
2326 SIVAL(&data
->value
, 0, 0x02);
2328 SIVAL(&data
->value
, 0, 0x03);
2334 if (!strcasecmp_m(value
, "MinorVersion")) {
2336 SIVAL(&data
->value
, 0, 0x00);
2341 * uint32_t size = 0x114
2342 * uint32_t major = 5
2343 * uint32_t minor = [0|1]
2344 * uint32_t build = [2195|2600]
2345 * extra unicode string = e.g. "Service Pack 3"
2347 if (!strcasecmp_m(value
, "OSVersion")) {
2349 enum ndr_err_code ndr_err
;
2350 struct spoolss_OSVersion os
;
2352 os
.major
= lp_parm_int(GLOBAL_SECTION_SNUM
,
2353 "spoolss", "os_major", 5);
2354 /* Windows 2000 == 5.0 */
2355 os
.minor
= lp_parm_int(GLOBAL_SECTION_SNUM
,
2356 "spoolss", "os_minor", 0);
2357 os
.build
= lp_parm_int(GLOBAL_SECTION_SNUM
,
2358 "spoolss", "os_build", 2195);
2359 os
.extra_string
= ""; /* leave extra string empty */
2361 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &os
,
2362 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2363 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2364 return WERR_GENERAL_FAILURE
;
2367 if (DEBUGLEVEL
>= 10) {
2368 NDR_PRINT_DEBUG(spoolss_OSVersion
, &os
);
2372 data
->binary
= blob
;
2378 if (!strcasecmp_m(value
, "DefaultSpoolDirectory")) {
2381 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2382 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2387 if (!strcasecmp_m(value
, "Architecture")) {
2389 data
->string
= talloc_strdup(mem_ctx
,
2390 lp_parm_const_string(GLOBAL_SECTION_SNUM
, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86
));
2391 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2396 if (!strcasecmp_m(value
, "DsPresent")) {
2399 /* only show the publish check box if we are a
2400 member of a AD domain */
2402 if (lp_security() == SEC_ADS
) {
2403 SIVAL(&data
->value
, 0, 0x01);
2405 SIVAL(&data
->value
, 0, 0x00);
2410 if (!strcasecmp_m(value
, "DNSMachineName")) {
2411 const char *hostname
= get_mydnsfullname();
2414 return WERR_BADFILE
;
2418 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2419 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2426 return WERR_INVALID_PARAM
;
2429 /****************************************************************
2430 _spoolss_GetPrinterData
2431 ****************************************************************/
2433 WERROR
_spoolss_GetPrinterData(struct pipes_struct
*p
,
2434 struct spoolss_GetPrinterData
*r
)
2436 struct spoolss_GetPrinterDataEx r2
;
2438 r2
.in
.handle
= r
->in
.handle
;
2439 r2
.in
.key_name
= "PrinterDriverData";
2440 r2
.in
.value_name
= r
->in
.value_name
;
2441 r2
.in
.offered
= r
->in
.offered
;
2442 r2
.out
.type
= r
->out
.type
;
2443 r2
.out
.data
= r
->out
.data
;
2444 r2
.out
.needed
= r
->out
.needed
;
2446 return _spoolss_GetPrinterDataEx(p
, &r2
);
2449 /*********************************************************
2450 Connect to the client machine.
2451 **********************************************************/
2453 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2454 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2457 struct cli_state
*the_cli
;
2458 struct sockaddr_storage rm_addr
;
2459 char addr
[INET6_ADDRSTRLEN
];
2461 if ( is_zero_addr(client_ss
) ) {
2462 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2464 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20, false) ) {
2465 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2468 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2470 rm_addr
= *client_ss
;
2471 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2472 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2476 if (ismyaddr((struct sockaddr
*)(void *)&rm_addr
)) {
2477 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2482 /* setup the connection */
2483 ret
= cli_full_connection( &the_cli
, lp_netbios_name(), remote_machine
,
2484 &rm_addr
, 0, "IPC$", "IPC",
2488 0, lp_client_signing());
2490 if ( !NT_STATUS_IS_OK( ret
) ) {
2491 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2496 if ( smbXcli_conn_protocol(the_cli
->conn
) != PROTOCOL_NT1
) {
2497 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2498 cli_shutdown(the_cli
);
2503 * Ok - we have an anonymous connection to the IPC$ share.
2504 * Now start the NT Domain stuff :-).
2507 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2508 if (!NT_STATUS_IS_OK(ret
)) {
2509 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2510 remote_machine
, nt_errstr(ret
)));
2511 cli_shutdown(the_cli
);
2518 /***************************************************************************
2519 Connect to the client.
2520 ****************************************************************************/
2522 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2523 uint32_t localprinter
,
2524 enum winreg_Type type
,
2525 struct policy_handle
*handle
,
2526 struct notify_back_channel
**_chan
,
2527 struct sockaddr_storage
*client_ss
,
2528 struct messaging_context
*msg_ctx
)
2532 struct notify_back_channel
*chan
;
2534 for (chan
= back_channels
; chan
; chan
= chan
->next
) {
2535 if (memcmp(&chan
->client_address
, client_ss
,
2536 sizeof(struct sockaddr_storage
)) == 0) {
2542 * If it's the first connection, contact the client
2543 * and connect to the IPC$ share anonymously
2546 fstring unix_printer
;
2548 /* the +2 is to strip the leading 2 backslashs */
2549 fstrcpy(unix_printer
, printer
+ 2);
2551 chan
= talloc_zero(NULL
, struct notify_back_channel
);
2555 chan
->client_address
= *client_ss
;
2557 if (!spoolss_connect_to_client(&chan
->cli_pipe
, client_ss
, unix_printer
)) {
2562 DLIST_ADD(back_channels
, chan
);
2564 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_NOTIFY2
,
2565 receive_notify2_message_list
);
2568 if (chan
->cli_pipe
== NULL
||
2569 chan
->cli_pipe
->binding_handle
== NULL
) {
2570 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2571 "NULL %s for printer %s\n",
2572 chan
->cli_pipe
== NULL
?
2573 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2579 * Tell the specific printing tdb we want messages for this printer
2580 * by registering our PID.
2583 if (!print_notify_register_pid(snum
)) {
2584 DEBUG(0, ("Failed to register our pid for printer %s\n",
2588 status
= dcerpc_spoolss_ReplyOpenPrinter(chan
->cli_pipe
->binding_handle
,
2597 if (!NT_STATUS_IS_OK(status
)) {
2598 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status
)));
2599 result
= ntstatus_to_werror(status
);
2600 } else if (!W_ERROR_IS_OK(result
)) {
2601 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result
)));
2604 chan
->active_connections
++;
2607 return (W_ERROR_IS_OK(result
));
2610 /****************************************************************
2611 ****************************************************************/
2613 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2614 const struct spoolss_NotifyOption
*r
)
2616 struct spoolss_NotifyOption
*option
;
2623 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2630 if (!option
->count
) {
2634 option
->types
= talloc_zero_array(option
,
2635 struct spoolss_NotifyOptionType
, option
->count
);
2636 if (!option
->types
) {
2637 talloc_free(option
);
2641 for (i
=0; i
< option
->count
; i
++) {
2642 option
->types
[i
] = r
->types
[i
];
2644 if (option
->types
[i
].count
) {
2645 option
->types
[i
].fields
= talloc_zero_array(option
,
2646 union spoolss_Field
, option
->types
[i
].count
);
2647 if (!option
->types
[i
].fields
) {
2648 talloc_free(option
);
2651 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2652 option
->types
[i
].fields
[k
] =
2653 r
->types
[i
].fields
[k
];
2661 /****************************************************************
2662 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2664 * before replying OK: status=0 a rpc call is made to the workstation
2665 * asking ReplyOpenPrinter
2667 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2668 * called from api_spoolss_rffpcnex
2669 ****************************************************************/
2671 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct
*p
,
2672 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2675 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2676 struct sockaddr_storage client_ss
;
2679 /* store the notify value in the printer struct */
2681 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2684 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2685 "Invalid handle (%s:%u:%u).\n",
2686 OUR_HANDLE(r
->in
.handle
)));
2690 Printer
->notify
.flags
= r
->in
.flags
;
2691 Printer
->notify
.options
= r
->in
.options
;
2692 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2693 Printer
->notify
.msg_ctx
= p
->msg_ctx
;
2695 TALLOC_FREE(Printer
->notify
.option
);
2696 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2698 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2700 /* Connect to the client machine and send a ReplyOpenPrinter */
2702 if ( Printer
->printer_type
== SPLHND_SERVER
)
2704 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2705 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2708 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2709 "remote_address is %s\n",
2710 tsocket_address_string(p
->remote_address
, p
->mem_ctx
)));
2712 if (!lp_print_notify_backchannel(snum
)) {
2713 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2714 "backchannel disabled\n"));
2715 return WERR_SERVER_UNAVAILABLE
;
2718 client_len
= tsocket_address_bsd_sockaddr(p
->remote_address
,
2719 (struct sockaddr
*) &client_ss
,
2720 sizeof(struct sockaddr_storage
));
2721 if (client_len
< 0) {
2725 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2726 Printer
->notify
.printerlocal
, REG_SZ
,
2727 &Printer
->notify
.cli_hnd
,
2728 &Printer
->notify
.cli_chan
,
2729 &client_ss
, p
->msg_ctx
)) {
2730 return WERR_SERVER_UNAVAILABLE
;
2736 /*******************************************************************
2737 * fill a notify_info_data with the servername
2738 ********************************************************************/
2740 static void spoolss_notify_server_name(struct messaging_context
*msg_ctx
,
2742 struct spoolss_Notify
*data
,
2743 print_queue_struct
*queue
,
2744 struct spoolss_PrinterInfo2
*pinfo2
,
2745 TALLOC_CTX
*mem_ctx
)
2747 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->servername
);
2750 /*******************************************************************
2751 * fill a notify_info_data with the printername (not including the servername).
2752 ********************************************************************/
2754 static void spoolss_notify_printer_name(struct messaging_context
*msg_ctx
,
2756 struct spoolss_Notify
*data
,
2757 print_queue_struct
*queue
,
2758 struct spoolss_PrinterInfo2
*pinfo2
,
2759 TALLOC_CTX
*mem_ctx
)
2761 /* the notify name should not contain the \\server\ part */
2762 const char *p
= strrchr(pinfo2
->printername
, '\\');
2765 p
= pinfo2
->printername
;
2770 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2773 /*******************************************************************
2774 * fill a notify_info_data with the servicename
2775 ********************************************************************/
2777 static void spoolss_notify_share_name(struct messaging_context
*msg_ctx
,
2779 struct spoolss_Notify
*data
,
2780 print_queue_struct
*queue
,
2781 struct spoolss_PrinterInfo2
*pinfo2
,
2782 TALLOC_CTX
*mem_ctx
)
2784 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(talloc_tos(), snum
));
2787 /*******************************************************************
2788 * fill a notify_info_data with the port name
2789 ********************************************************************/
2791 static void spoolss_notify_port_name(struct messaging_context
*msg_ctx
,
2793 struct spoolss_Notify
*data
,
2794 print_queue_struct
*queue
,
2795 struct spoolss_PrinterInfo2
*pinfo2
,
2796 TALLOC_CTX
*mem_ctx
)
2798 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->portname
);
2801 /*******************************************************************
2802 * fill a notify_info_data with the printername
2803 * but it doesn't exist, have to see what to do
2804 ********************************************************************/
2806 static void spoolss_notify_driver_name(struct messaging_context
*msg_ctx
,
2808 struct spoolss_Notify
*data
,
2809 print_queue_struct
*queue
,
2810 struct spoolss_PrinterInfo2
*pinfo2
,
2811 TALLOC_CTX
*mem_ctx
)
2813 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->drivername
);
2816 /*******************************************************************
2817 * fill a notify_info_data with the comment
2818 ********************************************************************/
2820 static void spoolss_notify_comment(struct messaging_context
*msg_ctx
,
2822 struct spoolss_Notify
*data
,
2823 print_queue_struct
*queue
,
2824 struct spoolss_PrinterInfo2
*pinfo2
,
2825 TALLOC_CTX
*mem_ctx
)
2829 if (*pinfo2
->comment
== '\0') {
2830 p
= lp_comment(talloc_tos(), snum
);
2832 p
= pinfo2
->comment
;
2835 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2838 /*******************************************************************
2839 * fill a notify_info_data with the comment
2840 * location = "Room 1, floor 2, building 3"
2841 ********************************************************************/
2843 static void spoolss_notify_location(struct messaging_context
*msg_ctx
,
2845 struct spoolss_Notify
*data
,
2846 print_queue_struct
*queue
,
2847 struct spoolss_PrinterInfo2
*pinfo2
,
2848 TALLOC_CTX
*mem_ctx
)
2850 const char *loc
= pinfo2
->location
;
2853 status
= printer_list_get_printer(mem_ctx
,
2858 if (NT_STATUS_IS_OK(status
)) {
2860 loc
= pinfo2
->location
;
2864 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, loc
);
2867 /*******************************************************************
2868 * fill a notify_info_data with the device mode
2869 * jfm:xxxx don't to it for know but that's a real problem !!!
2870 ********************************************************************/
2872 static void spoolss_notify_devmode(struct messaging_context
*msg_ctx
,
2874 struct spoolss_Notify
*data
,
2875 print_queue_struct
*queue
,
2876 struct spoolss_PrinterInfo2
*pinfo2
,
2877 TALLOC_CTX
*mem_ctx
)
2879 /* for a dummy implementation we have to zero the fields */
2880 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2883 /*******************************************************************
2884 * fill a notify_info_data with the separator file name
2885 ********************************************************************/
2887 static void spoolss_notify_sepfile(struct messaging_context
*msg_ctx
,
2889 struct spoolss_Notify
*data
,
2890 print_queue_struct
*queue
,
2891 struct spoolss_PrinterInfo2
*pinfo2
,
2892 TALLOC_CTX
*mem_ctx
)
2894 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->sepfile
);
2897 /*******************************************************************
2898 * fill a notify_info_data with the print processor
2899 * jfm:xxxx return always winprint to indicate we don't do anything to it
2900 ********************************************************************/
2902 static void spoolss_notify_print_processor(struct messaging_context
*msg_ctx
,
2904 struct spoolss_Notify
*data
,
2905 print_queue_struct
*queue
,
2906 struct spoolss_PrinterInfo2
*pinfo2
,
2907 TALLOC_CTX
*mem_ctx
)
2909 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->printprocessor
);
2912 /*******************************************************************
2913 * fill a notify_info_data with the print processor options
2914 * jfm:xxxx send an empty string
2915 ********************************************************************/
2917 static void spoolss_notify_parameters(struct messaging_context
*msg_ctx
,
2919 struct spoolss_Notify
*data
,
2920 print_queue_struct
*queue
,
2921 struct spoolss_PrinterInfo2
*pinfo2
,
2922 TALLOC_CTX
*mem_ctx
)
2924 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->parameters
);
2927 /*******************************************************************
2928 * fill a notify_info_data with the data type
2929 * jfm:xxxx always send RAW as data type
2930 ********************************************************************/
2932 static void spoolss_notify_datatype(struct messaging_context
*msg_ctx
,
2934 struct spoolss_Notify
*data
,
2935 print_queue_struct
*queue
,
2936 struct spoolss_PrinterInfo2
*pinfo2
,
2937 TALLOC_CTX
*mem_ctx
)
2939 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->datatype
);
2942 /*******************************************************************
2943 * fill a notify_info_data with the security descriptor
2944 * jfm:xxxx send an null pointer to say no security desc
2945 * have to implement security before !
2946 ********************************************************************/
2948 static void spoolss_notify_security_desc(struct messaging_context
*msg_ctx
,
2950 struct spoolss_Notify
*data
,
2951 print_queue_struct
*queue
,
2952 struct spoolss_PrinterInfo2
*pinfo2
,
2953 TALLOC_CTX
*mem_ctx
)
2955 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
, pinfo2
->secdesc
);
2958 /*******************************************************************
2959 * fill a notify_info_data with the attributes
2960 * jfm:xxxx a samba printer is always shared
2961 ********************************************************************/
2963 static void spoolss_notify_attributes(struct messaging_context
*msg_ctx
,
2965 struct spoolss_Notify
*data
,
2966 print_queue_struct
*queue
,
2967 struct spoolss_PrinterInfo2
*pinfo2
,
2968 TALLOC_CTX
*mem_ctx
)
2970 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->attributes
);
2973 /*******************************************************************
2974 * fill a notify_info_data with the priority
2975 ********************************************************************/
2977 static void spoolss_notify_priority(struct messaging_context
*msg_ctx
,
2979 struct spoolss_Notify
*data
,
2980 print_queue_struct
*queue
,
2981 struct spoolss_PrinterInfo2
*pinfo2
,
2982 TALLOC_CTX
*mem_ctx
)
2984 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->priority
);
2987 /*******************************************************************
2988 * fill a notify_info_data with the default priority
2989 ********************************************************************/
2991 static void spoolss_notify_default_priority(struct messaging_context
*msg_ctx
,
2993 struct spoolss_Notify
*data
,
2994 print_queue_struct
*queue
,
2995 struct spoolss_PrinterInfo2
*pinfo2
,
2996 TALLOC_CTX
*mem_ctx
)
2998 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->defaultpriority
);
3001 /*******************************************************************
3002 * fill a notify_info_data with the start time
3003 ********************************************************************/
3005 static void spoolss_notify_start_time(struct messaging_context
*msg_ctx
,
3007 struct spoolss_Notify
*data
,
3008 print_queue_struct
*queue
,
3009 struct spoolss_PrinterInfo2
*pinfo2
,
3010 TALLOC_CTX
*mem_ctx
)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->starttime
);
3015 /*******************************************************************
3016 * fill a notify_info_data with the until time
3017 ********************************************************************/
3019 static void spoolss_notify_until_time(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
->untiltime
);
3029 /*******************************************************************
3030 * fill a notify_info_data with the status
3031 ********************************************************************/
3033 static void spoolss_notify_status(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 print_status_struct status
;
3042 print_queue_length(msg_ctx
, snum
, &status
);
3043 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
3046 /*******************************************************************
3047 * fill a notify_info_data with the number of jobs queued
3048 ********************************************************************/
3050 static void spoolss_notify_cjobs(struct messaging_context
*msg_ctx
,
3052 struct spoolss_Notify
*data
,
3053 print_queue_struct
*queue
,
3054 struct spoolss_PrinterInfo2
*pinfo2
,
3055 TALLOC_CTX
*mem_ctx
)
3057 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3058 data
, print_queue_length(msg_ctx
, snum
, NULL
));
3061 /*******************************************************************
3062 * fill a notify_info_data with the average ppm
3063 ********************************************************************/
3065 static void spoolss_notify_average_ppm(struct messaging_context
*msg_ctx
,
3067 struct spoolss_Notify
*data
,
3068 print_queue_struct
*queue
,
3069 struct spoolss_PrinterInfo2
*pinfo2
,
3070 TALLOC_CTX
*mem_ctx
)
3072 /* always respond 8 pages per minutes */
3073 /* a little hard ! */
3074 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->averageppm
);
3077 /*******************************************************************
3078 * fill a notify_info_data with username
3079 ********************************************************************/
3081 static void spoolss_notify_username(struct messaging_context
*msg_ctx
,
3083 struct spoolss_Notify
*data
,
3084 print_queue_struct
*queue
,
3085 struct spoolss_PrinterInfo2
*pinfo2
,
3086 TALLOC_CTX
*mem_ctx
)
3088 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
3091 /*******************************************************************
3092 * fill a notify_info_data with job status
3093 ********************************************************************/
3095 static void spoolss_notify_job_status(struct messaging_context
*msg_ctx
,
3097 struct spoolss_Notify
*data
,
3098 print_queue_struct
*queue
,
3099 struct spoolss_PrinterInfo2
*pinfo2
,
3100 TALLOC_CTX
*mem_ctx
)
3102 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
3105 /*******************************************************************
3106 * fill a notify_info_data with job name
3107 ********************************************************************/
3109 static void spoolss_notify_job_name(struct messaging_context
*msg_ctx
,
3111 struct spoolss_Notify
*data
,
3112 print_queue_struct
*queue
,
3113 struct spoolss_PrinterInfo2
*pinfo2
,
3114 TALLOC_CTX
*mem_ctx
)
3116 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
3119 /*******************************************************************
3120 * fill a notify_info_data with job status
3121 ********************************************************************/
3123 static void spoolss_notify_job_status_string(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
)
3131 * Now we're returning job status codes we just return a "" here. JRA.
3136 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3139 switch (queue
->status
) {
3144 p
= ""; /* NT provides the paused string */
3153 #endif /* NO LONGER NEEDED. */
3155 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
3158 /*******************************************************************
3159 * fill a notify_info_data with job time
3160 ********************************************************************/
3162 static void spoolss_notify_job_time(struct messaging_context
*msg_ctx
,
3164 struct spoolss_Notify
*data
,
3165 print_queue_struct
*queue
,
3166 struct spoolss_PrinterInfo2
*pinfo2
,
3167 TALLOC_CTX
*mem_ctx
)
3169 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3172 /*******************************************************************
3173 * fill a notify_info_data with job size
3174 ********************************************************************/
3176 static void spoolss_notify_job_size(struct messaging_context
*msg_ctx
,
3178 struct spoolss_Notify
*data
,
3179 print_queue_struct
*queue
,
3180 struct spoolss_PrinterInfo2
*pinfo2
,
3181 TALLOC_CTX
*mem_ctx
)
3183 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
3186 /*******************************************************************
3187 * fill a notify_info_data with page info
3188 ********************************************************************/
3189 static void spoolss_notify_total_pages(struct messaging_context
*msg_ctx
,
3191 struct spoolss_Notify
*data
,
3192 print_queue_struct
*queue
,
3193 struct spoolss_PrinterInfo2
*pinfo2
,
3194 TALLOC_CTX
*mem_ctx
)
3196 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
3199 /*******************************************************************
3200 * fill a notify_info_data with pages printed info.
3201 ********************************************************************/
3202 static void spoolss_notify_pages_printed(struct messaging_context
*msg_ctx
,
3204 struct spoolss_Notify
*data
,
3205 print_queue_struct
*queue
,
3206 struct spoolss_PrinterInfo2
*pinfo2
,
3207 TALLOC_CTX
*mem_ctx
)
3209 /* Add code when back-end tracks this */
3210 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3213 /*******************************************************************
3214 Fill a notify_info_data with job position.
3215 ********************************************************************/
3217 static void spoolss_notify_job_position(struct messaging_context
*msg_ctx
,
3219 struct spoolss_Notify
*data
,
3220 print_queue_struct
*queue
,
3221 struct spoolss_PrinterInfo2
*pinfo2
,
3222 TALLOC_CTX
*mem_ctx
)
3224 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->sysjob
);
3227 /*******************************************************************
3228 Fill a notify_info_data with submitted time.
3229 ********************************************************************/
3231 static void spoolss_notify_submitted_time(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 data
->data
.string
.string
= NULL
;
3239 data
->data
.string
.size
= 0;
3241 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
3242 &data
->data
.string
.string
,
3243 &data
->data
.string
.size
);
3247 struct s_notify_info_data_table
3249 enum spoolss_NotifyType type
;
3252 enum spoolss_NotifyTable variable_type
;
3253 void (*fn
) (struct messaging_context
*msg_ctx
,
3254 int snum
, struct spoolss_Notify
*data
,
3255 print_queue_struct
*queue
,
3256 struct spoolss_PrinterInfo2
*pinfo2
,
3257 TALLOC_CTX
*mem_ctx
);
3260 /* A table describing the various print notification constants and
3261 whether the notification data is a pointer to a variable sized
3262 buffer, a one value uint32_t or a two value uint32_t. */
3264 static const struct s_notify_info_data_table notify_info_data_table
[] =
3266 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3267 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3268 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
3269 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3270 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3271 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
3272 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
3273 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3274 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
3275 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3276 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3277 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3278 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
3279 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
3280 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3281 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
3282 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3283 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3284 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
3285 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
3286 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
3287 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3288 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3289 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3290 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3291 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3292 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3293 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3294 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3295 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3296 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3297 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3298 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3299 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3300 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3301 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3302 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3303 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3304 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3305 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3306 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3307 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3308 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3309 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3310 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3311 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3312 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3313 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3314 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3317 /*******************************************************************
3318 Return the variable_type of info_data structure.
3319 ********************************************************************/
3321 static enum spoolss_NotifyTable
variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3326 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3327 if ( (notify_info_data_table
[i
].type
== type
) &&
3328 (notify_info_data_table
[i
].field
== field
) ) {
3329 return notify_info_data_table
[i
].variable_type
;
3333 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3335 return (enum spoolss_NotifyTable
) 0;
3338 /****************************************************************************
3339 ****************************************************************************/
3341 static bool search_notify(enum spoolss_NotifyType type
,
3347 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3348 if (notify_info_data_table
[i
].type
== type
&&
3349 notify_info_data_table
[i
].field
== field
&&
3350 notify_info_data_table
[i
].fn
!= NULL
) {
3359 /****************************************************************************
3360 ****************************************************************************/
3362 static void construct_info_data(struct spoolss_Notify
*info_data
,
3363 enum spoolss_NotifyType type
,
3364 uint16_t field
, int id
)
3366 info_data
->type
= type
;
3367 info_data
->field
.field
= field
;
3368 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3369 info_data
->job_id
= id
;
3372 /*******************************************************************
3374 * fill a notify_info struct with info asked
3376 ********************************************************************/
3378 static bool construct_notify_printer_info(struct messaging_context
*msg_ctx
,
3379 struct printer_handle
*print_hnd
,
3380 struct spoolss_NotifyInfo
*info
,
3381 struct spoolss_PrinterInfo2
*pinfo2
,
3383 const struct spoolss_NotifyOptionType
*option_type
,
3385 TALLOC_CTX
*mem_ctx
)
3388 enum spoolss_NotifyType type
;
3391 struct spoolss_Notify
*current_data
;
3393 type
= option_type
->type
;
3395 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3396 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3397 option_type
->count
, lp_servicename(talloc_tos(), snum
)));
3399 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3400 field
= option_type
->fields
[field_num
].field
;
3402 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3404 if (!search_notify(type
, field
, &j
) )
3407 info
->notifies
= talloc_realloc(info
, info
->notifies
,
3408 struct spoolss_Notify
,
3410 if (info
->notifies
== NULL
) {
3411 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3415 current_data
= &info
->notifies
[info
->count
];
3417 construct_info_data(current_data
, type
, field
, id
);
3419 DEBUG(10, ("construct_notify_printer_info: "
3420 "calling [%s] snum=%d printername=[%s])\n",
3421 notify_info_data_table
[j
].name
, snum
,
3422 pinfo2
->printername
));
3424 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3425 NULL
, pinfo2
, mem_ctx
);
3433 /*******************************************************************
3435 * fill a notify_info struct with info asked
3437 ********************************************************************/
3439 static bool construct_notify_jobs_info(struct messaging_context
*msg_ctx
,
3440 print_queue_struct
*queue
,
3441 struct spoolss_NotifyInfo
*info
,
3442 struct spoolss_PrinterInfo2
*pinfo2
,
3444 const struct spoolss_NotifyOptionType
*option_type
,
3446 TALLOC_CTX
*mem_ctx
)
3449 enum spoolss_NotifyType type
;
3451 struct spoolss_Notify
*current_data
;
3453 DEBUG(4,("construct_notify_jobs_info\n"));
3455 type
= option_type
->type
;
3457 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3458 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3459 option_type
->count
));
3461 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3462 field
= option_type
->fields
[field_num
].field
;
3464 if (!search_notify(type
, field
, &j
) )
3467 info
->notifies
= talloc_realloc(info
, info
->notifies
,
3468 struct spoolss_Notify
,
3470 if (info
->notifies
== NULL
) {
3471 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3475 current_data
=&(info
->notifies
[info
->count
]);
3477 construct_info_data(current_data
, type
, field
, id
);
3478 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3479 queue
, pinfo2
, mem_ctx
);
3487 * JFM: The enumeration is not that simple, it's even non obvious.
3489 * let's take an example: I want to monitor the PRINTER SERVER for
3490 * the printer's name and the number of jobs currently queued.
3491 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3492 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3494 * I have 3 printers on the back of my server.
3496 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3499 * 1 printer 1 name 1
3500 * 2 printer 1 cjob 1
3501 * 3 printer 2 name 2
3502 * 4 printer 2 cjob 2
3503 * 5 printer 3 name 3
3504 * 6 printer 3 name 3
3506 * that's the print server case, the printer case is even worse.
3509 /*******************************************************************
3511 * enumerate all printers on the printserver
3512 * fill a notify_info struct with info asked
3514 ********************************************************************/
3516 static WERROR
printserver_notify_info(struct pipes_struct
*p
,
3517 struct policy_handle
*hnd
,
3518 struct spoolss_NotifyInfo
*info
,
3519 TALLOC_CTX
*mem_ctx
)
3522 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3523 int n_services
=lp_numservices();
3525 struct spoolss_NotifyOption
*option
;
3526 struct spoolss_NotifyOptionType option_type
;
3527 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3530 DEBUG(4,("printserver_notify_info\n"));
3535 option
= Printer
->notify
.option
;
3538 info
->notifies
= NULL
;
3541 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3542 sending a ffpcn() request first */
3547 for (i
=0; i
<option
->count
; i
++) {
3548 option_type
= option
->types
[i
];
3550 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3553 for (snum
= 0; snum
< n_services
; snum
++) {
3554 if (!lp_browseable(snum
) ||
3555 !lp_snum_ok(snum
) ||
3556 !lp_print_ok(snum
)) {
3557 continue; /* skip */
3560 /* Maybe we should use the SYSTEM session_info here... */
3561 result
= winreg_get_printer_internal(mem_ctx
,
3562 get_session_info_system(),
3564 lp_servicename(talloc_tos(), snum
),
3566 if (!W_ERROR_IS_OK(result
)) {
3567 DEBUG(4, ("printserver_notify_info: "
3568 "Failed to get printer [%s]\n",
3569 lp_servicename(talloc_tos(), snum
)));
3574 construct_notify_printer_info(p
->msg_ctx
,
3580 TALLOC_FREE(pinfo2
);
3586 * Debugging information, don't delete.
3589 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3590 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3591 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3593 for (i
=0; i
<info
->count
; i
++) {
3594 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3595 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3596 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3603 /*******************************************************************
3605 * fill a notify_info struct with info asked
3607 ********************************************************************/
3609 static WERROR
printer_notify_info(struct pipes_struct
*p
,
3610 struct policy_handle
*hnd
,
3611 struct spoolss_NotifyInfo
*info
,
3612 TALLOC_CTX
*mem_ctx
)
3615 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3618 struct spoolss_NotifyOption
*option
;
3619 struct spoolss_NotifyOptionType option_type
;
3621 print_queue_struct
*queue
=NULL
;
3622 print_status_struct status
;
3623 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3625 struct tdb_print_db
*pdb
;
3627 DEBUG(4,("printer_notify_info\n"));
3632 option
= Printer
->notify
.option
;
3636 info
->notifies
= NULL
;
3639 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3640 sending a ffpcn() request first */
3645 if (!get_printer_snum(p
, hnd
, &snum
, NULL
)) {
3649 pdb
= get_print_db_byname(Printer
->sharename
);
3654 /* Maybe we should use the SYSTEM session_info here... */
3655 result
= winreg_get_printer_internal(mem_ctx
,
3656 get_session_info_system(),
3658 lp_servicename(talloc_tos(), snum
), &pinfo2
);
3659 if (!W_ERROR_IS_OK(result
)) {
3660 result
= WERR_BADFID
;
3665 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3666 * correct servername.
3668 pinfo2
->servername
= talloc_strdup(pinfo2
, Printer
->servername
);
3669 if (pinfo2
->servername
== NULL
) {
3670 result
= WERR_NOMEM
;
3674 for (i
= 0; i
< option
->count
; i
++) {
3675 option_type
= option
->types
[i
];
3677 switch (option_type
.type
) {
3678 case PRINTER_NOTIFY_TYPE
:
3679 if (construct_notify_printer_info(p
->msg_ctx
,
3688 case JOB_NOTIFY_TYPE
:
3690 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
,
3693 for (j
= 0; j
< count
; j
++) {
3695 jobid
= sysjob_to_jobid_pdb(pdb
,
3697 if (jobid
== (uint32_t)-1) {
3698 DEBUG(2, ("ignoring untracked job %d\n",
3702 /* FIXME check return value */
3703 construct_notify_jobs_info(p
->msg_ctx
,
3717 * Debugging information, don't delete.
3720 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3721 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3722 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3724 for (i=0; i<info->count; i++) {
3725 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3726 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3727 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3731 talloc_free(pinfo2
);
3734 release_print_db(pdb
);
3738 /****************************************************************
3739 _spoolss_RouterRefreshPrinterChangeNotify
3740 ****************************************************************/
3742 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct
*p
,
3743 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3745 struct spoolss_NotifyInfo
*info
;
3747 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3748 WERROR result
= WERR_BADFID
;
3750 /* we always have a spoolss_NotifyInfo struct */
3751 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3753 result
= WERR_NOMEM
;
3757 *r
->out
.info
= info
;
3760 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3761 "Invalid handle (%s:%u:%u).\n",
3762 OUR_HANDLE(r
->in
.handle
)));
3766 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3769 * We are now using the change value, and
3770 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3771 * I don't have a global notification system, I'm sending back all the
3772 * information even when _NOTHING_ has changed.
3775 /* We need to keep track of the change value to send back in
3776 RRPCN replies otherwise our updates are ignored. */
3778 Printer
->notify
.fnpcn
= true;
3780 if (Printer
->notify
.cli_chan
!= NULL
&&
3781 Printer
->notify
.cli_chan
->active_connections
> 0) {
3782 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3783 "Saving change value in request [%x]\n",
3785 Printer
->notify
.change
= r
->in
.change_low
;
3788 /* just ignore the spoolss_NotifyOption */
3790 switch (Printer
->printer_type
) {
3792 result
= printserver_notify_info(p
, r
->in
.handle
,
3796 case SPLHND_PRINTER
:
3797 result
= printer_notify_info(p
, r
->in
.handle
,
3802 Printer
->notify
.fnpcn
= false;
3808 /********************************************************************
3809 ********************************************************************/
3811 static WERROR
create_printername(TALLOC_CTX
*mem_ctx
,
3812 const char *servername
,
3813 const char *printername
,
3814 const char **printername_p
)
3816 /* FIXME: add lp_force_printername() */
3818 if (servername
== NULL
) {
3819 *printername_p
= talloc_strdup(mem_ctx
, printername
);
3820 W_ERROR_HAVE_NO_MEMORY(*printername_p
);
3824 if (servername
[0] == '\\' && servername
[1] == '\\') {
3828 *printername_p
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s", servername
, printername
);
3829 W_ERROR_HAVE_NO_MEMORY(*printername_p
);
3834 /********************************************************************
3835 ********************************************************************/
3837 static void compose_devicemode_devicename(struct spoolss_DeviceMode
*dm
,
3838 const char *printername
)
3844 dm
->devicename
= talloc_strndup(dm
, printername
,
3845 MIN(strlen(printername
), 31));
3848 /********************************************************************
3849 * construct_printer_info_0
3850 * fill a printer_info_0 struct
3851 ********************************************************************/
3853 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3854 const struct auth_session_info
*session_info
,
3855 struct messaging_context
*msg_ctx
,
3856 struct spoolss_PrinterInfo2
*info2
,
3857 const char *servername
,
3858 struct spoolss_PrinterInfo0
*r
,
3862 struct printer_session_counter
*session_counter
;
3863 struct timeval setuptime
;
3864 print_status_struct status
;
3867 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
3868 if (!W_ERROR_IS_OK(result
)) {
3873 r
->servername
= talloc_strdup(mem_ctx
, servername
);
3874 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3876 r
->servername
= NULL
;
3879 count
= print_queue_length(msg_ctx
, snum
, &status
);
3881 /* check if we already have a counter for this printer */
3882 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3883 if (session_counter
->snum
== snum
)
3887 /* it's the first time, add it to the list */
3888 if (session_counter
== NULL
) {
3889 session_counter
= talloc_zero(counter_list
, struct printer_session_counter
);
3890 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3891 session_counter
->snum
= snum
;
3892 session_counter
->counter
= 0;
3893 DLIST_ADD(counter_list
, session_counter
);
3897 session_counter
->counter
++;
3903 get_startup_time(&setuptime
);
3904 init_systemtime(&r
->time
, gmtime(&setuptime
.tv_sec
));
3907 * the global_counter should be stored in a TDB as it's common to all the clients
3908 * and should be zeroed on samba startup
3910 r
->global_counter
= session_counter
->counter
;
3912 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3913 SSVAL(&r
->version
, 0, 0x0005); /* NT 5 */
3914 SSVAL(&r
->version
, 2, 0x0893); /* build 2195 */
3915 r
->free_build
= SPOOLSS_RELEASE_BUILD
;
3917 r
->max_spooling
= 0;
3918 r
->session_counter
= session_counter
->counter
;
3919 r
->num_error_out_of_paper
= 0x0;
3920 r
->num_error_not_ready
= 0x0; /* number of print failure */
3922 r
->number_of_processors
= 0x1;
3923 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3924 r
->high_part_total_bytes
= 0x0;
3926 /* ChangeID in milliseconds*/
3927 winreg_printer_get_changeid_internal(mem_ctx
, session_info
, msg_ctx
,
3928 info2
->sharename
, &r
->change_id
);
3930 r
->last_error
= WERR_OK
;
3931 r
->status
= nt_printq_status(status
.status
);
3932 r
->enumerate_network_printers
= 0x0;
3933 r
->c_setprinter
= 0x0;
3934 r
->processor_architecture
= PROCESSOR_ARCHITECTURE_INTEL
;
3935 r
->processor_level
= 0x6; /* 6 ???*/
3944 /********************************************************************
3945 * construct_printer_info1
3946 * fill a spoolss_PrinterInfo1 struct
3947 ********************************************************************/
3949 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
3950 const struct spoolss_PrinterInfo2
*info2
,
3952 const char *servername
,
3953 struct spoolss_PrinterInfo1
*r
,
3960 if (info2
->comment
== NULL
|| info2
->comment
[0] == '\0') {
3961 r
->comment
= lp_comment(mem_ctx
, snum
);
3963 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
); /* saved comment */
3965 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3967 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->name
);
3968 if (!W_ERROR_IS_OK(result
)) {
3972 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
3976 W_ERROR_HAVE_NO_MEMORY(r
->description
);
3981 /********************************************************************
3982 * construct_printer_info2
3983 * fill a spoolss_PrinterInfo2 struct
3984 ********************************************************************/
3986 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
3987 struct messaging_context
*msg_ctx
,
3988 const struct spoolss_PrinterInfo2
*info2
,
3989 const char *servername
,
3990 struct spoolss_PrinterInfo2
*r
,
3994 print_status_struct status
;
3997 count
= print_queue_length(msg_ctx
, snum
, &status
);
4000 r
->servername
= talloc_strdup(mem_ctx
, servername
);
4001 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4003 r
->servername
= NULL
;
4006 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4007 if (!W_ERROR_IS_OK(result
)) {
4011 r
->sharename
= lp_servicename(mem_ctx
, snum
);
4012 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
4013 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
4014 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4015 r
->drivername
= talloc_strdup(mem_ctx
, info2
->drivername
);
4016 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
4018 if (info2
->comment
[0] == '\0') {
4019 r
->comment
= lp_comment(mem_ctx
, snum
);
4021 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
);
4023 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
4025 r
->location
= talloc_strdup(mem_ctx
, info2
->location
);
4026 if (info2
->location
[0] == '\0') {
4027 const char *loc
= NULL
;
4030 nt_status
= printer_list_get_printer(mem_ctx
,
4035 if (NT_STATUS_IS_OK(nt_status
)) {
4037 r
->location
= talloc_strdup(mem_ctx
, loc
);
4041 W_ERROR_HAVE_NO_MEMORY(r
->location
);
4043 r
->sepfile
= talloc_strdup(mem_ctx
, info2
->sepfile
);
4044 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
4045 r
->printprocessor
= talloc_strdup(mem_ctx
, info2
->printprocessor
);
4046 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
4047 r
->datatype
= talloc_strdup(mem_ctx
, info2
->datatype
);
4048 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
4049 r
->parameters
= talloc_strdup(mem_ctx
, info2
->parameters
);
4050 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
4052 r
->attributes
= info2
->attributes
;
4054 r
->priority
= info2
->priority
;
4055 r
->defaultpriority
= info2
->defaultpriority
;
4056 r
->starttime
= info2
->starttime
;
4057 r
->untiltime
= info2
->untiltime
;
4058 r
->status
= nt_printq_status(status
.status
);
4060 r
->averageppm
= info2
->averageppm
;
4062 if (info2
->devmode
!= NULL
) {
4063 result
= copy_devicemode(mem_ctx
,
4066 if (!W_ERROR_IS_OK(result
)) {
4069 } else if (lp_default_devmode(snum
)) {
4070 result
= spoolss_create_default_devmode(mem_ctx
,
4073 if (!W_ERROR_IS_OK(result
)) {
4078 DEBUG(8,("Returning NULL Devicemode!\n"));
4081 compose_devicemode_devicename(r
->devmode
, r
->printername
);
4085 if (info2
->secdesc
!= NULL
) {
4086 /* don't use talloc_steal() here unless you do a deep steal of all
4087 the SEC_DESC members */
4089 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
4095 /********************************************************************
4096 * construct_printer_info3
4097 * fill a spoolss_PrinterInfo3 struct
4098 ********************************************************************/
4100 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
4101 const struct spoolss_PrinterInfo2
*info2
,
4102 const char *servername
,
4103 struct spoolss_PrinterInfo3
*r
,
4106 /* These are the components of the SD we are returning. */
4108 if (info2
->secdesc
!= NULL
) {
4109 /* don't use talloc_steal() here unless you do a deep steal of all
4110 the SEC_DESC members */
4112 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
4113 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
4119 /********************************************************************
4120 * construct_printer_info4
4121 * fill a spoolss_PrinterInfo4 struct
4122 ********************************************************************/
4124 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
4125 const struct spoolss_PrinterInfo2
*info2
,
4126 const char *servername
,
4127 struct spoolss_PrinterInfo4
*r
,
4132 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4133 if (!W_ERROR_IS_OK(result
)) {
4138 r
->servername
= talloc_strdup(mem_ctx
, servername
);
4139 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4141 r
->servername
= NULL
;
4144 r
->attributes
= info2
->attributes
;
4149 /********************************************************************
4150 * construct_printer_info5
4151 * fill a spoolss_PrinterInfo5 struct
4152 ********************************************************************/
4154 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
4155 const struct spoolss_PrinterInfo2
*info2
,
4156 const char *servername
,
4157 struct spoolss_PrinterInfo5
*r
,
4162 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4163 if (!W_ERROR_IS_OK(result
)) {
4167 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
4168 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4170 r
->attributes
= info2
->attributes
;
4172 /* these two are not used by NT+ according to MSDN */
4173 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4174 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4179 /********************************************************************
4180 * construct_printer_info_6
4181 * fill a spoolss_PrinterInfo6 struct
4182 ********************************************************************/
4184 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
4185 struct messaging_context
*msg_ctx
,
4186 const struct spoolss_PrinterInfo2
*info2
,
4187 const char *servername
,
4188 struct spoolss_PrinterInfo6
*r
,
4191 print_status_struct status
;
4193 print_queue_length(msg_ctx
, snum
, &status
);
4195 r
->status
= nt_printq_status(status
.status
);
4200 /********************************************************************
4201 * construct_printer_info7
4202 * fill a spoolss_PrinterInfo7 struct
4203 ********************************************************************/
4205 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
4206 struct messaging_context
*msg_ctx
,
4207 const char *servername
,
4208 struct spoolss_PrinterInfo7
*r
,
4211 const struct auth_session_info
*session_info
;
4214 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
4215 if (tmp_ctx
== NULL
) {
4219 session_info
= get_session_info_system();
4220 SMB_ASSERT(session_info
!= NULL
);
4222 printer
= lp_servicename(tmp_ctx
, snum
);
4223 if (printer
== NULL
) {
4224 DEBUG(0, ("invalid printer snum %d\n", snum
));
4225 werr
= WERR_INVALID_PARAM
;
4229 if (is_printer_published(tmp_ctx
, session_info
, msg_ctx
,
4230 servername
, printer
, NULL
)) {
4232 werr
= nt_printer_guid_get(tmp_ctx
, session_info
, msg_ctx
,
4234 if (!W_ERROR_IS_OK(werr
)) {
4236 * If we do not have a GUID entry in the registry, then
4237 * try to retrieve it from AD and store it now.
4239 werr
= nt_printer_guid_retrieve(tmp_ctx
, printer
,
4241 if (!W_ERROR_IS_OK(werr
)) {
4242 DEBUG(1, ("Failed to retrieve GUID for "
4243 "printer [%s] from AD - "
4244 "Is the the printer still "
4245 "published ?\n", printer
));
4249 werr
= nt_printer_guid_store(msg_ctx
, printer
, guid
);
4250 if (!W_ERROR_IS_OK(werr
)) {
4251 DEBUG(3, ("failed to store printer %s guid\n",
4255 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
4256 r
->action
= DSPRINT_PUBLISH
;
4258 r
->guid
= talloc_strdup(mem_ctx
, "");
4259 r
->action
= DSPRINT_UNPUBLISH
;
4261 if (r
->guid
== NULL
) {
4268 talloc_free(tmp_ctx
);
4272 /********************************************************************
4273 * construct_printer_info8
4274 * fill a spoolss_PrinterInfo8 struct
4275 ********************************************************************/
4277 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
4278 const struct spoolss_PrinterInfo2
*info2
,
4279 const char *servername
,
4280 struct spoolss_DeviceModeInfo
*r
,
4284 const char *printername
;
4286 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &printername
);
4287 if (!W_ERROR_IS_OK(result
)) {
4291 if (info2
->devmode
!= NULL
) {
4292 result
= copy_devicemode(mem_ctx
,
4295 if (!W_ERROR_IS_OK(result
)) {
4298 } else if (lp_default_devmode(snum
)) {
4299 result
= spoolss_create_default_devmode(mem_ctx
,
4302 if (!W_ERROR_IS_OK(result
)) {
4307 DEBUG(8,("Returning NULL Devicemode!\n"));
4310 compose_devicemode_devicename(r
->devmode
, printername
);
4315 /********************************************************************
4316 Spoolss_enumprinters.
4317 ********************************************************************/
4319 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
4320 const struct auth_session_info
*session_info
,
4321 struct messaging_context
*msg_ctx
,
4322 const char *servername
,
4325 union spoolss_PrinterInfo
**info_p
,
4330 union spoolss_PrinterInfo
*info
= NULL
;
4332 WERROR result
= WERR_OK
;
4333 struct dcerpc_binding_handle
*b
= NULL
;
4334 TALLOC_CTX
*tmp_ctx
= NULL
;
4336 tmp_ctx
= talloc_new(mem_ctx
);
4342 * printer shares are updated on client enumeration. The background
4343 * printer process updates printer_list.tdb at regular intervals.
4346 delete_and_reload_printers(server_event_context(), msg_ctx
);
4349 n_services
= lp_numservices();
4353 for (snum
= 0; snum
< n_services
; snum
++) {
4355 const char *printer
;
4356 struct spoolss_PrinterInfo2
*info2
;
4358 if (!snum_is_shared_printer(snum
)) {
4362 printer
= lp_const_servicename(snum
);
4364 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4368 result
= winreg_printer_binding_handle(tmp_ctx
,
4372 if (!W_ERROR_IS_OK(result
)) {
4377 result
= winreg_create_printer(tmp_ctx
, b
,
4379 if (!W_ERROR_IS_OK(result
)) {
4383 info
= talloc_realloc(tmp_ctx
, info
,
4384 union spoolss_PrinterInfo
,
4387 result
= WERR_NOMEM
;
4391 result
= winreg_get_printer(tmp_ctx
, b
,
4393 if (!W_ERROR_IS_OK(result
)) {
4399 result
= construct_printer_info0(info
, session_info
,
4402 &info
[count
].info0
, snum
);
4405 result
= construct_printer_info1(info
, info2
, flags
,
4407 &info
[count
].info1
, snum
);
4410 result
= construct_printer_info2(info
, msg_ctx
, info2
,
4412 &info
[count
].info2
, snum
);
4415 result
= construct_printer_info4(info
, info2
,
4417 &info
[count
].info4
, snum
);
4420 result
= construct_printer_info5(info
, info2
,
4422 &info
[count
].info5
, snum
);
4426 result
= WERR_UNKNOWN_LEVEL
;
4430 if (!W_ERROR_IS_OK(result
)) {
4438 if (W_ERROR_IS_OK(result
)) {
4439 *info_p
= talloc_move(mem_ctx
, &info
);
4443 talloc_free(tmp_ctx
);
4448 /********************************************************************
4449 * handle enumeration of printers at level 0
4450 ********************************************************************/
4452 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
4453 const struct auth_session_info
*session_info
,
4454 struct messaging_context
*msg_ctx
,
4456 const char *servername
,
4457 union spoolss_PrinterInfo
**info
,
4460 DEBUG(4,("enum_all_printers_info_0\n"));
4462 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4463 servername
, 0, flags
, info
, count
);
4467 /********************************************************************
4468 ********************************************************************/
4470 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4471 const struct auth_session_info
*session_info
,
4472 struct messaging_context
*msg_ctx
,
4473 const char *servername
,
4475 union spoolss_PrinterInfo
**info
,
4478 DEBUG(4,("enum_all_printers_info_1\n"));
4480 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4481 servername
, 1, flags
, info
, count
);
4484 /********************************************************************
4485 enum_all_printers_info_1_local.
4486 *********************************************************************/
4488 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4489 const struct auth_session_info
*session_info
,
4490 struct messaging_context
*msg_ctx
,
4491 const char *servername
,
4492 union spoolss_PrinterInfo
**info
,
4495 DEBUG(4,("enum_all_printers_info_1_local\n"));
4497 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4498 servername
, PRINTER_ENUM_ICON8
, info
, count
);
4501 /********************************************************************
4502 enum_all_printers_info_1_name.
4503 *********************************************************************/
4505 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4506 const struct auth_session_info
*session_info
,
4507 struct messaging_context
*msg_ctx
,
4508 const char *servername
,
4509 union spoolss_PrinterInfo
**info
,
4512 const char *s
= servername
;
4514 DEBUG(4,("enum_all_printers_info_1_name\n"));
4516 if (servername
!= NULL
&&
4517 (servername
[0] == '\\') && (servername
[1] == '\\')) {
4521 if (!is_myname_or_ipaddr(s
)) {
4522 return WERR_INVALID_NAME
;
4525 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4526 servername
, PRINTER_ENUM_ICON8
, info
, count
);
4529 /********************************************************************
4530 enum_all_printers_info_1_network.
4531 *********************************************************************/
4533 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4534 const struct auth_session_info
*session_info
,
4535 struct messaging_context
*msg_ctx
,
4536 const char *servername
,
4537 union spoolss_PrinterInfo
**info
,
4540 const char *s
= servername
;
4542 DEBUG(4,("enum_all_printers_info_1_network\n"));
4544 /* If we respond to a enum_printers level 1 on our name with flags
4545 set to PRINTER_ENUM_REMOTE with a list of printers then these
4546 printers incorrectly appear in the APW browse list.
4547 Specifically the printers for the server appear at the workgroup
4548 level where all the other servers in the domain are
4549 listed. Windows responds to this call with a
4550 WERR_CAN_NOT_COMPLETE so we should do the same. */
4552 if (servername
!= NULL
&&
4553 (servername
[0] == '\\') && (servername
[1] == '\\')) {
4557 if (is_myname_or_ipaddr(s
)) {
4558 return WERR_CAN_NOT_COMPLETE
;
4561 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4562 servername
, PRINTER_ENUM_NAME
, info
, count
);
4565 /********************************************************************
4566 * api_spoolss_enumprinters
4568 * called from api_spoolss_enumprinters (see this to understand)
4569 ********************************************************************/
4571 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4572 const struct auth_session_info
*session_info
,
4573 struct messaging_context
*msg_ctx
,
4574 const char *servername
,
4575 union spoolss_PrinterInfo
**info
,
4578 DEBUG(4,("enum_all_printers_info_2\n"));
4580 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4581 servername
, 2, 0, info
, count
);
4584 /********************************************************************
4585 * handle enumeration of printers at level 1
4586 ********************************************************************/
4588 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4589 const struct auth_session_info
*session_info
,
4590 struct messaging_context
*msg_ctx
,
4592 const char *servername
,
4593 union spoolss_PrinterInfo
**info
,
4596 /* Not all the flags are equals */
4598 if (flags
& PRINTER_ENUM_LOCAL
) {
4599 return enum_all_printers_info_1_local(mem_ctx
, session_info
,
4600 msg_ctx
, servername
, info
, count
);
4603 if (flags
& PRINTER_ENUM_NAME
) {
4604 return enum_all_printers_info_1_name(mem_ctx
, session_info
,
4605 msg_ctx
, servername
, info
,
4609 if (flags
& PRINTER_ENUM_NETWORK
) {
4610 return enum_all_printers_info_1_network(mem_ctx
, session_info
,
4611 msg_ctx
, servername
, info
,
4615 return WERR_OK
; /* NT4sp5 does that */
4618 /********************************************************************
4619 * handle enumeration of printers at level 2
4620 ********************************************************************/
4622 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4623 const struct auth_session_info
*session_info
,
4624 struct messaging_context
*msg_ctx
,
4626 const char *servername
,
4627 union spoolss_PrinterInfo
**info
,
4630 if (flags
& PRINTER_ENUM_LOCAL
) {
4632 return enum_all_printers_info_2(mem_ctx
, session_info
, msg_ctx
,
4637 if (flags
& PRINTER_ENUM_NAME
) {
4638 if (servername
&& !is_myname_or_ipaddr(canon_servername(servername
))) {
4639 return WERR_INVALID_NAME
;
4642 return enum_all_printers_info_2(mem_ctx
, session_info
, msg_ctx
,
4647 if (flags
& PRINTER_ENUM_REMOTE
) {
4648 return WERR_UNKNOWN_LEVEL
;
4654 /********************************************************************
4655 * handle enumeration of printers at level 4
4656 ********************************************************************/
4658 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4659 const struct auth_session_info
*session_info
,
4660 struct messaging_context
*msg_ctx
,
4662 const char *servername
,
4663 union spoolss_PrinterInfo
**info
,
4666 DEBUG(4,("enum_all_printers_info_4\n"));
4668 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4669 servername
, 4, flags
, info
, count
);
4673 /********************************************************************
4674 * handle enumeration of printers at level 5
4675 ********************************************************************/
4677 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4678 const struct auth_session_info
*session_info
,
4679 struct messaging_context
*msg_ctx
,
4681 const char *servername
,
4682 union spoolss_PrinterInfo
**info
,
4685 DEBUG(4,("enum_all_printers_info_5\n"));
4687 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4688 servername
, 5, flags
, info
, count
);
4691 /****************************************************************
4692 _spoolss_EnumPrinters
4693 ****************************************************************/
4695 WERROR
_spoolss_EnumPrinters(struct pipes_struct
*p
,
4696 struct spoolss_EnumPrinters
*r
)
4698 const struct auth_session_info
*session_info
= get_session_info_system();
4701 /* that's an [in out] buffer */
4703 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4704 return WERR_INVALID_PARAM
;
4707 DEBUG(4,("_spoolss_EnumPrinters\n"));
4711 *r
->out
.info
= NULL
;
4715 * flags==PRINTER_ENUM_NAME
4716 * if name=="" then enumerates all printers
4717 * if name!="" then enumerate the printer
4718 * flags==PRINTER_ENUM_REMOTE
4719 * name is NULL, enumerate printers
4720 * Level 2: name!="" enumerates printers, name can't be NULL
4721 * Level 3: doesn't exist
4722 * Level 4: does a local registry lookup
4723 * Level 5: same as Level 2
4726 if (r
->in
.server
&& r
->in
.server
[0] == '\0') {
4727 r
->in
.server
= NULL
;
4730 switch (r
->in
.level
) {
4732 result
= enumprinters_level0(p
->mem_ctx
, session_info
,
4733 p
->msg_ctx
, r
->in
.flags
,
4735 r
->out
.info
, r
->out
.count
);
4738 result
= enumprinters_level1(p
->mem_ctx
, session_info
,
4739 p
->msg_ctx
, r
->in
.flags
,
4741 r
->out
.info
, r
->out
.count
);
4744 result
= enumprinters_level2(p
->mem_ctx
, session_info
,
4745 p
->msg_ctx
, r
->in
.flags
,
4747 r
->out
.info
, r
->out
.count
);
4750 result
= enumprinters_level4(p
->mem_ctx
, session_info
,
4751 p
->msg_ctx
, r
->in
.flags
,
4753 r
->out
.info
, r
->out
.count
);
4756 result
= enumprinters_level5(p
->mem_ctx
, session_info
,
4757 p
->msg_ctx
, r
->in
.flags
,
4759 r
->out
.info
, r
->out
.count
);
4762 return WERR_UNKNOWN_LEVEL
;
4765 if (!W_ERROR_IS_OK(result
)) {
4769 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4770 spoolss_EnumPrinters
,
4771 *r
->out
.info
, r
->in
.level
,
4773 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4774 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4776 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4779 /****************************************************************
4781 ****************************************************************/
4783 WERROR
_spoolss_GetPrinter(struct pipes_struct
*p
,
4784 struct spoolss_GetPrinter
*r
)
4786 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4787 struct spoolss_PrinterInfo2
*info2
= NULL
;
4788 WERROR result
= WERR_OK
;
4791 /* that's an [in out] buffer */
4793 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4794 result
= WERR_INVALID_PARAM
;
4800 if (Printer
== NULL
) {
4801 result
= WERR_BADFID
;
4805 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4806 result
= WERR_BADFID
;
4810 result
= winreg_get_printer_internal(p
->mem_ctx
,
4811 get_session_info_system(),
4813 lp_const_servicename(snum
),
4815 if (!W_ERROR_IS_OK(result
)) {
4819 switch (r
->in
.level
) {
4821 result
= construct_printer_info0(p
->mem_ctx
,
4822 get_session_info_system(),
4825 Printer
->servername
,
4826 &r
->out
.info
->info0
,
4830 result
= construct_printer_info1(p
->mem_ctx
, info2
,
4832 Printer
->servername
,
4833 &r
->out
.info
->info1
, snum
);
4836 result
= construct_printer_info2(p
->mem_ctx
, p
->msg_ctx
, info2
,
4837 Printer
->servername
,
4838 &r
->out
.info
->info2
, snum
);
4841 result
= construct_printer_info3(p
->mem_ctx
, info2
,
4842 Printer
->servername
,
4843 &r
->out
.info
->info3
, snum
);
4846 result
= construct_printer_info4(p
->mem_ctx
, info2
,
4847 Printer
->servername
,
4848 &r
->out
.info
->info4
, snum
);
4851 result
= construct_printer_info5(p
->mem_ctx
, info2
,
4852 Printer
->servername
,
4853 &r
->out
.info
->info5
, snum
);
4856 result
= construct_printer_info6(p
->mem_ctx
, p
->msg_ctx
, info2
,
4857 Printer
->servername
,
4858 &r
->out
.info
->info6
, snum
);
4861 result
= construct_printer_info7(p
->mem_ctx
, p
->msg_ctx
,
4862 Printer
->servername
,
4863 &r
->out
.info
->info7
, snum
);
4866 result
= construct_printer_info8(p
->mem_ctx
, info2
,
4867 Printer
->servername
,
4868 &r
->out
.info
->info8
, snum
);
4871 result
= WERR_UNKNOWN_LEVEL
;
4876 if (!W_ERROR_IS_OK(result
)) {
4877 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4878 r
->in
.level
, win_errstr(result
)));
4882 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
,
4883 r
->out
.info
, r
->in
.level
);
4884 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4886 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4889 TALLOC_FREE(r
->out
.info
);
4893 /********************************************************************
4894 ********************************************************************/
4896 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4898 if (in && strlen(in)) { \
4899 out = talloc_strdup(mem_ctx, in); \
4901 out = talloc_strdup(mem_ctx, ""); \
4903 W_ERROR_HAVE_NO_MEMORY(out); \
4906 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4908 if (in && strlen(in)) { \
4909 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4911 out = talloc_strdup(mem_ctx, ""); \
4913 W_ERROR_HAVE_NO_MEMORY(out); \
4916 static WERROR
string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4917 const char **string_array
,
4918 const char ***presult
,
4919 const char *cservername
,
4924 size_t num_strings
= 0;
4925 const char **array
= NULL
;
4927 if (string_array
== NULL
) {
4928 return WERR_INVALID_PARAMETER
;
4931 for (i
=0; string_array
[i
] && string_array
[i
][0] != '\0'; i
++) {
4932 const char *str
= NULL
;
4934 if (cservername
== NULL
|| arch
== NULL
) {
4935 FILL_DRIVER_STRING(mem_ctx
, string_array
[i
], str
);
4937 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
, arch
, version
, string_array
[i
], str
);
4940 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4947 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4948 &array
, &num_strings
);
4951 if (presult
!= NULL
) {
4960 /********************************************************************
4961 * fill a spoolss_DriverInfo1 struct
4962 ********************************************************************/
4964 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4965 struct spoolss_DriverInfo1
*r
,
4966 const struct spoolss_DriverInfo8
*driver
,
4967 const char *servername
)
4969 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4970 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4975 /********************************************************************
4976 * fill a spoolss_DriverInfo2 struct
4977 ********************************************************************/
4979 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4980 struct spoolss_DriverInfo2
*r
,
4981 const struct spoolss_DriverInfo8
*driver
,
4982 const char *servername
)
4985 const char *cservername
= canon_servername(servername
);
4987 r
->version
= driver
->version
;
4989 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4990 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4991 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4992 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4994 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4995 driver
->architecture
,
4997 driver
->driver_path
,
5000 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5001 driver
->architecture
,
5006 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5007 driver
->architecture
,
5009 driver
->config_file
,
5015 /********************************************************************
5016 * fill a spoolss_DriverInfo3 struct
5017 ********************************************************************/
5019 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
5020 struct spoolss_DriverInfo3
*r
,
5021 const struct spoolss_DriverInfo8
*driver
,
5022 const char *servername
)
5024 const char *cservername
= canon_servername(servername
);
5026 r
->version
= driver
->version
;
5028 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5029 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5030 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5031 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5033 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5034 driver
->architecture
,
5036 driver
->driver_path
,
5039 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5040 driver
->architecture
,
5045 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5046 driver
->architecture
,
5048 driver
->config_file
,
5051 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5052 driver
->architecture
,
5057 FILL_DRIVER_STRING(mem_ctx
,
5058 driver
->monitor_name
,
5061 FILL_DRIVER_STRING(mem_ctx
,
5062 driver
->default_datatype
,
5063 r
->default_datatype
);
5065 return string_array_from_driver_info(mem_ctx
,
5066 driver
->dependent_files
,
5067 &r
->dependent_files
,
5069 driver
->architecture
,
5073 /********************************************************************
5074 * fill a spoolss_DriverInfo4 struct
5075 ********************************************************************/
5077 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
5078 struct spoolss_DriverInfo4
*r
,
5079 const struct spoolss_DriverInfo8
*driver
,
5080 const char *servername
)
5082 const char *cservername
= canon_servername(servername
);
5085 r
->version
= driver
->version
;
5087 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5088 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5089 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5090 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5092 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5093 driver
->architecture
,
5095 driver
->driver_path
,
5098 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5099 driver
->architecture
,
5104 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5105 driver
->architecture
,
5107 driver
->config_file
,
5110 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5111 driver
->architecture
,
5116 result
= string_array_from_driver_info(mem_ctx
,
5117 driver
->dependent_files
,
5118 &r
->dependent_files
,
5120 driver
->architecture
,
5122 if (!W_ERROR_IS_OK(result
)) {
5126 FILL_DRIVER_STRING(mem_ctx
,
5127 driver
->monitor_name
,
5130 FILL_DRIVER_STRING(mem_ctx
,
5131 driver
->default_datatype
,
5132 r
->default_datatype
);
5135 result
= string_array_from_driver_info(mem_ctx
,
5136 driver
->previous_names
,
5143 /********************************************************************
5144 * fill a spoolss_DriverInfo5 struct
5145 ********************************************************************/
5147 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
5148 struct spoolss_DriverInfo5
*r
,
5149 const struct spoolss_DriverInfo8
*driver
,
5150 const char *servername
)
5152 const char *cservername
= canon_servername(servername
);
5154 r
->version
= driver
->version
;
5156 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5157 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5158 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5159 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5161 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5162 driver
->architecture
,
5164 driver
->driver_path
,
5167 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5168 driver
->architecture
,
5173 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5174 driver
->architecture
,
5176 driver
->config_file
,
5179 r
->driver_attributes
= 0;
5180 r
->config_version
= 0;
5181 r
->driver_version
= 0;
5185 /********************************************************************
5186 * fill a spoolss_DriverInfo6 struct
5187 ********************************************************************/
5189 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
5190 struct spoolss_DriverInfo6
*r
,
5191 const struct spoolss_DriverInfo8
*driver
,
5192 const char *servername
)
5194 const char *cservername
= canon_servername(servername
);
5197 r
->version
= driver
->version
;
5199 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5200 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5201 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5202 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5204 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5205 driver
->architecture
,
5207 driver
->driver_path
,
5210 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5211 driver
->architecture
,
5216 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5217 driver
->architecture
,
5219 driver
->config_file
,
5222 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5223 driver
->architecture
,
5228 FILL_DRIVER_STRING(mem_ctx
,
5229 driver
->monitor_name
,
5232 FILL_DRIVER_STRING(mem_ctx
,
5233 driver
->default_datatype
,
5234 r
->default_datatype
);
5236 result
= string_array_from_driver_info(mem_ctx
,
5237 driver
->dependent_files
,
5238 &r
->dependent_files
,
5240 driver
->architecture
,
5242 if (!W_ERROR_IS_OK(result
)) {
5246 result
= string_array_from_driver_info(mem_ctx
,
5247 driver
->previous_names
,
5250 if (!W_ERROR_IS_OK(result
)) {
5254 r
->driver_date
= driver
->driver_date
;
5255 r
->driver_version
= driver
->driver_version
;
5257 FILL_DRIVER_STRING(mem_ctx
,
5258 driver
->manufacturer_name
,
5259 r
->manufacturer_name
);
5260 FILL_DRIVER_STRING(mem_ctx
,
5261 driver
->manufacturer_url
,
5262 r
->manufacturer_url
);
5263 FILL_DRIVER_STRING(mem_ctx
,
5264 driver
->hardware_id
,
5266 FILL_DRIVER_STRING(mem_ctx
,
5273 /********************************************************************
5274 * fill a spoolss_DriverInfo8 struct
5275 ********************************************************************/
5277 static WERROR
fill_printer_driver_info8(TALLOC_CTX
*mem_ctx
,
5278 struct spoolss_DriverInfo8
*r
,
5279 const struct spoolss_DriverInfo8
*driver
,
5280 const char *servername
)
5282 const char *cservername
= canon_servername(servername
);
5285 r
->version
= driver
->version
;
5287 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5288 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5289 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5290 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5292 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5293 driver
->architecture
,
5295 driver
->driver_path
,
5298 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5299 driver
->architecture
,
5304 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5305 driver
->architecture
,
5307 driver
->config_file
,
5310 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5311 driver
->architecture
,
5316 FILL_DRIVER_STRING(mem_ctx
,
5317 driver
->monitor_name
,
5320 FILL_DRIVER_STRING(mem_ctx
,
5321 driver
->default_datatype
,
5322 r
->default_datatype
);
5324 result
= string_array_from_driver_info(mem_ctx
,
5325 driver
->dependent_files
,
5326 &r
->dependent_files
,
5328 driver
->architecture
,
5330 if (!W_ERROR_IS_OK(result
)) {
5334 result
= string_array_from_driver_info(mem_ctx
,
5335 driver
->previous_names
,
5338 if (!W_ERROR_IS_OK(result
)) {
5342 r
->driver_date
= driver
->driver_date
;
5343 r
->driver_version
= driver
->driver_version
;
5345 FILL_DRIVER_STRING(mem_ctx
,
5346 driver
->manufacturer_name
,
5347 r
->manufacturer_name
);
5348 FILL_DRIVER_STRING(mem_ctx
,
5349 driver
->manufacturer_url
,
5350 r
->manufacturer_url
);
5351 FILL_DRIVER_STRING(mem_ctx
,
5352 driver
->hardware_id
,
5354 FILL_DRIVER_STRING(mem_ctx
,
5358 FILL_DRIVER_STRING(mem_ctx
,
5359 driver
->print_processor
,
5360 r
->print_processor
);
5361 FILL_DRIVER_STRING(mem_ctx
,
5362 driver
->vendor_setup
,
5365 result
= string_array_from_driver_info(mem_ctx
,
5366 driver
->color_profiles
,
5369 if (!W_ERROR_IS_OK(result
)) {
5373 FILL_DRIVER_STRING(mem_ctx
,
5377 r
->printer_driver_attributes
= driver
->printer_driver_attributes
;
5379 result
= string_array_from_driver_info(mem_ctx
,
5380 driver
->core_driver_dependencies
,
5381 &r
->core_driver_dependencies
,
5383 if (!W_ERROR_IS_OK(result
)) {
5387 r
->min_inbox_driver_ver_date
= driver
->min_inbox_driver_ver_date
;
5388 r
->min_inbox_driver_ver_version
= driver
->min_inbox_driver_ver_version
;
5393 #if 0 /* disabled until marshalling issues are resolved - gd */
5394 /********************************************************************
5395 ********************************************************************/
5397 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
5398 struct spoolss_DriverFileInfo
*r
,
5399 const char *cservername
,
5400 const char *file_name
,
5401 enum spoolss_DriverFileType file_type
,
5402 uint32_t file_version
)
5404 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
5405 cservername
, file_name
);
5406 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
5407 r
->file_type
= file_type
;
5408 r
->file_version
= file_version
;
5413 /********************************************************************
5414 ********************************************************************/
5416 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
5417 const struct spoolss_DriverInfo8
*driver
,
5418 const char *cservername
,
5419 struct spoolss_DriverFileInfo
**info_p
,
5422 struct spoolss_DriverFileInfo
*info
= NULL
;
5430 if (strlen(driver
->driver_path
)) {
5431 info
= talloc_realloc(mem_ctx
, info
,
5432 struct spoolss_DriverFileInfo
,
5434 W_ERROR_HAVE_NO_MEMORY(info
);
5435 result
= fill_spoolss_DriverFileInfo(info
,
5438 driver
->driver_path
,
5439 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
5441 W_ERROR_NOT_OK_RETURN(result
);
5445 if (strlen(driver
->config_file
)) {
5446 info
= talloc_realloc(mem_ctx
, info
,
5447 struct spoolss_DriverFileInfo
,
5449 W_ERROR_HAVE_NO_MEMORY(info
);
5450 result
= fill_spoolss_DriverFileInfo(info
,
5453 driver
->config_file
,
5454 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
5456 W_ERROR_NOT_OK_RETURN(result
);
5460 if (strlen(driver
->data_file
)) {
5461 info
= talloc_realloc(mem_ctx
, info
,
5462 struct spoolss_DriverFileInfo
,
5464 W_ERROR_HAVE_NO_MEMORY(info
);
5465 result
= fill_spoolss_DriverFileInfo(info
,
5469 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
5471 W_ERROR_NOT_OK_RETURN(result
);
5475 if (strlen(driver
->help_file
)) {
5476 info
= talloc_realloc(mem_ctx
, info
,
5477 struct spoolss_DriverFileInfo
,
5479 W_ERROR_HAVE_NO_MEMORY(info
);
5480 result
= fill_spoolss_DriverFileInfo(info
,
5484 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
5486 W_ERROR_NOT_OK_RETURN(result
);
5490 for (i
=0; driver
->dependent_files
[i
] && driver
->dependent_files
[i
][0] != '\0'; i
++) {
5491 info
= talloc_realloc(mem_ctx
, info
,
5492 struct spoolss_DriverFileInfo
,
5494 W_ERROR_HAVE_NO_MEMORY(info
);
5495 result
= fill_spoolss_DriverFileInfo(info
,
5498 driver
->dependent_files
[i
],
5499 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
5501 W_ERROR_NOT_OK_RETURN(result
);
5511 /********************************************************************
5512 * fill a spoolss_DriverInfo101 struct
5513 ********************************************************************/
5515 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
5516 struct spoolss_DriverInfo101
*r
,
5517 const struct spoolss_DriverInfo8
*driver
,
5518 const char *servername
)
5520 const char *cservername
= canon_servername(servername
);
5523 r
->version
= driver
->version
;
5525 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5526 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5527 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5528 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5530 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
5534 if (!W_ERROR_IS_OK(result
)) {
5538 FILL_DRIVER_STRING(mem_ctx
,
5539 driver
->monitor_name
,
5542 FILL_DRIVER_STRING(mem_ctx
,
5543 driver
->default_datatype
,
5544 r
->default_datatype
);
5546 result
= string_array_from_driver_info(mem_ctx
,
5547 driver
->previous_names
,
5550 if (!W_ERROR_IS_OK(result
)) {
5554 r
->driver_date
= driver
->driver_date
;
5555 r
->driver_version
= driver
->driver_version
;
5557 FILL_DRIVER_STRING(mem_ctx
,
5558 driver
->manufacturer_name
,
5559 r
->manufacturer_name
);
5560 FILL_DRIVER_STRING(mem_ctx
,
5561 driver
->manufacturer_url
,
5562 r
->manufacturer_url
);
5563 FILL_DRIVER_STRING(mem_ctx
,
5564 driver
->hardware_id
,
5566 FILL_DRIVER_STRING(mem_ctx
,
5573 /********************************************************************
5574 ********************************************************************/
5576 static WERROR
construct_printer_driver_info_level(TALLOC_CTX
*mem_ctx
,
5577 const struct auth_session_info
*session_info
,
5578 struct messaging_context
*msg_ctx
,
5580 union spoolss_DriverInfo
*r
,
5582 const char *servername
,
5583 const char *architecture
,
5586 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
5587 struct spoolss_DriverInfo8
*driver
;
5589 struct dcerpc_binding_handle
*b
;
5590 TALLOC_CTX
*tmp_ctx
= NULL
;
5593 return WERR_UNKNOWN_LEVEL
;
5596 tmp_ctx
= talloc_new(mem_ctx
);
5601 result
= winreg_printer_binding_handle(tmp_ctx
,
5605 if (!W_ERROR_IS_OK(result
)) {
5609 result
= winreg_get_printer(tmp_ctx
, b
,
5610 lp_const_servicename(snum
),
5613 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5614 win_errstr(result
)));
5616 if (!W_ERROR_IS_OK(result
)) {
5617 result
= WERR_INVALID_PRINTER_NAME
;
5621 result
= winreg_get_driver(tmp_ctx
, b
,
5623 pinfo2
->drivername
, version
, &driver
);
5625 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5626 win_errstr(result
)));
5628 if (!W_ERROR_IS_OK(result
)) {
5630 * Is this a W2k client ?
5634 result
= WERR_UNKNOWN_PRINTER_DRIVER
;
5638 /* Yes - try again with a WinNT driver. */
5640 result
= winreg_get_driver(tmp_ctx
, b
,
5644 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5645 win_errstr(result
)));
5646 if (!W_ERROR_IS_OK(result
)) {
5647 result
= WERR_UNKNOWN_PRINTER_DRIVER
;
5652 /* these are allocated on mem_ctx and not tmp_ctx because they are
5653 * the 'return value' and need to utlive this call */
5656 result
= fill_printer_driver_info1(mem_ctx
, &r
->info1
, driver
, servername
);
5659 result
= fill_printer_driver_info2(mem_ctx
, &r
->info2
, driver
, servername
);
5662 result
= fill_printer_driver_info3(mem_ctx
, &r
->info3
, driver
, servername
);
5665 result
= fill_printer_driver_info4(mem_ctx
, &r
->info4
, driver
, servername
);
5668 result
= fill_printer_driver_info5(mem_ctx
, &r
->info5
, driver
, servername
);
5671 result
= fill_printer_driver_info6(mem_ctx
, &r
->info6
, driver
, servername
);
5674 result
= fill_printer_driver_info8(mem_ctx
, &r
->info8
, driver
, servername
);
5676 #if 0 /* disabled until marshalling issues are resolved - gd */
5678 result
= fill_printer_driver_info101(mem_ctx
, &r
->info101
, driver
, servername
);
5682 result
= WERR_UNKNOWN_LEVEL
;
5687 talloc_free(tmp_ctx
);
5691 /****************************************************************
5692 _spoolss_GetPrinterDriver2
5693 ****************************************************************/
5695 WERROR
_spoolss_GetPrinterDriver2(struct pipes_struct
*p
,
5696 struct spoolss_GetPrinterDriver2
*r
)
5698 struct printer_handle
*printer
;
5700 uint32_t version
= r
->in
.client_major_version
;
5704 /* that's an [in out] buffer */
5706 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5707 result
= WERR_INVALID_PARAM
;
5711 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5713 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5714 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5715 result
= WERR_INVALID_PRINTER_NAME
;
5720 *r
->out
.server_major_version
= 0;
5721 *r
->out
.server_minor_version
= 0;
5723 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5724 result
= WERR_BADFID
;
5728 if (r
->in
.client_major_version
== SPOOLSS_DRIVER_VERSION_2012
) {
5729 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5730 "downgrading to v3\n"));
5731 version
= SPOOLSS_DRIVER_VERSION_200X
;
5734 result
= construct_printer_driver_info_level(p
->mem_ctx
,
5735 get_session_info_system(),
5737 r
->in
.level
, r
->out
.info
,
5738 snum
, printer
->servername
,
5741 if (!W_ERROR_IS_OK(result
)) {
5745 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
,
5746 r
->out
.info
, r
->in
.level
);
5747 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5749 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5752 TALLOC_FREE(r
->out
.info
);
5757 /****************************************************************
5758 _spoolss_StartPagePrinter
5759 ****************************************************************/
5761 WERROR
_spoolss_StartPagePrinter(struct pipes_struct
*p
,
5762 struct spoolss_StartPagePrinter
*r
)
5764 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5767 DEBUG(3,("_spoolss_StartPagePrinter: "
5768 "Error in startpageprinter printer handle\n"));
5772 Printer
->page_started
= true;
5776 /****************************************************************
5777 _spoolss_EndPagePrinter
5778 ****************************************************************/
5780 WERROR
_spoolss_EndPagePrinter(struct pipes_struct
*p
,
5781 struct spoolss_EndPagePrinter
*r
)
5785 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5788 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5789 OUR_HANDLE(r
->in
.handle
)));
5793 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5796 Printer
->page_started
= false;
5797 print_job_endpage(p
->msg_ctx
, snum
, Printer
->jobid
);
5802 /****************************************************************
5803 _spoolss_StartDocPrinter
5804 ****************************************************************/
5806 WERROR
_spoolss_StartDocPrinter(struct pipes_struct
*p
,
5807 struct spoolss_StartDocPrinter
*r
)
5809 struct spoolss_DocumentInfo1
*info_1
;
5811 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5817 DEBUG(2,("_spoolss_StartDocPrinter: "
5818 "Invalid handle (%s:%u:%u)\n",
5819 OUR_HANDLE(r
->in
.handle
)));
5823 if (Printer
->jobid
) {
5824 DEBUG(2, ("_spoolss_StartDocPrinter: "
5825 "StartDocPrinter called twice! "
5826 "(existing jobid = %d)\n", Printer
->jobid
));
5827 return WERR_INVALID_HANDLE
;
5830 if (r
->in
.info_ctr
->level
!= 1) {
5831 return WERR_UNKNOWN_LEVEL
;
5834 info_1
= r
->in
.info_ctr
->info
.info1
;
5837 * a nice thing with NT is it doesn't listen to what you tell it.
5838 * when asked to send _only_ RAW datas, it tries to send datas
5841 * So I add checks like in NT Server ...
5844 if (info_1
->datatype
) {
5846 * The v4 driver model used in Windows 8 declares print jobs
5847 * intended to bypass the XPS processing layer by setting
5848 * datatype to "XPS_PASS" instead of "RAW".
5850 if ((strcmp(info_1
->datatype
, "RAW") != 0)
5851 && (strcmp(info_1
->datatype
, "XPS_PASS") != 0)) {
5853 return WERR_INVALID_DATATYPE
;
5857 /* get the share number of the printer */
5858 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5862 rc
= get_remote_hostname(p
->remote_address
,
5868 if (strequal(rhost
,"UNKNOWN")) {
5869 rhost
= tsocket_address_inet_addr_string(p
->remote_address
,
5871 if (rhost
== NULL
) {
5876 werr
= print_job_start(p
->session_info
,
5880 info_1
->document_name
,
5881 info_1
->output_file
,
5885 /* An error occured in print_job_start() so return an appropriate
5888 if (!W_ERROR_IS_OK(werr
)) {
5892 Printer
->document_started
= true;
5893 *r
->out
.job_id
= Printer
->jobid
;
5898 /****************************************************************
5899 _spoolss_EndDocPrinter
5900 ****************************************************************/
5902 WERROR
_spoolss_EndDocPrinter(struct pipes_struct
*p
,
5903 struct spoolss_EndDocPrinter
*r
)
5905 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5910 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5911 OUR_HANDLE(r
->in
.handle
)));
5915 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5919 Printer
->document_started
= false;
5920 status
= print_job_end(p
->msg_ctx
, snum
, Printer
->jobid
, NORMAL_CLOSE
);
5921 if (!NT_STATUS_IS_OK(status
)) {
5922 DEBUG(2, ("_spoolss_EndDocPrinter: "
5923 "print_job_end failed [%s]\n",
5924 nt_errstr(status
)));
5928 return ntstatus_to_werror(status
);
5931 /****************************************************************
5932 _spoolss_WritePrinter
5933 ****************************************************************/
5935 WERROR
_spoolss_WritePrinter(struct pipes_struct
*p
,
5936 struct spoolss_WritePrinter
*r
)
5938 ssize_t buffer_written
;
5940 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5943 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5944 OUR_HANDLE(r
->in
.handle
)));
5945 *r
->out
.num_written
= r
->in
._data_size
;
5949 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5952 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5953 buffer_written
= print_job_write(server_event_context(),p
->msg_ctx
,
5954 snum
, Printer
->jobid
,
5955 (const char *)r
->in
.data
.data
,
5956 (size_t)r
->in
._data_size
);
5957 if (buffer_written
== (ssize_t
)-1) {
5958 *r
->out
.num_written
= 0;
5959 if (errno
== ENOSPC
)
5960 return WERR_NO_SPOOL_SPACE
;
5962 return WERR_ACCESS_DENIED
;
5965 *r
->out
.num_written
= r
->in
._data_size
;
5970 /********************************************************************
5971 * api_spoolss_getprinter
5972 * called from the spoolss dispatcher
5974 ********************************************************************/
5976 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5977 struct pipes_struct
*p
)
5979 const struct auth_session_info
*session_info
= p
->session_info
;
5981 WERROR errcode
= WERR_BADFUNC
;
5982 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
5985 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5986 OUR_HANDLE(handle
)));
5990 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5994 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5995 errcode
= print_queue_pause(session_info
, p
->msg_ctx
, snum
);
5997 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5998 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5999 errcode
= print_queue_resume(session_info
, p
->msg_ctx
, snum
);
6001 case SPOOLSS_PRINTER_CONTROL_PURGE
:
6002 errcode
= print_queue_purge(session_info
, p
->msg_ctx
, snum
);
6005 return WERR_UNKNOWN_LEVEL
;
6012 /****************************************************************
6013 _spoolss_AbortPrinter
6014 * From MSDN: "Deletes printer's spool file if printer is configured
6016 ****************************************************************/
6018 WERROR
_spoolss_AbortPrinter(struct pipes_struct
*p
,
6019 struct spoolss_AbortPrinter
*r
)
6021 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6023 WERROR errcode
= WERR_OK
;
6026 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6027 OUR_HANDLE(r
->in
.handle
)));
6031 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
6034 if (!Printer
->document_started
) {
6035 return WERR_SPL_NO_STARTDOC
;
6038 errcode
= print_job_delete(p
->session_info
,
6046 /********************************************************************
6047 * called by spoolss_api_setprinter
6048 * when updating a printer description
6049 ********************************************************************/
6051 static WERROR
update_printer_sec(struct policy_handle
*handle
,
6052 struct pipes_struct
*p
,
6053 struct sec_desc_buf
*secdesc_ctr
)
6055 struct spoolss_security_descriptor
*new_secdesc
= NULL
;
6056 struct spoolss_security_descriptor
*old_secdesc
= NULL
;
6057 const char *printer
;
6060 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6061 struct dcerpc_binding_handle
*b
;
6062 TALLOC_CTX
*tmp_ctx
= NULL
;
6064 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
6065 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6066 OUR_HANDLE(handle
)));
6068 result
= WERR_BADFID
;
6072 if (secdesc_ctr
== NULL
) {
6073 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6074 result
= WERR_INVALID_PARAM
;
6077 printer
= lp_const_servicename(snum
);
6079 /* Check the user has permissions to change the security
6080 descriptor. By experimentation with two NT machines, the user
6081 requires Full Access to the printer to change security
6084 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6085 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6086 result
= WERR_ACCESS_DENIED
;
6090 tmp_ctx
= talloc_new(p
->mem_ctx
);
6095 result
= winreg_printer_binding_handle(tmp_ctx
,
6096 get_session_info_system(),
6099 if (!W_ERROR_IS_OK(result
)) {
6103 /* NT seems to like setting the security descriptor even though
6104 nothing may have actually changed. */
6105 result
= winreg_get_printer_secdesc(tmp_ctx
, b
,
6108 if (!W_ERROR_IS_OK(result
)) {
6109 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6110 result
= WERR_BADFID
;
6114 if (DEBUGLEVEL
>= 10) {
6115 struct security_acl
*the_acl
;
6118 the_acl
= old_secdesc
->dacl
;
6119 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6120 printer
, the_acl
->num_aces
));
6122 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6123 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6124 &the_acl
->aces
[i
].trustee
),
6125 the_acl
->aces
[i
].access_mask
));
6128 the_acl
= secdesc_ctr
->sd
->dacl
;
6131 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6132 printer
, the_acl
->num_aces
));
6134 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6135 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6136 &the_acl
->aces
[i
].trustee
),
6137 the_acl
->aces
[i
].access_mask
));
6140 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6144 new_secdesc
= sec_desc_merge(tmp_ctx
, secdesc_ctr
->sd
, old_secdesc
);
6145 if (new_secdesc
== NULL
) {
6146 result
= WERR_NOMEM
;
6150 if (security_descriptor_equal(new_secdesc
, old_secdesc
)) {
6155 result
= winreg_set_printer_secdesc(tmp_ctx
, b
,
6160 talloc_free(tmp_ctx
);
6164 /********************************************************************
6165 Canonicalize printer info from a client
6166 ********************************************************************/
6168 static bool check_printer_ok(TALLOC_CTX
*mem_ctx
,
6169 struct spoolss_SetPrinterInfo2
*info2
,
6172 fstring printername
;
6175 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6176 "portname=%s drivername=%s comment=%s location=%s\n",
6177 info2
->servername
, info2
->printername
, info2
->sharename
,
6178 info2
->portname
, info2
->drivername
, info2
->comment
,
6181 /* we force some elements to "correct" values */
6182 info2
->servername
= talloc_asprintf(mem_ctx
, "\\\\%s", lp_netbios_name());
6183 if (info2
->servername
== NULL
) {
6186 info2
->sharename
= talloc_strdup(mem_ctx
, lp_const_servicename(snum
));
6187 if (info2
->sharename
== NULL
) {
6191 /* check to see if we allow printername != sharename */
6192 if (lp_force_printername(snum
)) {
6193 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6194 lp_netbios_name(), info2
->sharename
);
6196 /* make sure printername is in \\server\printername format */
6197 fstrcpy(printername
, info2
->printername
);
6199 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
6200 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
6204 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6205 lp_netbios_name(), p
);
6207 if (info2
->printername
== NULL
) {
6211 info2
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
6212 info2
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
6217 /****************************************************************************
6218 ****************************************************************************/
6220 static WERROR
add_port_hook(TALLOC_CTX
*ctx
, struct security_token
*token
, const char *portname
, const char *uri
)
6222 char *cmd
= lp_addport_cmd(talloc_tos());
6223 char *command
= NULL
;
6225 bool is_print_op
= false;
6228 return WERR_ACCESS_DENIED
;
6231 command
= talloc_asprintf(ctx
,
6232 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
6238 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
6240 DEBUG(10,("Running [%s]\n", command
));
6242 /********* BEGIN SePrintOperatorPrivilege **********/
6247 ret
= smbrun(command
, NULL
);
6252 /********* END SePrintOperatorPrivilege **********/
6254 DEBUGADD(10,("returned [%d]\n", ret
));
6256 TALLOC_FREE(command
);
6259 return WERR_ACCESS_DENIED
;
6265 /****************************************************************************
6266 ****************************************************************************/
6268 static bool spoolss_conn_snum_used(struct smbd_server_connection
*sconn
,
6272 * As we do not know if we are embedded in the file server process
6273 * or not, we have to pretend that all shares are in use.
6278 static bool add_printer_hook(TALLOC_CTX
*ctx
, struct security_token
*token
,
6279 struct spoolss_SetPrinterInfo2
*info2
,
6280 const char *remote_machine
,
6281 struct messaging_context
*msg_ctx
)
6283 char *cmd
= lp_addprinter_cmd(talloc_tos());
6285 char *command
= NULL
;
6289 bool is_print_op
= false;
6291 if (!remote_machine
) {
6295 command
= talloc_asprintf(ctx
,
6296 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6297 cmd
, info2
->printername
, info2
->sharename
,
6298 info2
->portname
, info2
->drivername
,
6299 info2
->location
, info2
->comment
, remote_machine
);
6305 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
6307 DEBUG(10,("Running [%s]\n", command
));
6309 /********* BEGIN SePrintOperatorPrivilege **********/
6314 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6315 /* Tell everyone we updated smb.conf. */
6316 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
6322 /********* END SePrintOperatorPrivilege **********/
6324 DEBUGADD(10,("returned [%d]\n", ret
));
6326 TALLOC_FREE(command
);
6334 /* reload our services immediately */
6336 reload_services(NULL
, spoolss_conn_snum_used
, false);
6340 /* Get lines and convert them back to dos-codepage */
6341 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
6342 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6345 /* Set the portname to what the script says the portname should be. */
6346 /* but don't require anything to be return from the script exit a good error code */
6349 /* Set the portname to what the script says the portname should be. */
6350 info2
->portname
= talloc_strdup(ctx
, qlines
[0]);
6351 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6354 TALLOC_FREE(qlines
);
6358 static WERROR
update_dsspooler(TALLOC_CTX
*mem_ctx
,
6359 const struct auth_session_info
*session_info
,
6360 struct messaging_context
*msg_ctx
,
6362 struct spoolss_SetPrinterInfo2
*printer
,
6363 struct spoolss_PrinterInfo2
*old_printer
)
6365 bool force_update
= (old_printer
== NULL
);
6366 const char *dnsdomname
;
6367 const char *longname
;
6368 const char *uncname
;
6369 const char *spooling
;
6371 WERROR result
= WERR_OK
;
6372 struct dcerpc_binding_handle
*b
;
6373 TALLOC_CTX
*tmp_ctx
;
6376 tmp_ctx
= talloc_new(mem_ctx
);
6381 result
= winreg_printer_binding_handle(tmp_ctx
,
6385 if (!W_ERROR_IS_OK(result
)) {
6389 if (printer
->drivername
!= NULL
&&
6391 !strequal(printer
->drivername
, old_printer
->drivername
))) {
6392 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->drivername
);
6394 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME
));
6395 result
= WERR_INVALID_DATA
;
6398 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6400 SPOOL_DSSPOOLER_KEY
,
6401 SPOOL_REG_DRIVERNAME
,
6405 if (!W_ERROR_IS_OK(result
)) {
6406 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME
));
6410 if (!force_update
) {
6411 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6412 printer
->drivername
));
6414 notify_printer_driver(server_event_context(), msg_ctx
,
6415 snum
, printer
->drivername
?
6416 printer
->drivername
: "");
6420 if (printer
->comment
!= NULL
&&
6422 !strequal(printer
->comment
, old_printer
->comment
))) {
6423 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->comment
);
6425 DEBUG(0, ("comment data corrupted\n"));
6426 result
= WERR_INVALID_DATA
;
6429 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6431 SPOOL_DSSPOOLER_KEY
,
6432 SPOOL_REG_DESCRIPTION
,
6436 if (!W_ERROR_IS_OK(result
)) {
6437 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION
));
6441 if (!force_update
) {
6442 notify_printer_comment(server_event_context(), msg_ctx
,
6443 snum
, printer
->comment
?
6444 printer
->comment
: "");
6448 if (printer
->sharename
!= NULL
&&
6450 !strequal(printer
->sharename
, old_printer
->sharename
))) {
6451 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->sharename
);
6453 DEBUG(0, ("sharename data corrupted\n"));
6454 result
= WERR_INVALID_DATA
;
6457 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6459 SPOOL_DSSPOOLER_KEY
,
6460 SPOOL_REG_PRINTSHARENAME
,
6464 if (!W_ERROR_IS_OK(result
)) {
6465 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME
));
6469 if (!force_update
) {
6470 notify_printer_sharename(server_event_context(),
6472 snum
, printer
->sharename
?
6473 printer
->sharename
: "");
6476 /* name change, purge any cache entries for the old */
6477 prune_printername_cache();
6480 if (printer
->printername
!= NULL
&&
6482 !strequal(printer
->printername
, old_printer
->printername
))) {
6485 p
= strrchr(printer
->printername
, '\\' );
6489 p
= printer
->printername
;
6492 ok
= push_reg_sz(tmp_ctx
, &buffer
, p
);
6494 DEBUG(0, ("printername data corrupted\n"));
6495 result
= WERR_INVALID_DATA
;
6498 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6500 SPOOL_DSSPOOLER_KEY
,
6501 SPOOL_REG_PRINTERNAME
,
6505 if (!W_ERROR_IS_OK(result
)) {
6506 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME
));
6510 if (!force_update
) {
6511 notify_printer_printername(server_event_context(),
6512 msg_ctx
, snum
, p
? p
: "");
6515 /* name change, purge any cache entries for the old */
6516 prune_printername_cache();
6519 if (printer
->portname
!= NULL
&&
6521 !strequal(printer
->portname
, old_printer
->portname
))) {
6522 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->portname
);
6524 DEBUG(0, ("portname data corrupted\n"));
6525 result
= WERR_INVALID_DATA
;
6528 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6530 SPOOL_DSSPOOLER_KEY
,
6535 if (!W_ERROR_IS_OK(result
)) {
6536 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME
));
6540 if (!force_update
) {
6541 notify_printer_port(server_event_context(),
6542 msg_ctx
, snum
, printer
->portname
?
6543 printer
->portname
: "");
6547 if (printer
->location
!= NULL
&&
6549 !strequal(printer
->location
, old_printer
->location
))) {
6550 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->location
);
6552 DEBUG(0, ("location data corrupted\n"));
6553 result
= WERR_INVALID_DATA
;
6556 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6558 SPOOL_DSSPOOLER_KEY
,
6563 if (!W_ERROR_IS_OK(result
)) {
6564 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION
));
6568 if (!force_update
) {
6569 notify_printer_location(server_event_context(),
6572 printer
->location
: "");
6576 if (printer
->sepfile
!= NULL
&&
6578 !strequal(printer
->sepfile
, old_printer
->sepfile
))) {
6579 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->sepfile
);
6581 DEBUG(0, ("sepfile data corrupted\n"));
6582 result
= WERR_INVALID_DATA
;
6585 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6587 SPOOL_DSSPOOLER_KEY
,
6588 SPOOL_REG_PRINTSEPARATORFILE
,
6592 if (!W_ERROR_IS_OK(result
)) {
6593 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE
));
6597 if (!force_update
) {
6598 notify_printer_sepfile(server_event_context(),
6601 printer
->sepfile
: "");
6605 if (printer
->starttime
!= 0 &&
6607 printer
->starttime
!= old_printer
->starttime
)) {
6608 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6609 SIVAL(buffer
.data
, 0, printer
->starttime
);
6610 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6612 SPOOL_DSSPOOLER_KEY
,
6613 SPOOL_REG_PRINTSTARTTIME
,
6617 if (!W_ERROR_IS_OK(result
)) {
6618 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME
));
6623 if (printer
->untiltime
!= 0 &&
6625 printer
->untiltime
!= old_printer
->untiltime
)) {
6626 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6627 SIVAL(buffer
.data
, 0, printer
->untiltime
);
6628 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6630 SPOOL_DSSPOOLER_KEY
,
6631 SPOOL_REG_PRINTENDTIME
,
6635 if (!W_ERROR_IS_OK(result
)) {
6636 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME
));
6641 if (force_update
|| printer
->priority
!= old_printer
->priority
) {
6642 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6643 SIVAL(buffer
.data
, 0, printer
->priority
);
6644 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6646 SPOOL_DSSPOOLER_KEY
,
6651 if (!W_ERROR_IS_OK(result
)) {
6652 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME
));
6657 if (force_update
|| printer
->attributes
!= old_printer
->attributes
) {
6658 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6659 SIVAL(buffer
.data
, 0, (printer
->attributes
&
6660 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
6661 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6663 SPOOL_DSSPOOLER_KEY
,
6664 SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
6668 if (!W_ERROR_IS_OK(result
)) {
6669 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME
));
6673 switch (printer
->attributes
& 0x3) {
6675 spooling
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
6678 spooling
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
6681 spooling
= SPOOL_REGVAL_PRINTDIRECT
;
6684 spooling
= "unknown";
6686 ok
= push_reg_sz(tmp_ctx
, &buffer
, spooling
);
6688 DEBUG(0, ("printSpooling data corrupted\n"));
6689 result
= WERR_INVALID_DATA
;
6692 winreg_set_printer_dataex(tmp_ctx
, b
,
6694 SPOOL_DSSPOOLER_KEY
,
6695 SPOOL_REG_PRINTSPOOLING
,
6701 ok
= push_reg_sz(tmp_ctx
, &buffer
, lp_netbios_name());
6703 DEBUG(0, ("shortServerName data corrupted\n"));
6704 result
= WERR_INVALID_DATA
;
6707 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6709 SPOOL_DSSPOOLER_KEY
,
6710 SPOOL_REG_SHORTSERVERNAME
,
6714 if (!W_ERROR_IS_OK(result
)) {
6715 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME
));
6719 dnsdomname
= get_mydnsfullname();
6720 if (dnsdomname
!= NULL
&& dnsdomname
[0] != '\0') {
6721 longname
= talloc_strdup(tmp_ctx
, dnsdomname
);
6723 longname
= talloc_strdup(tmp_ctx
, lp_netbios_name());
6725 if (longname
== NULL
) {
6726 result
= WERR_NOMEM
;
6730 ok
= push_reg_sz(tmp_ctx
, &buffer
, longname
);
6732 DEBUG(0, ("longname data corrupted\n"));
6733 result
= WERR_INVALID_DATA
;
6736 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6738 SPOOL_DSSPOOLER_KEY
,
6739 SPOOL_REG_SERVERNAME
,
6743 if (!W_ERROR_IS_OK(result
)) {
6744 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME
));
6748 uncname
= talloc_asprintf(tmp_ctx
, "\\\\%s\\%s",
6749 lp_netbios_name(), printer
->sharename
);
6750 ok
= push_reg_sz(tmp_ctx
, &buffer
, uncname
);
6752 DEBUG(0, ("uncName data corrupted\n"));
6753 result
= WERR_INVALID_DATA
;
6756 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6758 SPOOL_DSSPOOLER_KEY
,
6763 if (!W_ERROR_IS_OK(result
)) {
6764 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME
));
6769 talloc_free(tmp_ctx
);
6773 /********************************************************************
6774 * Called by spoolss_api_setprinter
6775 * when updating a printer description.
6776 ********************************************************************/
6778 static WERROR
update_printer(struct pipes_struct
*p
,
6779 struct policy_handle
*handle
,
6780 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
6781 struct spoolss_DeviceMode
*devmode
)
6783 uint32_t printer_mask
= SPOOLSS_PRINTER_INFO_ALL
;
6784 struct spoolss_SetPrinterInfo2
*printer
= info_ctr
->info
.info2
;
6785 struct spoolss_PrinterInfo2
*old_printer
;
6786 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6788 WERROR result
= WERR_OK
;
6789 TALLOC_CTX
*tmp_ctx
;
6790 struct dcerpc_binding_handle
*b
;
6792 DEBUG(8,("update_printer\n"));
6794 tmp_ctx
= talloc_new(p
->mem_ctx
);
6795 if (tmp_ctx
== NULL
) {
6800 result
= WERR_BADFID
;
6804 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6805 result
= WERR_BADFID
;
6809 result
= winreg_printer_binding_handle(tmp_ctx
,
6810 get_session_info_system(),
6813 if (!W_ERROR_IS_OK(result
)) {
6817 result
= winreg_get_printer(tmp_ctx
, b
,
6818 lp_const_servicename(snum
),
6820 if (!W_ERROR_IS_OK(result
)) {
6821 result
= WERR_BADFID
;
6825 /* Do sanity check on the requested changes for Samba */
6826 if (!check_printer_ok(tmp_ctx
, printer
, snum
)) {
6827 result
= WERR_INVALID_PARAM
;
6831 /* FIXME!!! If the driver has changed we really should verify that
6832 it is installed before doing much else --jerry */
6834 /* Check calling user has permission to update printer description */
6835 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6836 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6837 result
= WERR_ACCESS_DENIED
;
6841 /* Call addprinter hook */
6842 /* Check changes to see if this is really needed */
6844 if (*lp_addprinter_cmd(talloc_tos()) &&
6845 (!strequal(printer
->drivername
, old_printer
->drivername
) ||
6846 !strequal(printer
->comment
, old_printer
->comment
) ||
6847 !strequal(printer
->portname
, old_printer
->portname
) ||
6848 !strequal(printer
->location
, old_printer
->location
)) )
6852 raddr
= tsocket_address_inet_addr_string(p
->remote_address
,
6854 if (raddr
== NULL
) {
6858 /* add_printer_hook() will call reload_services() */
6859 if (!add_printer_hook(tmp_ctx
, p
->session_info
->security_token
,
6862 result
= WERR_ACCESS_DENIED
;
6867 result
= update_dsspooler(tmp_ctx
,
6868 get_session_info_system(),
6873 if (!W_ERROR_IS_OK(result
)) {
6877 printer_mask
&= ~SPOOLSS_PRINTER_INFO_SECDESC
;
6879 if (devmode
== NULL
) {
6880 printer_mask
&= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
6882 result
= winreg_update_printer(tmp_ctx
, b
,
6890 talloc_free(tmp_ctx
);
6895 /****************************************************************************
6896 ****************************************************************************/
6897 static WERROR
publish_or_unpublish_printer(struct pipes_struct
*p
,
6898 struct policy_handle
*handle
,
6899 struct spoolss_SetPrinterInfo7
*info7
)
6902 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
6905 struct printer_handle
*Printer
;
6907 if ( lp_security() != SEC_ADS
) {
6908 return WERR_UNKNOWN_LEVEL
;
6911 Printer
= find_printer_index_by_hnd(p
, handle
);
6913 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6918 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6921 result
= winreg_get_printer_internal(p
->mem_ctx
,
6922 get_session_info_system(),
6924 lp_servicename(talloc_tos(), snum
),
6926 if (!W_ERROR_IS_OK(result
)) {
6930 nt_printer_publish(pinfo2
,
6931 get_session_info_system(),
6936 TALLOC_FREE(pinfo2
);
6939 return WERR_UNKNOWN_LEVEL
;
6943 /********************************************************************
6944 ********************************************************************/
6946 static WERROR
update_printer_devmode(struct pipes_struct
*p
,
6947 struct policy_handle
*handle
,
6948 struct spoolss_DeviceMode
*devmode
)
6951 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6952 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_DEVMODE
;
6954 DEBUG(8,("update_printer_devmode\n"));
6960 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6964 /* Check calling user has permission to update printer description */
6965 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6966 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6967 return WERR_ACCESS_DENIED
;
6970 return winreg_update_printer_internal(p
->mem_ctx
,
6971 get_session_info_system(),
6973 lp_const_servicename(snum
),
6981 /****************************************************************
6983 ****************************************************************/
6985 WERROR
_spoolss_SetPrinter(struct pipes_struct
*p
,
6986 struct spoolss_SetPrinter
*r
)
6990 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6993 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6994 OUR_HANDLE(r
->in
.handle
)));
6998 /* check the level */
6999 switch (r
->in
.info_ctr
->level
) {
7001 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
7003 result
= update_printer(p
, r
->in
.handle
,
7005 r
->in
.devmode_ctr
->devmode
);
7006 if (!W_ERROR_IS_OK(result
))
7008 if (r
->in
.secdesc_ctr
->sd
)
7009 result
= update_printer_sec(r
->in
.handle
, p
,
7013 return update_printer_sec(r
->in
.handle
, p
,
7016 return publish_or_unpublish_printer(p
, r
->in
.handle
,
7017 r
->in
.info_ctr
->info
.info7
);
7019 return update_printer_devmode(p
, r
->in
.handle
,
7020 r
->in
.devmode_ctr
->devmode
);
7022 return WERR_UNKNOWN_LEVEL
;
7026 /****************************************************************
7027 _spoolss_FindClosePrinterNotify
7028 ****************************************************************/
7030 WERROR
_spoolss_FindClosePrinterNotify(struct pipes_struct
*p
,
7031 struct spoolss_FindClosePrinterNotify
*r
)
7033 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
7036 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7037 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
7041 if (Printer
->notify
.cli_chan
!= NULL
&&
7042 Printer
->notify
.cli_chan
->active_connections
> 0) {
7045 if (Printer
->printer_type
== SPLHND_PRINTER
) {
7046 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7051 srv_spoolss_replycloseprinter(snum
, Printer
);
7054 Printer
->notify
.flags
=0;
7055 Printer
->notify
.options
=0;
7056 Printer
->notify
.localmachine
[0]='\0';
7057 Printer
->notify
.printerlocal
=0;
7058 TALLOC_FREE(Printer
->notify
.option
);
7063 /****************************************************************
7065 ****************************************************************/
7067 WERROR
_spoolss_AddJob(struct pipes_struct
*p
,
7068 struct spoolss_AddJob
*r
)
7070 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7071 return WERR_INVALID_PARAM
;
7074 /* this is what a NT server returns for AddJob. AddJob must fail on
7075 * non-local printers */
7077 if (r
->in
.level
!= 1) {
7078 return WERR_UNKNOWN_LEVEL
;
7081 return WERR_INVALID_PARAM
;
7084 /****************************************************************************
7086 ****************************************************************************/
7088 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
7089 struct spoolss_JobInfo1
*r
,
7090 const print_queue_struct
*queue
,
7092 int position
, int snum
,
7093 struct spoolss_PrinterInfo2
*pinfo2
)
7097 t
= gmtime(&queue
->time
);
7101 r
->printer_name
= lp_servicename(mem_ctx
, snum
);
7102 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
7103 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
7104 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
7105 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
7106 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
7107 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
7108 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
7109 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
7110 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
7111 r
->text_status
= talloc_strdup(mem_ctx
, "");
7112 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
7114 r
->status
= nt_printj_status(queue
->status
);
7115 r
->priority
= queue
->priority
;
7116 r
->position
= position
;
7117 r
->total_pages
= queue
->page_count
;
7118 r
->pages_printed
= 0; /* ??? */
7120 init_systemtime(&r
->submitted
, t
);
7125 /****************************************************************************
7127 ****************************************************************************/
7129 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
7130 struct spoolss_JobInfo2
*r
,
7131 const print_queue_struct
*queue
,
7133 int position
, int snum
,
7134 struct spoolss_PrinterInfo2
*pinfo2
,
7135 struct spoolss_DeviceMode
*devmode
)
7139 t
= gmtime(&queue
->time
);
7143 r
->printer_name
= lp_servicename(mem_ctx
, snum
);
7144 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
7145 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
7146 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
7147 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
7148 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
7149 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
7150 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
7151 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
7152 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
7153 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
7154 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
7155 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
7156 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
7157 r
->parameters
= talloc_strdup(mem_ctx
, "");
7158 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
7159 r
->driver_name
= talloc_strdup(mem_ctx
, pinfo2
->drivername
);
7160 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
7162 r
->devmode
= devmode
;
7164 r
->text_status
= talloc_strdup(mem_ctx
, "");
7165 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
7169 r
->status
= nt_printj_status(queue
->status
);
7170 r
->priority
= queue
->priority
;
7171 r
->position
= position
;
7174 r
->total_pages
= queue
->page_count
;
7175 r
->size
= queue
->size
;
7176 init_systemtime(&r
->submitted
, t
);
7178 r
->pages_printed
= 0; /* ??? */
7183 /****************************************************************************
7184 Enumjobs at level 1.
7185 ****************************************************************************/
7187 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
7188 const print_queue_struct
*queue
,
7189 uint32_t num_queues
, int snum
,
7190 struct spoolss_PrinterInfo2
*pinfo2
,
7191 union spoolss_JobInfo
**info_p
,
7194 union spoolss_JobInfo
*info
;
7196 WERROR result
= WERR_OK
;
7197 uint32_t num_filled
;
7198 struct tdb_print_db
*pdb
;
7200 info
= talloc_array(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7202 result
= WERR_NOMEM
;
7206 pdb
= get_print_db_byname(pinfo2
->sharename
);
7208 result
= WERR_INVALID_PARAM
;
7213 for (i
= 0; i
< num_queues
; i
++) {
7214 uint32_t jobid
= sysjob_to_jobid_pdb(pdb
, queue
[i
].sysjob
);
7215 if (jobid
== (uint32_t)-1) {
7216 DEBUG(4, ("skipping sysjob %d\n", queue
[i
].sysjob
));
7220 result
= fill_job_info1(info
,
7221 &info
[num_filled
].info1
,
7227 if (!W_ERROR_IS_OK(result
)) {
7234 release_print_db(pdb
);
7236 *count
= num_filled
;
7241 release_print_db(pdb
);
7249 /****************************************************************************
7250 Enumjobs at level 2.
7251 ****************************************************************************/
7253 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
7254 const print_queue_struct
*queue
,
7255 uint32_t num_queues
, int snum
,
7256 struct spoolss_PrinterInfo2
*pinfo2
,
7257 union spoolss_JobInfo
**info_p
,
7260 union spoolss_JobInfo
*info
;
7262 WERROR result
= WERR_OK
;
7263 uint32_t num_filled
;
7264 struct tdb_print_db
*pdb
;
7266 info
= talloc_array(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7268 result
= WERR_NOMEM
;
7272 pdb
= get_print_db_byname(pinfo2
->sharename
);
7274 result
= WERR_INVALID_PARAM
;
7279 for (i
= 0; i
< num_queues
; i
++) {
7280 struct spoolss_DeviceMode
*devmode
;
7281 uint32_t jobid
= sysjob_to_jobid_pdb(pdb
, queue
[i
].sysjob
);
7282 if (jobid
== (uint32_t)-1) {
7283 DEBUG(4, ("skipping sysjob %d\n", queue
[i
].sysjob
));
7287 result
= spoolss_create_default_devmode(info
,
7288 pinfo2
->printername
,
7290 if (!W_ERROR_IS_OK(result
)) {
7291 DEBUG(3, ("Can't proceed w/o a devmode!"));
7295 result
= fill_job_info2(info
,
7296 &info
[num_filled
].info2
,
7303 if (!W_ERROR_IS_OK(result
)) {
7309 release_print_db(pdb
);
7311 *count
= num_filled
;
7316 release_print_db(pdb
);
7324 /****************************************************************************
7325 Enumjobs at level 3.
7326 ****************************************************************************/
7328 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
7329 const print_queue_struct
*queue
,
7330 uint32_t num_queues
, int snum
,
7331 struct spoolss_PrinterInfo2
*pinfo2
,
7332 union spoolss_JobInfo
**info_p
,
7335 union spoolss_JobInfo
*info
;
7337 WERROR result
= WERR_OK
;
7338 uint32_t num_filled
;
7339 struct tdb_print_db
*pdb
;
7341 info
= talloc_array(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7343 result
= WERR_NOMEM
;
7347 pdb
= get_print_db_byname(pinfo2
->sharename
);
7349 result
= WERR_INVALID_PARAM
;
7354 for (i
= 0; i
< num_queues
; i
++) {
7355 uint32_t jobid
= sysjob_to_jobid_pdb(pdb
, queue
[i
].sysjob
);
7356 if (jobid
== (uint32_t)-1) {
7357 DEBUG(4, ("skipping sysjob %d\n", queue
[i
].sysjob
));
7361 info
[num_filled
].info3
.job_id
= jobid
;
7362 /* next_job_id is overwritten on next iteration */
7363 info
[num_filled
].info3
.next_job_id
= 0;
7364 info
[num_filled
].info3
.reserved
= 0;
7366 if (num_filled
> 0) {
7367 info
[num_filled
- 1].info3
.next_job_id
= jobid
;
7372 release_print_db(pdb
);
7374 *count
= num_filled
;
7385 /****************************************************************
7387 ****************************************************************/
7389 WERROR
_spoolss_EnumJobs(struct pipes_struct
*p
,
7390 struct spoolss_EnumJobs
*r
)
7393 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
7395 print_status_struct prt_status
;
7396 print_queue_struct
*queue
= NULL
;
7399 /* that's an [in out] buffer */
7401 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7402 return WERR_INVALID_PARAM
;
7405 if ((r
->in
.level
!= 1) && (r
->in
.level
!= 2) && (r
->in
.level
!= 3)) {
7406 DEBUG(4, ("EnumJobs level %d not supported\n", r
->in
.level
));
7407 return WERR_UNKNOWN_LEVEL
;
7410 DEBUG(4,("_spoolss_EnumJobs\n"));
7414 *r
->out
.info
= NULL
;
7416 /* lookup the printer snum and tdb entry */
7418 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7422 result
= winreg_get_printer_internal(p
->mem_ctx
,
7423 get_session_info_system(),
7425 lp_const_servicename(snum
),
7427 if (!W_ERROR_IS_OK(result
)) {
7431 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
7432 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7433 count
, prt_status
.status
, prt_status
.message
));
7437 TALLOC_FREE(pinfo2
);
7441 switch (r
->in
.level
) {
7443 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
7444 pinfo2
, r
->out
.info
, r
->out
.count
);
7447 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
7448 pinfo2
, r
->out
.info
, r
->out
.count
);
7451 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
7452 pinfo2
, r
->out
.info
, r
->out
.count
);
7455 SMB_ASSERT(false); /* level checked on entry */
7460 TALLOC_FREE(pinfo2
);
7462 if (!W_ERROR_IS_OK(result
)) {
7466 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7468 *r
->out
.info
, r
->in
.level
,
7470 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7471 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7473 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7476 /****************************************************************
7477 _spoolss_ScheduleJob
7478 ****************************************************************/
7480 WERROR
_spoolss_ScheduleJob(struct pipes_struct
*p
,
7481 struct spoolss_ScheduleJob
*r
)
7486 /****************************************************************
7487 ****************************************************************/
7489 static WERROR
spoolss_setjob_1(TALLOC_CTX
*mem_ctx
,
7490 struct messaging_context
*msg_ctx
,
7491 const char *printer_name
,
7493 struct spoolss_SetJobInfo1
*r
)
7497 if (!print_job_get_name(mem_ctx
, printer_name
, job_id
, &old_doc_name
)) {
7501 if (strequal(old_doc_name
, r
->document_name
)) {
7505 if (!print_job_set_name(server_event_context(), msg_ctx
,
7506 printer_name
, job_id
, r
->document_name
)) {
7513 /****************************************************************
7515 ****************************************************************/
7517 WERROR
_spoolss_SetJob(struct pipes_struct
*p
,
7518 struct spoolss_SetJob
*r
)
7520 const struct auth_session_info
*session_info
= p
->session_info
;
7522 WERROR errcode
= WERR_BADFUNC
;
7524 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7528 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
7529 return WERR_INVALID_PRINTER_NAME
;
7532 switch (r
->in
.command
) {
7533 case SPOOLSS_JOB_CONTROL_CANCEL
:
7534 case SPOOLSS_JOB_CONTROL_DELETE
:
7535 errcode
= print_job_delete(session_info
, p
->msg_ctx
,
7536 snum
, r
->in
.job_id
);
7537 if (W_ERROR_EQUAL(errcode
, WERR_PRINTER_HAS_JOBS_QUEUED
)) {
7541 case SPOOLSS_JOB_CONTROL_PAUSE
:
7542 errcode
= print_job_pause(session_info
, p
->msg_ctx
,
7543 snum
, r
->in
.job_id
);
7545 case SPOOLSS_JOB_CONTROL_RESTART
:
7546 case SPOOLSS_JOB_CONTROL_RESUME
:
7547 errcode
= print_job_resume(session_info
, p
->msg_ctx
,
7548 snum
, r
->in
.job_id
);
7554 return WERR_UNKNOWN_LEVEL
;
7557 if (!W_ERROR_IS_OK(errcode
)) {
7561 if (r
->in
.ctr
== NULL
) {
7565 switch (r
->in
.ctr
->level
) {
7567 errcode
= spoolss_setjob_1(p
->mem_ctx
, p
->msg_ctx
,
7568 lp_const_servicename(snum
),
7570 r
->in
.ctr
->info
.info1
);
7576 return WERR_UNKNOWN_LEVEL
;
7582 /****************************************************************************
7583 Enumerates all printer drivers by level and architecture.
7584 ****************************************************************************/
7586 static WERROR
enumprinterdrivers_level_by_architecture(TALLOC_CTX
*mem_ctx
,
7587 const struct auth_session_info
*session_info
,
7588 struct messaging_context
*msg_ctx
,
7589 const char *servername
,
7590 const char *architecture
,
7592 union spoolss_DriverInfo
**info_p
,
7597 struct spoolss_DriverInfo8
*driver
;
7598 union spoolss_DriverInfo
*info
= NULL
;
7600 WERROR result
= WERR_OK
;
7601 uint32_t num_drivers
;
7602 const char **drivers
;
7603 struct dcerpc_binding_handle
*b
;
7604 TALLOC_CTX
*tmp_ctx
= NULL
;
7609 tmp_ctx
= talloc_new(mem_ctx
);
7614 result
= winreg_printer_binding_handle(tmp_ctx
,
7618 if (!W_ERROR_IS_OK(result
)) {
7622 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
7623 result
= winreg_get_driver_list(tmp_ctx
, b
,
7624 architecture
, version
,
7625 &num_drivers
, &drivers
);
7626 if (!W_ERROR_IS_OK(result
)) {
7629 DEBUG(4, ("we have:[%d] drivers in environment"
7630 " [%s] and version [%d]\n",
7631 num_drivers
, architecture
, version
));
7633 if (num_drivers
!= 0) {
7634 info
= talloc_realloc(tmp_ctx
, info
,
7635 union spoolss_DriverInfo
,
7636 count
+ num_drivers
);
7638 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7639 "failed to enlarge driver info buffer!\n"));
7640 result
= WERR_NOMEM
;
7645 for (i
= 0; i
< num_drivers
; i
++) {
7646 DEBUG(5, ("\tdriver: [%s]\n", drivers
[i
]));
7648 result
= winreg_get_driver(tmp_ctx
, b
,
7649 architecture
, drivers
[i
],
7651 if (!W_ERROR_IS_OK(result
)) {
7657 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
7658 driver
, servername
);
7661 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
7662 driver
, servername
);
7665 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
7666 driver
, servername
);
7669 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
7670 driver
, servername
);
7673 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
7674 driver
, servername
);
7677 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
7678 driver
, servername
);
7681 result
= fill_printer_driver_info8(info
, &info
[count
+i
].info8
,
7682 driver
, servername
);
7685 result
= WERR_UNKNOWN_LEVEL
;
7689 TALLOC_FREE(driver
);
7691 if (!W_ERROR_IS_OK(result
)) {
7696 count
+= num_drivers
;
7697 TALLOC_FREE(drivers
);
7701 if (W_ERROR_IS_OK(result
)) {
7702 *info_p
= talloc_move(mem_ctx
, &info
);
7706 talloc_free(tmp_ctx
);
7710 /****************************************************************************
7711 Enumerates all printer drivers by level.
7712 ****************************************************************************/
7714 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
7715 const struct auth_session_info
*session_info
,
7716 struct messaging_context
*msg_ctx
,
7717 const char *servername
,
7718 const char *architecture
,
7720 union spoolss_DriverInfo
**info_p
,
7724 WERROR result
= WERR_OK
;
7726 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_ALL
)) {
7728 for (a
=0; archi_table
[a
].long_archi
!= NULL
; a
++) {
7730 union spoolss_DriverInfo
*info
= NULL
;
7733 result
= enumprinterdrivers_level_by_architecture(mem_ctx
,
7737 archi_table
[a
].long_archi
,
7741 if (!W_ERROR_IS_OK(result
)) {
7745 for (i
=0; i
< count
; i
++) {
7746 ADD_TO_ARRAY(mem_ctx
, union spoolss_DriverInfo
,
7747 info
[i
], info_p
, count_p
);
7754 return enumprinterdrivers_level_by_architecture(mem_ctx
,
7764 /****************************************************************
7765 _spoolss_EnumPrinterDrivers
7766 ****************************************************************/
7768 WERROR
_spoolss_EnumPrinterDrivers(struct pipes_struct
*p
,
7769 struct spoolss_EnumPrinterDrivers
*r
)
7771 const char *cservername
;
7774 /* that's an [in out] buffer */
7776 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7777 return WERR_INVALID_PARAM
;
7780 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7784 *r
->out
.info
= NULL
;
7786 cservername
= canon_servername(r
->in
.server
);
7788 if (!is_myname_or_ipaddr(cservername
)) {
7789 return WERR_UNKNOWN_PRINTER_DRIVER
;
7792 result
= enumprinterdrivers_level(p
->mem_ctx
,
7793 get_session_info_system(),
7800 if (!W_ERROR_IS_OK(result
)) {
7804 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7805 spoolss_EnumPrinterDrivers
,
7806 *r
->out
.info
, r
->in
.level
,
7808 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7809 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7811 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7814 /****************************************************************
7816 ****************************************************************/
7818 WERROR
_spoolss_EnumForms(struct pipes_struct
*p
,
7819 struct spoolss_EnumForms
*r
)
7825 *r
->out
.info
= NULL
;
7827 /* that's an [in out] buffer */
7829 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
7830 return WERR_INVALID_PARAM
;
7833 DEBUG(4,("_spoolss_EnumForms\n"));
7834 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7835 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7837 switch (r
->in
.level
) {
7839 result
= winreg_printer_enumforms1_internal(p
->mem_ctx
,
7840 get_session_info_system(),
7846 result
= WERR_UNKNOWN_LEVEL
;
7850 if (!W_ERROR_IS_OK(result
)) {
7854 if (*r
->out
.count
== 0) {
7855 return WERR_NO_MORE_ITEMS
;
7858 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7860 *r
->out
.info
, r
->in
.level
,
7862 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7863 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7865 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7868 /****************************************************************
7870 ****************************************************************/
7872 WERROR
_spoolss_GetForm(struct pipes_struct
*p
,
7873 struct spoolss_GetForm
*r
)
7877 /* that's an [in out] buffer */
7879 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7880 TALLOC_FREE(r
->out
.info
);
7881 return WERR_INVALID_PARAM
;
7884 DEBUG(4,("_spoolss_GetForm\n"));
7885 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7886 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7888 switch (r
->in
.level
) {
7890 result
= winreg_printer_getform1_internal(p
->mem_ctx
,
7891 get_session_info_system(),
7894 &r
->out
.info
->info1
);
7897 result
= WERR_UNKNOWN_LEVEL
;
7901 if (!W_ERROR_IS_OK(result
)) {
7902 TALLOC_FREE(r
->out
.info
);
7906 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
,
7907 r
->out
.info
, r
->in
.level
);
7908 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7910 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7913 /****************************************************************************
7914 ****************************************************************************/
7916 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
7917 struct spoolss_PortInfo1
*r
,
7920 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7921 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7926 /****************************************************************************
7927 TODO: This probably needs distinguish between TCP/IP and Local ports
7929 ****************************************************************************/
7931 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
7932 struct spoolss_PortInfo2
*r
,
7935 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7936 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7938 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
7939 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
7941 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
7942 W_ERROR_HAVE_NO_MEMORY(r
->description
);
7944 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
7951 /****************************************************************************
7952 wrapper around the enumer ports command
7953 ****************************************************************************/
7955 static WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
7957 char *cmd
= lp_enumports_cmd(talloc_tos());
7958 char **qlines
= NULL
;
7959 char *command
= NULL
;
7967 /* if no hook then just fill in the default port */
7970 if (!(qlines
= talloc_array( NULL
, char*, 2 ))) {
7973 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
7974 TALLOC_FREE(qlines
);
7981 /* we have a valid enumport command */
7983 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
7988 DEBUG(10,("Running [%s]\n", command
));
7989 ret
= smbrun(command
, &fd
);
7990 DEBUG(10,("Returned [%d]\n", ret
));
7991 TALLOC_FREE(command
);
7996 return WERR_ACCESS_DENIED
;
8000 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
8001 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
8011 /****************************************************************************
8013 ****************************************************************************/
8015 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
8016 union spoolss_PortInfo
**info_p
,
8019 union spoolss_PortInfo
*info
= NULL
;
8021 WERROR result
= WERR_OK
;
8022 char **qlines
= NULL
;
8025 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
8026 if (!W_ERROR_IS_OK(result
)) {
8031 info
= talloc_array(mem_ctx
, union spoolss_PortInfo
, numlines
);
8033 DEBUG(10,("Returning WERR_NOMEM\n"));
8034 result
= WERR_NOMEM
;
8038 for (i
=0; i
<numlines
; i
++) {
8039 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
8040 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
8041 if (!W_ERROR_IS_OK(result
)) {
8046 TALLOC_FREE(qlines
);
8049 if (!W_ERROR_IS_OK(result
)) {
8051 TALLOC_FREE(qlines
);
8063 /****************************************************************************
8065 ****************************************************************************/
8067 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
8068 union spoolss_PortInfo
**info_p
,
8071 union spoolss_PortInfo
*info
= NULL
;
8073 WERROR result
= WERR_OK
;
8074 char **qlines
= NULL
;
8077 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
8078 if (!W_ERROR_IS_OK(result
)) {
8083 info
= talloc_array(mem_ctx
, union spoolss_PortInfo
, numlines
);
8085 DEBUG(10,("Returning WERR_NOMEM\n"));
8086 result
= WERR_NOMEM
;
8090 for (i
=0; i
<numlines
; i
++) {
8091 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
8092 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
8093 if (!W_ERROR_IS_OK(result
)) {
8098 TALLOC_FREE(qlines
);
8101 if (!W_ERROR_IS_OK(result
)) {
8103 TALLOC_FREE(qlines
);
8115 /****************************************************************
8117 ****************************************************************/
8119 WERROR
_spoolss_EnumPorts(struct pipes_struct
*p
,
8120 struct spoolss_EnumPorts
*r
)
8124 /* that's an [in out] buffer */
8126 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8127 return WERR_INVALID_PARAM
;
8130 DEBUG(4,("_spoolss_EnumPorts\n"));
8134 *r
->out
.info
= NULL
;
8136 switch (r
->in
.level
) {
8138 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
8142 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
8146 return WERR_UNKNOWN_LEVEL
;
8149 if (!W_ERROR_IS_OK(result
)) {
8153 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8155 *r
->out
.info
, r
->in
.level
,
8157 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8158 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8160 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8163 /****************************************************************************
8164 ****************************************************************************/
8166 static WERROR
spoolss_addprinterex_level_2(struct pipes_struct
*p
,
8168 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
8169 struct spoolss_DeviceMode
*devmode
,
8170 struct security_descriptor
*secdesc
,
8171 struct spoolss_UserLevelCtr
*user_ctr
,
8172 struct policy_handle
*handle
)
8174 struct spoolss_SetPrinterInfo2
*info2
= info_ctr
->info
.info2
;
8175 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_ALL
;
8177 WERROR err
= WERR_OK
;
8179 /* samba does not have a concept of local, non-shared printers yet, so
8180 * make sure we always setup sharename - gd */
8181 if ((info2
->sharename
== NULL
|| info2
->sharename
[0] == '\0') &&
8182 (info2
->printername
!= NULL
&& info2
->printername
[0] != '\0')) {
8183 DEBUG(5, ("spoolss_addprinterex_level_2: "
8184 "no sharename has been set, setting printername %s as sharename\n",
8185 info2
->printername
));
8186 info2
->sharename
= info2
->printername
;
8189 /* check to see if the printer already exists */
8190 if ((snum
= print_queue_snum(info2
->sharename
)) != -1) {
8191 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8193 return WERR_PRINTER_ALREADY_EXISTS
;
8196 if (!lp_force_printername(GLOBAL_SECTION_SNUM
)) {
8197 if ((snum
= print_queue_snum(info2
->printername
)) != -1) {
8198 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8199 info2
->printername
));
8200 return WERR_PRINTER_ALREADY_EXISTS
;
8204 /* validate printer info struct */
8205 if (!info2
->printername
|| strlen(info2
->printername
) == 0) {
8206 return WERR_INVALID_PRINTER_NAME
;
8208 if (!info2
->portname
|| strlen(info2
->portname
) == 0) {
8209 return WERR_UNKNOWN_PORT
;
8211 if (!info2
->drivername
|| strlen(info2
->drivername
) == 0) {
8212 return WERR_UNKNOWN_PRINTER_DRIVER
;
8214 if (!info2
->printprocessor
|| strlen(info2
->printprocessor
) == 0) {
8215 return WERR_UNKNOWN_PRINTPROCESSOR
;
8218 /* FIXME!!! smbd should check to see if the driver is installed before
8219 trying to add a printer like this --jerry */
8221 if (*lp_addprinter_cmd(talloc_tos()) ) {
8224 raddr
= tsocket_address_inet_addr_string(p
->remote_address
,
8226 if (raddr
== NULL
) {
8230 if ( !add_printer_hook(p
->mem_ctx
, p
->session_info
->security_token
,
8233 return WERR_ACCESS_DENIED
;
8236 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8237 "smb.conf parameter \"addprinter command\" is defined. This "
8238 "parameter must exist for this call to succeed\n",
8239 info2
->sharename
));
8242 if ((snum
= print_queue_snum(info2
->sharename
)) == -1) {
8243 return WERR_ACCESS_DENIED
;
8246 /* you must be a printer admin to add a new printer */
8247 if (!print_access_check(p
->session_info
,
8250 PRINTER_ACCESS_ADMINISTER
)) {
8251 return WERR_ACCESS_DENIED
;
8255 * Do sanity check on the requested changes for Samba.
8258 if (!check_printer_ok(p
->mem_ctx
, info2
, snum
)) {
8259 return WERR_INVALID_PARAM
;
8262 if (devmode
== NULL
) {
8263 info2_mask
= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
8266 err
= update_dsspooler(p
->mem_ctx
,
8267 get_session_info_system(),
8272 if (!W_ERROR_IS_OK(err
)) {
8276 err
= winreg_update_printer_internal(p
->mem_ctx
,
8277 get_session_info_system(),
8284 if (!W_ERROR_IS_OK(err
)) {
8288 err
= open_printer_hnd(p
, handle
, info2
->printername
, PRINTER_ACCESS_ADMINISTER
);
8289 if (!W_ERROR_IS_OK(err
)) {
8290 /* Handle open failed - remove addition. */
8291 ZERO_STRUCTP(handle
);
8298 /****************************************************************
8299 _spoolss_AddPrinterEx
8300 ****************************************************************/
8302 WERROR
_spoolss_AddPrinterEx(struct pipes_struct
*p
,
8303 struct spoolss_AddPrinterEx
*r
)
8305 switch (r
->in
.info_ctr
->level
) {
8307 /* we don't handle yet */
8308 /* but I know what to do ... */
8309 return WERR_UNKNOWN_LEVEL
;
8311 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
8313 r
->in
.devmode_ctr
->devmode
,
8314 r
->in
.secdesc_ctr
->sd
,
8315 r
->in
.userlevel_ctr
,
8318 return WERR_UNKNOWN_LEVEL
;
8322 /****************************************************************
8324 ****************************************************************/
8326 WERROR
_spoolss_AddPrinter(struct pipes_struct
*p
,
8327 struct spoolss_AddPrinter
*r
)
8329 struct spoolss_AddPrinterEx a
;
8330 struct spoolss_UserLevelCtr userlevel_ctr
;
8332 ZERO_STRUCT(userlevel_ctr
);
8334 userlevel_ctr
.level
= 1;
8336 a
.in
.server
= r
->in
.server
;
8337 a
.in
.info_ctr
= r
->in
.info_ctr
;
8338 a
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
8339 a
.in
.secdesc_ctr
= r
->in
.secdesc_ctr
;
8340 a
.in
.userlevel_ctr
= &userlevel_ctr
;
8341 a
.out
.handle
= r
->out
.handle
;
8343 return _spoolss_AddPrinterEx(p
, &a
);
8346 /****************************************************************
8347 _spoolss_AddPrinterDriverEx
8348 ****************************************************************/
8350 WERROR
_spoolss_AddPrinterDriverEx(struct pipes_struct
*p
,
8351 struct spoolss_AddPrinterDriverEx
*r
)
8353 WERROR err
= WERR_OK
;
8354 const char *driver_name
= NULL
;
8359 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
8360 fn
= "_spoolss_AddPrinterDriver";
8362 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
8363 fn
= "_spoolss_AddPrinterDriverEx";
8366 return WERR_INVALID_PARAM
;
8370 * we only support the semantics of AddPrinterDriver()
8371 * i.e. only copy files that are newer than existing ones
8374 if (r
->in
.flags
== 0) {
8375 return WERR_INVALID_PARAM
;
8378 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
8379 return WERR_ACCESS_DENIED
;
8383 if (r
->in
.info_ctr
->level
!= 3 && r
->in
.info_ctr
->level
!= 6) {
8384 /* Clever hack from Martin Zielinski <mz@seh.de>
8385 * to allow downgrade from level 8 (Vista).
8387 DEBUG(0,("%s: level %d not yet implemented\n", fn
,
8388 r
->in
.info_ctr
->level
));
8389 return WERR_UNKNOWN_LEVEL
;
8392 DEBUG(5,("Cleaning driver's information\n"));
8393 err
= clean_up_driver_struct(p
->mem_ctx
, p
->session_info
, r
->in
.info_ctr
);
8394 if (!W_ERROR_IS_OK(err
))
8397 DEBUG(5,("Moving driver to final destination\n"));
8398 err
= move_driver_to_download_area(p
->session_info
, r
->in
.info_ctr
);
8399 if (!W_ERROR_IS_OK(err
)) {
8403 err
= winreg_add_driver_internal(p
->mem_ctx
,
8404 get_session_info_system(),
8409 if (!W_ERROR_IS_OK(err
)) {
8414 * I think this is where he DrvUpgradePrinter() hook would be
8415 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8416 * server. Right now, we just need to send ourselves a message
8417 * to update each printer bound to this driver. --jerry
8420 if (!srv_spoolss_drv_upgrade_printer(driver_name
, p
->msg_ctx
)) {
8421 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8429 /****************************************************************
8430 _spoolss_AddPrinterDriver
8431 ****************************************************************/
8433 WERROR
_spoolss_AddPrinterDriver(struct pipes_struct
*p
,
8434 struct spoolss_AddPrinterDriver
*r
)
8436 struct spoolss_AddPrinterDriverEx a
;
8438 switch (r
->in
.info_ctr
->level
) {
8445 return WERR_UNKNOWN_LEVEL
;
8448 a
.in
.servername
= r
->in
.servername
;
8449 a
.in
.info_ctr
= r
->in
.info_ctr
;
8450 a
.in
.flags
= APD_COPY_NEW_FILES
;
8452 return _spoolss_AddPrinterDriverEx(p
, &a
);
8455 /****************************************************************************
8456 ****************************************************************************/
8458 struct _spoolss_paths
{
8464 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
8466 static const struct _spoolss_paths spoolss_paths
[]= {
8467 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
8468 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
8471 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
8472 const char *servername
,
8473 const char *environment
,
8477 const char *pservername
= NULL
;
8478 const char *long_archi
;
8479 const char *short_archi
;
8483 /* environment may be empty */
8484 if (environment
&& strlen(environment
)) {
8485 long_archi
= environment
;
8487 long_archi
= lp_parm_const_string(GLOBAL_SECTION_SNUM
,
8488 "spoolss", "architecture",
8489 SPOOLSS_ARCHITECTURE_NT_X86
);
8492 /* servername may be empty */
8493 if (servername
&& strlen(servername
)) {
8494 pservername
= canon_servername(servername
);
8496 if (!is_myname_or_ipaddr(pservername
)) {
8497 return WERR_INVALID_PARAM
;
8501 if (!(short_archi
= get_short_archi(long_archi
))) {
8502 return WERR_INVALID_ENVIRONMENT
;
8505 switch (component
) {
8506 case SPOOLSS_PRTPROCS_PATH
:
8507 case SPOOLSS_DRIVER_PATH
:
8509 *path
= talloc_asprintf(mem_ctx
,
8512 spoolss_paths
[component
].share
,
8515 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
8516 SPOOLSS_DEFAULT_SERVER_PATH
,
8517 spoolss_paths
[component
].dir
,
8522 return WERR_INVALID_PARAM
;
8532 /****************************************************************************
8533 ****************************************************************************/
8535 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
8536 const char *servername
,
8537 const char *environment
,
8538 struct spoolss_DriverDirectoryInfo1
*r
)
8543 werr
= compose_spoolss_server_path(mem_ctx
,
8546 SPOOLSS_DRIVER_PATH
,
8548 if (!W_ERROR_IS_OK(werr
)) {
8552 DEBUG(4,("printer driver directory: [%s]\n", path
));
8554 r
->directory_name
= path
;
8559 /****************************************************************
8560 _spoolss_GetPrinterDriverDirectory
8561 ****************************************************************/
8563 WERROR
_spoolss_GetPrinterDriverDirectory(struct pipes_struct
*p
,
8564 struct spoolss_GetPrinterDriverDirectory
*r
)
8568 /* that's an [in out] buffer */
8570 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8571 TALLOC_FREE(r
->out
.info
);
8572 return WERR_INVALID_PARAM
;
8575 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8580 /* r->in.level is ignored */
8582 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
8585 &r
->out
.info
->info1
);
8586 if (!W_ERROR_IS_OK(werror
)) {
8587 TALLOC_FREE(r
->out
.info
);
8591 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
,
8592 r
->out
.info
, r
->in
.level
);
8593 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8595 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8598 /****************************************************************
8599 _spoolss_EnumPrinterData
8600 ****************************************************************/
8602 WERROR
_spoolss_EnumPrinterData(struct pipes_struct
*p
,
8603 struct spoolss_EnumPrinterData
*r
)
8606 struct spoolss_EnumPrinterDataEx r2
;
8608 struct spoolss_PrinterEnumValues
*info
, *val
= NULL
;
8611 r2
.in
.handle
= r
->in
.handle
;
8612 r2
.in
.key_name
= "PrinterDriverData";
8614 r2
.out
.count
= &count
;
8615 r2
.out
.info
= &info
;
8616 r2
.out
.needed
= &needed
;
8618 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
8619 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
8620 r2
.in
.offered
= needed
;
8621 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
8623 if (!W_ERROR_IS_OK(result
)) {
8628 * The NT machine wants to know the biggest size of value and data
8630 * cf: MSDN EnumPrinterData remark section
8633 if (!r
->in
.value_offered
&& !r
->in
.data_offered
) {
8634 uint32_t biggest_valuesize
= 0;
8635 uint32_t biggest_datasize
= 0;
8638 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8640 for (i
=0; i
<count
; i
++) {
8642 name_length
= strlen(info
[i
].value_name
);
8643 if (strlen(info
[i
].value_name
) > biggest_valuesize
) {
8644 biggest_valuesize
= name_length
;
8647 if (info
[i
].data_length
> biggest_datasize
) {
8648 biggest_datasize
= info
[i
].data_length
;
8651 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
8655 /* the value is an UNICODE string but real_value_size is the length
8656 in bytes including the trailing 0 */
8658 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
8659 *r
->out
.data_needed
= biggest_datasize
;
8661 DEBUG(6,("final values: [%d], [%d]\n",
8662 *r
->out
.value_needed
, *r
->out
.data_needed
));
8667 if (r
->in
.enum_index
< count
) {
8668 val
= &info
[r
->in
.enum_index
];
8672 /* out_value should default to "" or else NT4 has
8673 problems unmarshalling the response */
8675 if (r
->in
.value_offered
) {
8676 *r
->out
.value_needed
= 1;
8677 r
->out
.value_name
= talloc_strdup(r
, "");
8678 if (!r
->out
.value_name
) {
8682 r
->out
.value_name
= NULL
;
8683 *r
->out
.value_needed
= 0;
8686 /* the data is counted in bytes */
8688 *r
->out
.data_needed
= r
->in
.data_offered
;
8690 result
= WERR_NO_MORE_ITEMS
;
8694 * - counted in bytes in the request
8695 * - counted in UNICODE chars in the max reply
8696 * - counted in bytes in the real size
8698 * take a pause *before* coding not *during* coding
8702 if (r
->in
.value_offered
) {
8703 r
->out
.value_name
= talloc_strdup(r
, val
->value_name
);
8704 if (!r
->out
.value_name
) {
8707 *r
->out
.value_needed
= val
->value_name_len
;
8709 r
->out
.value_name
= NULL
;
8710 *r
->out
.value_needed
= 0;
8715 *r
->out
.type
= val
->type
;
8717 /* data - counted in bytes */
8720 * See the section "Dynamically Typed Query Parameters"
8724 if (r
->out
.data
&& val
->data
&& val
->data
->data
&&
8725 val
->data_length
&& r
->in
.data_offered
) {
8726 memcpy(r
->out
.data
, val
->data
->data
,
8727 MIN(val
->data_length
,r
->in
.data_offered
));
8730 *r
->out
.data_needed
= val
->data_length
;
8738 /****************************************************************
8739 _spoolss_SetPrinterData
8740 ****************************************************************/
8742 WERROR
_spoolss_SetPrinterData(struct pipes_struct
*p
,
8743 struct spoolss_SetPrinterData
*r
)
8745 struct spoolss_SetPrinterDataEx r2
;
8747 r2
.in
.handle
= r
->in
.handle
;
8748 r2
.in
.key_name
= "PrinterDriverData";
8749 r2
.in
.value_name
= r
->in
.value_name
;
8750 r2
.in
.type
= r
->in
.type
;
8751 r2
.in
.data
= r
->in
.data
;
8752 r2
.in
.offered
= r
->in
.offered
;
8754 return _spoolss_SetPrinterDataEx(p
, &r2
);
8757 /****************************************************************
8758 _spoolss_ResetPrinter
8759 ****************************************************************/
8761 WERROR
_spoolss_ResetPrinter(struct pipes_struct
*p
,
8762 struct spoolss_ResetPrinter
*r
)
8764 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8767 DEBUG(5,("_spoolss_ResetPrinter\n"));
8770 * All we do is to check to see if the handle and queue is valid.
8771 * This call really doesn't mean anything to us because we only
8772 * support RAW printing. --jerry
8776 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8777 OUR_HANDLE(r
->in
.handle
)));
8781 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8785 /* blindly return success */
8789 /****************************************************************
8790 _spoolss_DeletePrinterData
8791 ****************************************************************/
8793 WERROR
_spoolss_DeletePrinterData(struct pipes_struct
*p
,
8794 struct spoolss_DeletePrinterData
*r
)
8796 struct spoolss_DeletePrinterDataEx r2
;
8798 r2
.in
.handle
= r
->in
.handle
;
8799 r2
.in
.key_name
= "PrinterDriverData";
8800 r2
.in
.value_name
= r
->in
.value_name
;
8802 return _spoolss_DeletePrinterDataEx(p
, &r2
);
8805 /****************************************************************
8807 ****************************************************************/
8809 WERROR
_spoolss_AddForm(struct pipes_struct
*p
,
8810 struct spoolss_AddForm
*r
)
8812 struct spoolss_AddFormInfo1
*form
;
8814 WERROR status
= WERR_OK
;
8815 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8816 struct dcerpc_binding_handle
*b
;
8817 TALLOC_CTX
*tmp_ctx
= NULL
;
8819 DEBUG(5,("_spoolss_AddForm\n"));
8822 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8823 OUR_HANDLE(r
->in
.handle
)));
8827 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8828 and not a printer admin, then fail */
8830 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
8831 !security_token_has_privilege(p
->session_info
->security_token
,
8832 SEC_PRIV_PRINT_OPERATOR
)) {
8833 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8834 return WERR_ACCESS_DENIED
;
8837 if (r
->in
.info_ctr
->level
!= 1) {
8838 return WERR_INVALID_LEVEL
;
8841 form
= r
->in
.info_ctr
->info
.info1
;
8843 return WERR_INVALID_PARAM
;
8846 switch (form
->flags
) {
8847 case SPOOLSS_FORM_USER
:
8848 case SPOOLSS_FORM_BUILTIN
:
8849 case SPOOLSS_FORM_PRINTER
:
8852 return WERR_INVALID_PARAM
;
8855 tmp_ctx
= talloc_new(p
->mem_ctx
);
8860 status
= winreg_printer_binding_handle(tmp_ctx
,
8861 get_session_info_system(),
8864 if (!W_ERROR_IS_OK(status
)) {
8868 status
= winreg_printer_addform1(tmp_ctx
, b
, form
);
8869 if (!W_ERROR_IS_OK(status
)) {
8874 * ChangeID must always be set if this is a printer
8876 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8877 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8878 status
= WERR_BADFID
;
8882 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
8883 lp_const_servicename(snum
));
8887 talloc_free(tmp_ctx
);
8891 /****************************************************************
8893 ****************************************************************/
8895 WERROR
_spoolss_DeleteForm(struct pipes_struct
*p
,
8896 struct spoolss_DeleteForm
*r
)
8898 const char *form_name
= r
->in
.form_name
;
8899 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8901 WERROR status
= WERR_OK
;
8902 struct dcerpc_binding_handle
*b
;
8903 TALLOC_CTX
*tmp_ctx
= NULL
;
8905 DEBUG(5,("_spoolss_DeleteForm\n"));
8908 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8909 OUR_HANDLE(r
->in
.handle
)));
8913 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
8914 !security_token_has_privilege(p
->session_info
->security_token
,
8915 SEC_PRIV_PRINT_OPERATOR
)) {
8916 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8917 return WERR_ACCESS_DENIED
;
8920 tmp_ctx
= talloc_new(p
->mem_ctx
);
8925 status
= winreg_printer_binding_handle(tmp_ctx
,
8926 get_session_info_system(),
8929 if (!W_ERROR_IS_OK(status
)) {
8933 status
= winreg_printer_deleteform1(tmp_ctx
, b
, form_name
);
8934 if (!W_ERROR_IS_OK(status
)) {
8939 * ChangeID must always be set if this is a printer
8941 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8942 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8943 status
= WERR_BADFID
;
8947 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
8948 lp_const_servicename(snum
));
8952 talloc_free(tmp_ctx
);
8956 /****************************************************************
8958 ****************************************************************/
8960 WERROR
_spoolss_SetForm(struct pipes_struct
*p
,
8961 struct spoolss_SetForm
*r
)
8963 struct spoolss_AddFormInfo1
*form
;
8964 const char *form_name
= r
->in
.form_name
;
8966 WERROR status
= WERR_OK
;
8967 struct dcerpc_binding_handle
*b
;
8968 TALLOC_CTX
*tmp_ctx
= NULL
;
8970 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8972 DEBUG(5,("_spoolss_SetForm\n"));
8975 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8976 OUR_HANDLE(r
->in
.handle
)));
8980 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8981 and not a printer admin, then fail */
8983 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
8984 !security_token_has_privilege(p
->session_info
->security_token
,
8985 SEC_PRIV_PRINT_OPERATOR
)) {
8986 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8987 return WERR_ACCESS_DENIED
;
8990 if (r
->in
.info_ctr
->level
!= 1) {
8991 return WERR_INVALID_LEVEL
;
8994 form
= r
->in
.info_ctr
->info
.info1
;
8996 return WERR_INVALID_PARAM
;
8999 tmp_ctx
= talloc_new(p
->mem_ctx
);
9004 status
= winreg_printer_binding_handle(tmp_ctx
,
9005 get_session_info_system(),
9008 if (!W_ERROR_IS_OK(status
)) {
9012 status
= winreg_printer_setform1(tmp_ctx
, b
,
9015 if (!W_ERROR_IS_OK(status
)) {
9020 * ChangeID must always be set if this is a printer
9022 if (Printer
->printer_type
== SPLHND_PRINTER
) {
9023 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9024 status
= WERR_BADFID
;
9028 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
9029 lp_const_servicename(snum
));
9033 talloc_free(tmp_ctx
);
9037 /****************************************************************************
9038 fill_print_processor1
9039 ****************************************************************************/
9041 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
9042 struct spoolss_PrintProcessorInfo1
*r
,
9043 const char *print_processor_name
)
9045 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
9046 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
9051 /****************************************************************************
9052 enumprintprocessors level 1.
9053 ****************************************************************************/
9055 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
9056 union spoolss_PrintProcessorInfo
**info_p
,
9059 union spoolss_PrintProcessorInfo
*info
;
9062 info
= talloc_array(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
9063 W_ERROR_HAVE_NO_MEMORY(info
);
9067 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
9068 if (!W_ERROR_IS_OK(result
)) {
9073 if (!W_ERROR_IS_OK(result
)) {
9084 /****************************************************************
9085 _spoolss_EnumPrintProcessors
9086 ****************************************************************/
9088 WERROR
_spoolss_EnumPrintProcessors(struct pipes_struct
*p
,
9089 struct spoolss_EnumPrintProcessors
*r
)
9093 /* that's an [in out] buffer */
9095 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9096 return WERR_INVALID_PARAM
;
9099 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9102 * Enumerate the print processors ...
9104 * Just reply with "winprint", to keep NT happy
9105 * and I can use my nice printer checker.
9110 *r
->out
.info
= NULL
;
9112 if (!get_short_archi(r
->in
.environment
)) {
9113 return WERR_INVALID_ENVIRONMENT
;
9116 switch (r
->in
.level
) {
9118 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
9122 return WERR_UNKNOWN_LEVEL
;
9125 if (!W_ERROR_IS_OK(result
)) {
9129 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
9130 spoolss_EnumPrintProcessors
,
9131 *r
->out
.info
, r
->in
.level
,
9133 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9134 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
9136 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9139 /****************************************************************************
9140 fill_printprocdatatype1
9141 ****************************************************************************/
9143 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
9144 struct spoolss_PrintProcDataTypesInfo1
*r
,
9145 const char *name_array
)
9147 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
9148 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
9153 /****************************************************************************
9154 enumprintprocdatatypes level 1.
9155 ****************************************************************************/
9157 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
9158 union spoolss_PrintProcDataTypesInfo
**info_p
,
9162 union spoolss_PrintProcDataTypesInfo
*info
;
9164 info
= talloc_array(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
9165 W_ERROR_HAVE_NO_MEMORY(info
);
9169 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
9170 if (!W_ERROR_IS_OK(result
)) {
9175 if (!W_ERROR_IS_OK(result
)) {
9186 /****************************************************************
9187 _spoolss_EnumPrintProcDataTypes
9188 ****************************************************************/
9190 WERROR
_spoolss_EnumPrintProcDataTypes(struct pipes_struct
*p
,
9191 struct spoolss_EnumPrintProcDataTypes
*r
)
9195 /* that's an [in out] buffer */
9197 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9198 return WERR_INVALID_PARAM
;
9201 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9205 *r
->out
.info
= NULL
;
9207 if (r
->in
.print_processor_name
== NULL
||
9208 !strequal(r
->in
.print_processor_name
, "winprint")) {
9209 return WERR_UNKNOWN_PRINTPROCESSOR
;
9212 switch (r
->in
.level
) {
9214 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
9218 return WERR_UNKNOWN_LEVEL
;
9221 if (!W_ERROR_IS_OK(result
)) {
9225 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
9226 spoolss_EnumPrintProcDataTypes
,
9227 *r
->out
.info
, r
->in
.level
,
9229 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9230 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
9232 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9235 /****************************************************************************
9237 ****************************************************************************/
9239 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
9240 struct spoolss_MonitorInfo1
*r
,
9241 const char *monitor_name
)
9243 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
9244 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
9249 /****************************************************************************
9251 ****************************************************************************/
9253 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
9254 struct spoolss_MonitorInfo2
*r
,
9255 const char *monitor_name
,
9256 const char *environment
,
9257 const char *dll_name
)
9259 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
9260 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
9261 r
->environment
= talloc_strdup(mem_ctx
, environment
);
9262 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
9263 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
9264 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
9269 /****************************************************************************
9270 enumprintmonitors level 1.
9271 ****************************************************************************/
9273 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
9274 union spoolss_MonitorInfo
**info_p
,
9277 union spoolss_MonitorInfo
*info
;
9278 WERROR result
= WERR_OK
;
9280 info
= talloc_array(mem_ctx
, union spoolss_MonitorInfo
, 2);
9281 W_ERROR_HAVE_NO_MEMORY(info
);
9285 result
= fill_monitor_1(info
, &info
[0].info1
,
9287 if (!W_ERROR_IS_OK(result
)) {
9291 result
= fill_monitor_1(info
, &info
[1].info1
,
9293 if (!W_ERROR_IS_OK(result
)) {
9298 if (!W_ERROR_IS_OK(result
)) {
9309 /****************************************************************************
9310 enumprintmonitors level 2.
9311 ****************************************************************************/
9313 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
9314 union spoolss_MonitorInfo
**info_p
,
9317 union spoolss_MonitorInfo
*info
;
9318 WERROR result
= WERR_OK
;
9320 info
= talloc_array(mem_ctx
, union spoolss_MonitorInfo
, 2);
9321 W_ERROR_HAVE_NO_MEMORY(info
);
9325 result
= fill_monitor_2(info
, &info
[0].info2
,
9327 "Windows NT X86", /* FIXME */
9329 if (!W_ERROR_IS_OK(result
)) {
9333 result
= fill_monitor_2(info
, &info
[1].info2
,
9335 "Windows NT X86", /* FIXME */
9337 if (!W_ERROR_IS_OK(result
)) {
9342 if (!W_ERROR_IS_OK(result
)) {
9353 /****************************************************************
9354 _spoolss_EnumMonitors
9355 ****************************************************************/
9357 WERROR
_spoolss_EnumMonitors(struct pipes_struct
*p
,
9358 struct spoolss_EnumMonitors
*r
)
9362 /* that's an [in out] buffer */
9364 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9365 return WERR_INVALID_PARAM
;
9368 DEBUG(5,("_spoolss_EnumMonitors\n"));
9371 * Enumerate the print monitors ...
9373 * Just reply with "Local Port", to keep NT happy
9374 * and I can use my nice printer checker.
9379 *r
->out
.info
= NULL
;
9381 switch (r
->in
.level
) {
9383 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
9387 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
9391 return WERR_UNKNOWN_LEVEL
;
9394 if (!W_ERROR_IS_OK(result
)) {
9398 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
9399 spoolss_EnumMonitors
,
9400 *r
->out
.info
, r
->in
.level
,
9402 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9403 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
9405 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9408 /****************************************************************************
9409 ****************************************************************************/
9411 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
9412 const print_queue_struct
*queue
,
9413 int count
, int snum
,
9414 struct spoolss_PrinterInfo2
*pinfo2
,
9417 struct spoolss_JobInfo1
*r
)
9422 for (i
=0; i
<count
; i
++) {
9423 if (queue
[i
].sysjob
== sysjob
) {
9429 if (found
== false) {
9430 /* NT treats not found as bad param... yet another bad choice */
9431 return WERR_INVALID_PARAM
;
9434 return fill_job_info1(mem_ctx
,
9443 /****************************************************************************
9444 ****************************************************************************/
9446 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
9447 const print_queue_struct
*queue
,
9448 int count
, int snum
,
9449 struct spoolss_PrinterInfo2
*pinfo2
,
9452 struct spoolss_JobInfo2
*r
)
9456 struct spoolss_DeviceMode
*devmode
;
9459 for (i
=0; i
<count
; i
++) {
9460 if (queue
[i
].sysjob
== sysjob
) {
9466 if (found
== false) {
9467 /* NT treats not found as bad param... yet another bad
9469 return WERR_INVALID_PARAM
;
9473 * if the print job does not have a DEVMODE associated with it,
9474 * just use the one for the printer. A NULL devicemode is not
9475 * a failure condition
9478 devmode
= print_job_devmode(mem_ctx
, lp_const_servicename(snum
), jobid
);
9480 result
= spoolss_create_default_devmode(mem_ctx
,
9481 pinfo2
->printername
,
9483 if (!W_ERROR_IS_OK(result
)) {
9484 DEBUG(3, ("Can't proceed w/o a devmode!"));
9489 return fill_job_info2(mem_ctx
,
9499 /****************************************************************
9501 ****************************************************************/
9503 WERROR
_spoolss_GetJob(struct pipes_struct
*p
,
9504 struct spoolss_GetJob
*r
)
9506 WERROR result
= WERR_OK
;
9507 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
9508 const char *svc_name
;
9512 struct tdb_print_db
*pdb
;
9513 print_queue_struct
*queue
= NULL
;
9514 print_status_struct prt_status
;
9516 /* that's an [in out] buffer */
9518 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9519 result
= WERR_INVALID_PARAM
;
9520 goto err_jinfo_free
;
9523 DEBUG(5,("_spoolss_GetJob\n"));
9527 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9528 result
= WERR_BADFID
;
9529 goto err_jinfo_free
;
9532 svc_name
= lp_const_servicename(snum
);
9533 if (svc_name
== NULL
) {
9534 result
= WERR_INVALID_PARAM
;
9535 goto err_jinfo_free
;
9538 result
= winreg_get_printer_internal(p
->mem_ctx
,
9539 get_session_info_system(),
9543 if (!W_ERROR_IS_OK(result
)) {
9544 goto err_jinfo_free
;
9547 pdb
= get_print_db_byname(svc_name
);
9549 DEBUG(3, ("failed to get print db for svc %s\n", svc_name
));
9550 result
= WERR_INVALID_PARAM
;
9551 goto err_pinfo_free
;
9554 sysjob
= jobid_to_sysjob_pdb(pdb
, r
->in
.job_id
);
9555 release_print_db(pdb
);
9557 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r
->in
.job_id
));
9558 result
= WERR_INVALID_PARAM
;
9559 goto err_pinfo_free
;
9562 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
9564 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9565 count
, prt_status
.status
, prt_status
.message
));
9567 switch (r
->in
.level
) {
9569 result
= getjob_level_1(p
->mem_ctx
,
9570 queue
, count
, snum
, pinfo2
,
9571 r
->in
.job_id
, sysjob
,
9572 &r
->out
.info
->info1
);
9575 result
= getjob_level_2(p
->mem_ctx
,
9576 queue
, count
, snum
, pinfo2
,
9577 r
->in
.job_id
, sysjob
,
9578 &r
->out
.info
->info2
);
9581 result
= WERR_UNKNOWN_LEVEL
;
9586 TALLOC_FREE(pinfo2
);
9588 if (!W_ERROR_IS_OK(result
)) {
9589 goto err_jinfo_free
;
9592 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, r
->out
.info
,
9594 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9596 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9599 TALLOC_FREE(pinfo2
);
9601 TALLOC_FREE(r
->out
.info
);
9605 /****************************************************************
9606 _spoolss_GetPrinterDataEx
9607 ****************************************************************/
9609 WERROR
_spoolss_GetPrinterDataEx(struct pipes_struct
*p
,
9610 struct spoolss_GetPrinterDataEx
*r
)
9613 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9614 const char *printer
;
9616 WERROR result
= WERR_OK
;
9618 enum winreg_Type val_type
= REG_NONE
;
9619 uint8_t *val_data
= NULL
;
9620 uint32_t val_size
= 0;
9621 struct dcerpc_binding_handle
*b
;
9622 TALLOC_CTX
*tmp_ctx
;
9624 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9626 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9627 r
->in
.key_name
, r
->in
.value_name
));
9629 /* in case of problem, return some default values */
9632 *r
->out
.type
= REG_NONE
;
9634 tmp_ctx
= talloc_new(p
->mem_ctx
);
9640 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9641 OUR_HANDLE(r
->in
.handle
)));
9642 result
= WERR_BADFID
;
9646 /* check to see if the keyname is valid */
9647 if (!strlen(r
->in
.key_name
)) {
9648 result
= WERR_INVALID_PARAM
;
9652 /* Is the handle to a printer or to the server? */
9654 if (Printer
->printer_type
== SPLHND_SERVER
) {
9656 union spoolss_PrinterData data
;
9658 result
= getprinterdata_printer_server(tmp_ctx
,
9662 if (!W_ERROR_IS_OK(result
)) {
9666 result
= push_spoolss_PrinterData(tmp_ctx
, &blob
,
9667 *r
->out
.type
, &data
);
9668 if (!W_ERROR_IS_OK(result
)) {
9672 *r
->out
.needed
= blob
.length
;
9674 if (r
->in
.offered
>= *r
->out
.needed
) {
9675 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
9682 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9683 result
= WERR_BADFID
;
9686 printer
= lp_const_servicename(snum
);
9688 result
= winreg_printer_binding_handle(tmp_ctx
,
9689 get_session_info_system(),
9692 if (!W_ERROR_IS_OK(result
)) {
9696 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9697 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
9698 strequal(r
->in
.value_name
, "ChangeId")) {
9699 *r
->out
.type
= REG_DWORD
;
9701 if (r
->in
.offered
>= *r
->out
.needed
) {
9702 uint32_t changeid
= 0;
9704 result
= winreg_printer_get_changeid(tmp_ctx
, b
,
9707 if (!W_ERROR_IS_OK(result
)) {
9711 SIVAL(r
->out
.data
, 0, changeid
);
9717 result
= winreg_get_printer_dataex(tmp_ctx
, b
,
9724 if (!W_ERROR_IS_OK(result
)) {
9728 *r
->out
.needed
= val_size
;
9729 *r
->out
.type
= val_type
;
9731 if (r
->in
.offered
>= *r
->out
.needed
) {
9732 memcpy(r
->out
.data
, val_data
, val_size
);
9736 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9738 if (W_ERROR_IS_OK(result
)) {
9739 result
= SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9742 talloc_free(tmp_ctx
);
9746 /****************************************************************
9747 _spoolss_SetPrinterDataEx
9748 ****************************************************************/
9750 WERROR
_spoolss_SetPrinterDataEx(struct pipes_struct
*p
,
9751 struct spoolss_SetPrinterDataEx
*r
)
9753 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
9755 WERROR result
= WERR_OK
;
9756 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9758 struct dcerpc_binding_handle
*b
;
9759 TALLOC_CTX
*tmp_ctx
;
9761 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9763 /* From MSDN documentation of SetPrinterDataEx: pass request to
9764 SetPrinterData if key is "PrinterDriverData" */
9767 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9768 OUR_HANDLE(r
->in
.handle
)));
9772 if (Printer
->printer_type
== SPLHND_SERVER
) {
9773 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9774 "Not implemented for server handles yet\n"));
9775 return WERR_INVALID_PARAM
;
9778 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9783 * Access check : NT returns "access denied" if you make a
9784 * SetPrinterData call without the necessary privildge.
9785 * we were originally returning OK if nothing changed
9786 * which made Win2k issue **a lot** of SetPrinterData
9787 * when connecting to a printer --jerry
9790 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9791 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9792 "change denied by handle access permissions\n"));
9793 return WERR_ACCESS_DENIED
;
9796 tmp_ctx
= talloc_new(p
->mem_ctx
);
9801 result
= winreg_printer_binding_handle(tmp_ctx
,
9802 get_session_info_system(),
9805 if (!W_ERROR_IS_OK(result
)) {
9809 result
= winreg_get_printer(tmp_ctx
, b
,
9810 lp_servicename(talloc_tos(), snum
),
9812 if (!W_ERROR_IS_OK(result
)) {
9816 /* check for OID in valuename */
9818 oid_string
= strchr(r
->in
.value_name
, ',');
9824 /* save the registry data */
9826 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
9834 if (W_ERROR_IS_OK(result
)) {
9835 /* save the OID if one was specified */
9837 char *str
= talloc_asprintf(tmp_ctx
, "%s\\%s",
9838 r
->in
.key_name
, SPOOL_OID_KEY
);
9840 result
= WERR_NOMEM
;
9845 * I'm not checking the status here on purpose. Don't know
9846 * if this is right, but I'm returning the status from the
9847 * previous set_printer_dataex() call. I have no idea if
9848 * this is right. --jerry
9850 winreg_set_printer_dataex(tmp_ctx
, b
,
9855 (uint8_t *) oid_string
,
9856 strlen(oid_string
) + 1);
9859 result
= winreg_printer_update_changeid(tmp_ctx
, b
,
9860 lp_const_servicename(snum
));
9865 talloc_free(tmp_ctx
);
9869 /****************************************************************
9870 _spoolss_DeletePrinterDataEx
9871 ****************************************************************/
9873 WERROR
_spoolss_DeletePrinterDataEx(struct pipes_struct
*p
,
9874 struct spoolss_DeletePrinterDataEx
*r
)
9876 const char *printer
;
9878 WERROR status
= WERR_OK
;
9879 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9881 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9884 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9885 "Invalid handle (%s:%u:%u).\n",
9886 OUR_HANDLE(r
->in
.handle
)));
9890 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9891 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9892 "printer properties change denied by handle\n"));
9893 return WERR_ACCESS_DENIED
;
9896 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
9900 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9903 printer
= lp_const_servicename(snum
);
9905 status
= winreg_delete_printer_dataex_internal(p
->mem_ctx
,
9906 get_session_info_system(),
9911 if (W_ERROR_IS_OK(status
)) {
9912 status
= winreg_printer_update_changeid_internal(p
->mem_ctx
,
9913 get_session_info_system(),
9921 /****************************************************************
9922 _spoolss_EnumPrinterKey
9923 ****************************************************************/
9925 WERROR
_spoolss_EnumPrinterKey(struct pipes_struct
*p
,
9926 struct spoolss_EnumPrinterKey
*r
)
9929 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9931 WERROR result
= WERR_BADFILE
;
9932 const char **array
= NULL
;
9935 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9938 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9939 OUR_HANDLE(r
->in
.handle
)));
9943 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9947 result
= winreg_enum_printer_key_internal(p
->mem_ctx
,
9948 get_session_info_system(),
9950 lp_const_servicename(snum
),
9954 if (!W_ERROR_IS_OK(result
)) {
9958 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
9959 result
= WERR_NOMEM
;
9963 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
9964 *r
->out
.needed
= blob
.length
;
9966 if (r
->in
.offered
< *r
->out
.needed
) {
9967 result
= WERR_MORE_DATA
;
9970 r
->out
.key_buffer
->string_array
= array
;
9974 if (!W_ERROR_IS_OK(result
)) {
9976 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
9984 /****************************************************************
9985 _spoolss_DeletePrinterKey
9986 ****************************************************************/
9988 WERROR
_spoolss_DeletePrinterKey(struct pipes_struct
*p
,
9989 struct spoolss_DeletePrinterKey
*r
)
9991 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9994 const char *printer
;
9995 struct dcerpc_binding_handle
*b
;
9996 TALLOC_CTX
*tmp_ctx
;
9998 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10001 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10002 OUR_HANDLE(r
->in
.handle
)));
10003 return WERR_BADFID
;
10006 /* if keyname == NULL, return error */
10007 if ( !r
->in
.key_name
)
10008 return WERR_INVALID_PARAM
;
10010 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
10011 return WERR_BADFID
;
10014 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
10015 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10016 "printer properties change denied by handle\n"));
10017 return WERR_ACCESS_DENIED
;
10020 printer
= lp_const_servicename(snum
);
10022 tmp_ctx
= talloc_new(p
->mem_ctx
);
10027 status
= winreg_printer_binding_handle(tmp_ctx
,
10028 get_session_info_system(),
10031 if (!W_ERROR_IS_OK(status
)) {
10035 /* delete the key and all subkeys */
10036 status
= winreg_delete_printer_key(tmp_ctx
, b
,
10039 if (W_ERROR_IS_OK(status
)) {
10040 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
10045 talloc_free(tmp_ctx
);
10049 /****************************************************************
10050 _spoolss_EnumPrinterDataEx
10051 ****************************************************************/
10053 WERROR
_spoolss_EnumPrinterDataEx(struct pipes_struct
*p
,
10054 struct spoolss_EnumPrinterDataEx
*r
)
10056 uint32_t count
= 0;
10057 struct spoolss_PrinterEnumValues
*info
= NULL
;
10058 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
10062 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10065 *r
->out
.needed
= 0;
10066 *r
->out
.info
= NULL
;
10069 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10070 OUR_HANDLE(r
->in
.handle
)));
10071 return WERR_BADFID
;
10075 * first check for a keyname of NULL or "". Win2k seems to send
10076 * this a lot and we should send back WERR_INVALID_PARAM
10077 * no need to spend time looking up the printer in this case.
10081 if (!strlen(r
->in
.key_name
)) {
10082 result
= WERR_INVALID_PARAM
;
10086 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
10087 return WERR_BADFID
;
10090 /* now look for a match on the key name */
10091 result
= winreg_enum_printer_dataex_internal(p
->mem_ctx
,
10092 get_session_info_system(),
10094 lp_const_servicename(snum
),
10098 if (!W_ERROR_IS_OK(result
)) {
10102 #if 0 /* FIXME - gd */
10103 /* housekeeping information in the reply */
10105 /* Fix from Martin Zielinski <mz@seh.de> - ensure
10106 * the hand marshalled container size is a multiple
10107 * of 4 bytes for RPC alignment.
10111 needed
+= 4-(needed
% 4);
10114 *r
->out
.count
= count
;
10115 *r
->out
.info
= info
;
10118 if (!W_ERROR_IS_OK(result
)) {
10122 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
10123 spoolss_EnumPrinterDataEx
,
10126 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
10127 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
10129 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
10132 /****************************************************************************
10133 ****************************************************************************/
10135 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
10136 const char *servername
,
10137 const char *environment
,
10138 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
10143 werr
= compose_spoolss_server_path(mem_ctx
,
10146 SPOOLSS_PRTPROCS_PATH
,
10148 if (!W_ERROR_IS_OK(werr
)) {
10152 DEBUG(4,("print processor directory: [%s]\n", path
));
10154 r
->directory_name
= path
;
10159 /****************************************************************
10160 _spoolss_GetPrintProcessorDirectory
10161 ****************************************************************/
10163 WERROR
_spoolss_GetPrintProcessorDirectory(struct pipes_struct
*p
,
10164 struct spoolss_GetPrintProcessorDirectory
*r
)
10167 char *prnproc_share
= NULL
;
10168 bool prnproc_share_exists
= false;
10171 /* that's an [in out] buffer */
10173 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
10174 result
= WERR_INVALID_PARAM
;
10175 goto err_info_free
;
10178 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10181 *r
->out
.needed
= 0;
10183 /* r->in.level is ignored */
10185 /* We always should reply with a local print processor directory so that
10186 * users are not forced to have a [prnproc$] share on the Samba spoolss
10187 * server, if users decide to do so, lets announce it though - Guenther */
10189 snum
= find_service(talloc_tos(), "prnproc$", &prnproc_share
);
10190 if (!prnproc_share
) {
10191 result
= WERR_NOMEM
;
10192 goto err_info_free
;
10195 prnproc_share_exists
= true;
10198 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
10199 prnproc_share_exists
? r
->in
.server
: NULL
,
10201 &r
->out
.info
->info1
);
10202 if (!W_ERROR_IS_OK(result
)) {
10203 goto err_info_free
;
10206 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
,
10207 r
->out
.info
, r
->in
.level
);
10208 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
10210 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
10213 TALLOC_FREE(r
->out
.info
);
10217 /*******************************************************************
10218 ********************************************************************/
10220 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
10221 const char *dllname
)
10223 enum ndr_err_code ndr_err
;
10224 struct spoolss_MonitorUi ui
;
10226 ui
.dll_name
= dllname
;
10228 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, &ui
,
10229 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
10230 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
10231 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
10233 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
10236 /*******************************************************************
10237 Streams the monitor UI DLL name in UNICODE
10238 *******************************************************************/
10240 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
10241 struct security_token
*token
, DATA_BLOB
*in
,
10242 DATA_BLOB
*out
, uint32_t *needed
)
10244 const char *dllname
= "tcpmonui.dll";
10246 *needed
= (strlen(dllname
)+1) * 2;
10248 if (out
->length
< *needed
) {
10249 return WERR_INSUFFICIENT_BUFFER
;
10252 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
10259 /*******************************************************************
10260 ********************************************************************/
10262 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
10263 struct spoolss_PortData1
*port1
,
10264 const DATA_BLOB
*buf
)
10266 enum ndr_err_code ndr_err
;
10267 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port1
,
10268 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
10269 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
10270 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
10272 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
10275 /*******************************************************************
10276 ********************************************************************/
10278 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
10279 struct spoolss_PortData2
*port2
,
10280 const DATA_BLOB
*buf
)
10282 enum ndr_err_code ndr_err
;
10283 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port2
,
10284 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
10285 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
10286 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
10288 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
10291 /*******************************************************************
10292 Create a new TCP/IP port
10293 *******************************************************************/
10295 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
10296 struct security_token
*token
, DATA_BLOB
*in
,
10297 DATA_BLOB
*out
, uint32_t *needed
)
10299 struct spoolss_PortData1 port1
;
10300 struct spoolss_PortData2 port2
;
10301 char *device_uri
= NULL
;
10304 const char *portname
;
10305 const char *hostaddress
;
10307 uint32_t port_number
;
10310 /* peek for spoolss_PortData version */
10312 if (!in
|| (in
->length
< (128 + 4))) {
10313 return WERR_GENERAL_FAILURE
;
10316 version
= IVAL(in
->data
, 128);
10320 ZERO_STRUCT(port1
);
10322 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
10326 portname
= port1
.portname
;
10327 hostaddress
= port1
.hostaddress
;
10328 queue
= port1
.queue
;
10329 protocol
= port1
.protocol
;
10330 port_number
= port1
.port_number
;
10334 ZERO_STRUCT(port2
);
10336 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
10340 portname
= port2
.portname
;
10341 hostaddress
= port2
.hostaddress
;
10342 queue
= port2
.queue
;
10343 protocol
= port2
.protocol
;
10344 port_number
= port2
.port_number
;
10348 DEBUG(1,("xcvtcp_addport: "
10349 "unknown version of port_data: %d\n", version
));
10350 return WERR_UNKNOWN_PORT
;
10353 /* create the device URI and call the add_port_hook() */
10355 switch (protocol
) {
10356 case PROTOCOL_RAWTCP_TYPE
:
10357 device_uri
= talloc_asprintf(mem_ctx
,
10358 "socket://%s:%d/", hostaddress
,
10362 case PROTOCOL_LPR_TYPE
:
10363 device_uri
= talloc_asprintf(mem_ctx
,
10364 "lpr://%s/%s", hostaddress
, queue
);
10368 return WERR_UNKNOWN_PORT
;
10375 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
10378 /*******************************************************************
10379 *******************************************************************/
10381 struct xcv_api_table xcvtcp_cmds
[] = {
10382 { "MonitorUI", xcvtcp_monitorui
},
10383 { "AddPort", xcvtcp_addport
},
10387 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
10388 struct security_token
*token
, const char *command
,
10395 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
10397 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
10398 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
10399 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
10402 return WERR_BADFUNC
;
10405 /*******************************************************************
10406 *******************************************************************/
10407 #if 0 /* don't support management using the "Local Port" monitor */
10409 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
10410 struct security_token
*token
, DATA_BLOB
*in
,
10411 DATA_BLOB
*out
, uint32_t *needed
)
10413 const char *dllname
= "localui.dll";
10415 *needed
= (strlen(dllname
)+1) * 2;
10417 if (out
->length
< *needed
) {
10418 return WERR_INSUFFICIENT_BUFFER
;
10421 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
10428 /*******************************************************************
10429 *******************************************************************/
10431 struct xcv_api_table xcvlocal_cmds
[] = {
10432 { "MonitorUI", xcvlocal_monitorui
},
10436 struct xcv_api_table xcvlocal_cmds
[] = {
10443 /*******************************************************************
10444 *******************************************************************/
10446 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
10447 struct security_token
*token
, const char *command
,
10448 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
10453 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
10455 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
10456 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
10457 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
10459 return WERR_BADFUNC
;
10462 /****************************************************************
10464 ****************************************************************/
10466 WERROR
_spoolss_XcvData(struct pipes_struct
*p
,
10467 struct spoolss_XcvData
*r
)
10469 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
10470 DATA_BLOB out_data
= data_blob_null
;
10474 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10475 OUR_HANDLE(r
->in
.handle
)));
10476 return WERR_BADFID
;
10479 /* Has to be a handle to the TCP/IP port monitor */
10481 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
10482 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10483 return WERR_BADFID
;
10486 /* requires administrative access to the server */
10488 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
10489 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10490 return WERR_ACCESS_DENIED
;
10493 /* Allocate the outgoing buffer */
10495 if (r
->in
.out_data_size
) {
10496 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
10497 if (out_data
.data
== NULL
) {
10502 switch ( Printer
->printer_type
) {
10503 case SPLHND_PORTMON_TCP
:
10504 werror
= process_xcvtcp_command(p
->mem_ctx
,
10505 p
->session_info
->security_token
,
10506 r
->in
.function_name
,
10507 &r
->in
.in_data
, &out_data
,
10510 case SPLHND_PORTMON_LOCAL
:
10511 werror
= process_xcvlocal_command(p
->mem_ctx
,
10512 p
->session_info
->security_token
,
10513 r
->in
.function_name
,
10514 &r
->in
.in_data
, &out_data
,
10518 werror
= WERR_INVALID_PRINT_MONITOR
;
10521 if (!W_ERROR_IS_OK(werror
)) {
10525 *r
->out
.status_code
= 0;
10527 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
10528 memcpy(r
->out
.out_data
, out_data
.data
,
10529 MIN(r
->in
.out_data_size
, out_data
.length
));
10535 /****************************************************************
10536 _spoolss_AddPrintProcessor
10537 ****************************************************************/
10539 WERROR
_spoolss_AddPrintProcessor(struct pipes_struct
*p
,
10540 struct spoolss_AddPrintProcessor
*r
)
10542 /* for now, just indicate success and ignore the add. We'll
10543 automatically set the winprint processor for printer
10544 entries later. Used to debug the LexMark Optra S 1855 PCL
10550 /****************************************************************
10552 ****************************************************************/
10554 WERROR
_spoolss_AddPort(struct pipes_struct
*p
,
10555 struct spoolss_AddPort
*r
)
10557 /* do what w2k3 does */
10559 return WERR_NOT_SUPPORTED
;
10562 /****************************************************************
10563 _spoolss_GetPrinterDriver
10564 ****************************************************************/
10566 WERROR
_spoolss_GetPrinterDriver(struct pipes_struct
*p
,
10567 struct spoolss_GetPrinterDriver
*r
)
10569 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10570 return WERR_NOT_SUPPORTED
;
10573 /****************************************************************
10574 _spoolss_ReadPrinter
10575 ****************************************************************/
10577 WERROR
_spoolss_ReadPrinter(struct pipes_struct
*p
,
10578 struct spoolss_ReadPrinter
*r
)
10580 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10581 return WERR_NOT_SUPPORTED
;
10584 /****************************************************************
10585 _spoolss_WaitForPrinterChange
10586 ****************************************************************/
10588 WERROR
_spoolss_WaitForPrinterChange(struct pipes_struct
*p
,
10589 struct spoolss_WaitForPrinterChange
*r
)
10591 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10592 return WERR_NOT_SUPPORTED
;
10595 /****************************************************************
10596 _spoolss_ConfigurePort
10597 ****************************************************************/
10599 WERROR
_spoolss_ConfigurePort(struct pipes_struct
*p
,
10600 struct spoolss_ConfigurePort
*r
)
10602 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10603 return WERR_NOT_SUPPORTED
;
10606 /****************************************************************
10607 _spoolss_DeletePort
10608 ****************************************************************/
10610 WERROR
_spoolss_DeletePort(struct pipes_struct
*p
,
10611 struct spoolss_DeletePort
*r
)
10613 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10614 return WERR_NOT_SUPPORTED
;
10617 /****************************************************************
10618 _spoolss_CreatePrinterIC
10619 ****************************************************************/
10621 WERROR
_spoolss_CreatePrinterIC(struct pipes_struct
*p
,
10622 struct spoolss_CreatePrinterIC
*r
)
10624 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10625 return WERR_NOT_SUPPORTED
;
10628 /****************************************************************
10629 _spoolss_PlayGDIScriptOnPrinterIC
10630 ****************************************************************/
10632 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct
*p
,
10633 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
10635 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10636 return WERR_NOT_SUPPORTED
;
10639 /****************************************************************
10640 _spoolss_DeletePrinterIC
10641 ****************************************************************/
10643 WERROR
_spoolss_DeletePrinterIC(struct pipes_struct
*p
,
10644 struct spoolss_DeletePrinterIC
*r
)
10646 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10647 return WERR_NOT_SUPPORTED
;
10650 /****************************************************************
10651 _spoolss_AddPrinterConnection
10652 ****************************************************************/
10654 WERROR
_spoolss_AddPrinterConnection(struct pipes_struct
*p
,
10655 struct spoolss_AddPrinterConnection
*r
)
10657 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10658 return WERR_NOT_SUPPORTED
;
10661 /****************************************************************
10662 _spoolss_DeletePrinterConnection
10663 ****************************************************************/
10665 WERROR
_spoolss_DeletePrinterConnection(struct pipes_struct
*p
,
10666 struct spoolss_DeletePrinterConnection
*r
)
10668 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10669 return WERR_NOT_SUPPORTED
;
10672 /****************************************************************
10673 _spoolss_PrinterMessageBox
10674 ****************************************************************/
10676 WERROR
_spoolss_PrinterMessageBox(struct pipes_struct
*p
,
10677 struct spoolss_PrinterMessageBox
*r
)
10679 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10680 return WERR_NOT_SUPPORTED
;
10683 /****************************************************************
10684 _spoolss_AddMonitor
10685 ****************************************************************/
10687 WERROR
_spoolss_AddMonitor(struct pipes_struct
*p
,
10688 struct spoolss_AddMonitor
*r
)
10690 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10691 return WERR_NOT_SUPPORTED
;
10694 /****************************************************************
10695 _spoolss_DeleteMonitor
10696 ****************************************************************/
10698 WERROR
_spoolss_DeleteMonitor(struct pipes_struct
*p
,
10699 struct spoolss_DeleteMonitor
*r
)
10701 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10702 return WERR_NOT_SUPPORTED
;
10705 /****************************************************************
10706 _spoolss_DeletePrintProcessor
10707 ****************************************************************/
10709 WERROR
_spoolss_DeletePrintProcessor(struct pipes_struct
*p
,
10710 struct spoolss_DeletePrintProcessor
*r
)
10712 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10713 return WERR_NOT_SUPPORTED
;
10716 /****************************************************************
10717 _spoolss_AddPrintProvidor
10718 ****************************************************************/
10720 WERROR
_spoolss_AddPrintProvidor(struct pipes_struct
*p
,
10721 struct spoolss_AddPrintProvidor
*r
)
10723 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10724 return WERR_NOT_SUPPORTED
;
10727 /****************************************************************
10728 _spoolss_DeletePrintProvidor
10729 ****************************************************************/
10731 WERROR
_spoolss_DeletePrintProvidor(struct pipes_struct
*p
,
10732 struct spoolss_DeletePrintProvidor
*r
)
10734 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10735 return WERR_NOT_SUPPORTED
;
10738 /****************************************************************
10739 _spoolss_FindFirstPrinterChangeNotification
10740 ****************************************************************/
10742 WERROR
_spoolss_FindFirstPrinterChangeNotification(struct pipes_struct
*p
,
10743 struct spoolss_FindFirstPrinterChangeNotification
*r
)
10745 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10746 return WERR_NOT_SUPPORTED
;
10749 /****************************************************************
10750 _spoolss_FindNextPrinterChangeNotification
10751 ****************************************************************/
10753 WERROR
_spoolss_FindNextPrinterChangeNotification(struct pipes_struct
*p
,
10754 struct spoolss_FindNextPrinterChangeNotification
*r
)
10756 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10757 return WERR_NOT_SUPPORTED
;
10760 /****************************************************************
10761 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10762 ****************************************************************/
10764 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct
*p
,
10765 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
10767 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10768 return WERR_NOT_SUPPORTED
;
10771 /****************************************************************
10772 _spoolss_ReplyOpenPrinter
10773 ****************************************************************/
10775 WERROR
_spoolss_ReplyOpenPrinter(struct pipes_struct
*p
,
10776 struct spoolss_ReplyOpenPrinter
*r
)
10778 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10779 return WERR_NOT_SUPPORTED
;
10782 /****************************************************************
10783 _spoolss_RouterReplyPrinter
10784 ****************************************************************/
10786 WERROR
_spoolss_RouterReplyPrinter(struct pipes_struct
*p
,
10787 struct spoolss_RouterReplyPrinter
*r
)
10789 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10790 return WERR_NOT_SUPPORTED
;
10793 /****************************************************************
10794 _spoolss_ReplyClosePrinter
10795 ****************************************************************/
10797 WERROR
_spoolss_ReplyClosePrinter(struct pipes_struct
*p
,
10798 struct spoolss_ReplyClosePrinter
*r
)
10800 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10801 return WERR_NOT_SUPPORTED
;
10804 /****************************************************************
10806 ****************************************************************/
10808 WERROR
_spoolss_AddPortEx(struct pipes_struct
*p
,
10809 struct spoolss_AddPortEx
*r
)
10811 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10812 return WERR_NOT_SUPPORTED
;
10815 /****************************************************************
10816 _spoolss_RouterFindFirstPrinterChangeNotification
10817 ****************************************************************/
10819 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct
*p
,
10820 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
10822 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10823 return WERR_NOT_SUPPORTED
;
10826 /****************************************************************
10827 _spoolss_SpoolerInit
10828 ****************************************************************/
10830 WERROR
_spoolss_SpoolerInit(struct pipes_struct
*p
,
10831 struct spoolss_SpoolerInit
*r
)
10833 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10834 return WERR_NOT_SUPPORTED
;
10837 /****************************************************************
10838 _spoolss_ResetPrinterEx
10839 ****************************************************************/
10841 WERROR
_spoolss_ResetPrinterEx(struct pipes_struct
*p
,
10842 struct spoolss_ResetPrinterEx
*r
)
10844 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10845 return WERR_NOT_SUPPORTED
;
10848 /****************************************************************
10849 _spoolss_RouterReplyPrinterEx
10850 ****************************************************************/
10852 WERROR
_spoolss_RouterReplyPrinterEx(struct pipes_struct
*p
,
10853 struct spoolss_RouterReplyPrinterEx
*r
)
10855 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10856 return WERR_NOT_SUPPORTED
;
10859 /****************************************************************
10861 ****************************************************************/
10863 WERROR
_spoolss_44(struct pipes_struct
*p
,
10864 struct spoolss_44
*r
)
10866 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10867 return WERR_NOT_SUPPORTED
;
10870 /****************************************************************
10872 ****************************************************************/
10874 WERROR
_spoolss_SetPort(struct pipes_struct
*p
,
10875 struct spoolss_SetPort
*r
)
10877 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10878 return WERR_NOT_SUPPORTED
;
10881 /****************************************************************
10883 ****************************************************************/
10885 WERROR
_spoolss_4a(struct pipes_struct
*p
,
10886 struct spoolss_4a
*r
)
10888 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10889 return WERR_NOT_SUPPORTED
;
10892 /****************************************************************
10894 ****************************************************************/
10896 WERROR
_spoolss_4b(struct pipes_struct
*p
,
10897 struct spoolss_4b
*r
)
10899 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10900 return WERR_NOT_SUPPORTED
;
10903 /****************************************************************
10905 ****************************************************************/
10907 WERROR
_spoolss_4c(struct pipes_struct
*p
,
10908 struct spoolss_4c
*r
)
10910 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10911 return WERR_NOT_SUPPORTED
;
10914 /****************************************************************
10916 ****************************************************************/
10918 WERROR
_spoolss_53(struct pipes_struct
*p
,
10919 struct spoolss_53
*r
)
10921 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10922 return WERR_NOT_SUPPORTED
;
10925 /****************************************************************
10926 _spoolss_AddPerMachineConnection
10927 ****************************************************************/
10929 WERROR
_spoolss_AddPerMachineConnection(struct pipes_struct
*p
,
10930 struct spoolss_AddPerMachineConnection
*r
)
10932 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10933 return WERR_NOT_SUPPORTED
;
10936 /****************************************************************
10937 _spoolss_DeletePerMachineConnection
10938 ****************************************************************/
10940 WERROR
_spoolss_DeletePerMachineConnection(struct pipes_struct
*p
,
10941 struct spoolss_DeletePerMachineConnection
*r
)
10943 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10944 return WERR_NOT_SUPPORTED
;
10947 /****************************************************************
10948 _spoolss_EnumPerMachineConnections
10949 ****************************************************************/
10951 WERROR
_spoolss_EnumPerMachineConnections(struct pipes_struct
*p
,
10952 struct spoolss_EnumPerMachineConnections
*r
)
10954 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10955 return WERR_NOT_SUPPORTED
;
10958 /****************************************************************
10960 ****************************************************************/
10962 WERROR
_spoolss_5a(struct pipes_struct
*p
,
10963 struct spoolss_5a
*r
)
10965 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10966 return WERR_NOT_SUPPORTED
;
10969 /****************************************************************
10971 ****************************************************************/
10973 WERROR
_spoolss_5b(struct pipes_struct
*p
,
10974 struct spoolss_5b
*r
)
10976 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10977 return WERR_NOT_SUPPORTED
;
10980 /****************************************************************
10982 ****************************************************************/
10984 WERROR
_spoolss_5c(struct pipes_struct
*p
,
10985 struct spoolss_5c
*r
)
10987 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10988 return WERR_NOT_SUPPORTED
;
10991 /****************************************************************
10993 ****************************************************************/
10995 WERROR
_spoolss_5d(struct pipes_struct
*p
,
10996 struct spoolss_5d
*r
)
10998 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10999 return WERR_NOT_SUPPORTED
;
11002 /****************************************************************
11004 ****************************************************************/
11006 WERROR
_spoolss_5e(struct pipes_struct
*p
,
11007 struct spoolss_5e
*r
)
11009 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11010 return WERR_NOT_SUPPORTED
;
11013 /****************************************************************
11015 ****************************************************************/
11017 WERROR
_spoolss_5f(struct pipes_struct
*p
,
11018 struct spoolss_5f
*r
)
11020 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11021 return WERR_NOT_SUPPORTED
;
11024 /****************************************************************
11026 ****************************************************************/
11028 WERROR
_spoolss_60(struct pipes_struct
*p
,
11029 struct spoolss_60
*r
)
11031 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11032 return WERR_NOT_SUPPORTED
;
11035 /****************************************************************
11036 _spoolss_RpcSendRecvBidiData
11037 ****************************************************************/
11039 WERROR
_spoolss_RpcSendRecvBidiData(struct pipes_struct
*p
,
11040 struct spoolss_RpcSendRecvBidiData
*r
)
11042 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11043 return WERR_NOT_SUPPORTED
;
11046 /****************************************************************
11048 ****************************************************************/
11050 WERROR
_spoolss_62(struct pipes_struct
*p
,
11051 struct spoolss_62
*r
)
11053 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11054 return WERR_NOT_SUPPORTED
;
11057 /****************************************************************
11059 ****************************************************************/
11061 WERROR
_spoolss_63(struct pipes_struct
*p
,
11062 struct spoolss_63
*r
)
11064 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11065 return WERR_NOT_SUPPORTED
;
11068 /****************************************************************
11070 ****************************************************************/
11072 WERROR
_spoolss_64(struct pipes_struct
*p
,
11073 struct spoolss_64
*r
)
11075 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11076 return WERR_NOT_SUPPORTED
;
11079 /****************************************************************
11081 ****************************************************************/
11083 WERROR
_spoolss_65(struct pipes_struct
*p
,
11084 struct spoolss_65
*r
)
11086 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11087 return WERR_NOT_SUPPORTED
;
11090 /****************************************************************
11091 _spoolss_GetCorePrinterDrivers
11092 ****************************************************************/
11094 WERROR
_spoolss_GetCorePrinterDrivers(struct pipes_struct
*p
,
11095 struct spoolss_GetCorePrinterDrivers
*r
)
11097 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11098 return WERR_NOT_SUPPORTED
;
11101 /****************************************************************
11103 ****************************************************************/
11105 WERROR
_spoolss_67(struct pipes_struct
*p
,
11106 struct spoolss_67
*r
)
11108 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11109 return WERR_NOT_SUPPORTED
;
11112 /****************************************************************
11113 _spoolss_GetPrinterDriverPackagePath
11114 ****************************************************************/
11116 WERROR
_spoolss_GetPrinterDriverPackagePath(struct pipes_struct
*p
,
11117 struct spoolss_GetPrinterDriverPackagePath
*r
)
11119 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11120 return WERR_NOT_SUPPORTED
;
11123 /****************************************************************
11125 ****************************************************************/
11127 WERROR
_spoolss_69(struct pipes_struct
*p
,
11128 struct spoolss_69
*r
)
11130 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11131 return WERR_NOT_SUPPORTED
;
11134 /****************************************************************
11136 ****************************************************************/
11138 WERROR
_spoolss_6a(struct pipes_struct
*p
,
11139 struct spoolss_6a
*r
)
11141 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11142 return WERR_NOT_SUPPORTED
;
11145 /****************************************************************
11147 ****************************************************************/
11149 WERROR
_spoolss_6b(struct pipes_struct
*p
,
11150 struct spoolss_6b
*r
)
11152 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11153 return WERR_NOT_SUPPORTED
;
11156 /****************************************************************
11158 ****************************************************************/
11160 WERROR
_spoolss_6c(struct pipes_struct
*p
,
11161 struct spoolss_6c
*r
)
11163 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11164 return WERR_NOT_SUPPORTED
;
11167 /****************************************************************
11169 ****************************************************************/
11171 WERROR
_spoolss_6d(struct pipes_struct
*p
,
11172 struct spoolss_6d
*r
)
11174 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11175 return WERR_NOT_SUPPORTED
;
11178 /****************************************************************
11179 _spoolss_RpcGetJobNamedPropertyValue
11180 ****************************************************************/
11182 WERROR
_spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct
*p
,
11183 struct spoolss_RpcGetJobNamedPropertyValue
*r
)
11185 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11186 return WERR_NOT_SUPPORTED
;
11189 /****************************************************************
11190 _spoolss_RpcSetJobNamedProperty
11191 ****************************************************************/
11193 WERROR
_spoolss_RpcSetJobNamedProperty(struct pipes_struct
*p
,
11194 struct spoolss_RpcSetJobNamedProperty
*r
)
11196 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11197 return WERR_NOT_SUPPORTED
;
11200 /****************************************************************
11201 _spoolss_RpcDeleteJobNamedProperty
11202 ****************************************************************/
11204 WERROR
_spoolss_RpcDeleteJobNamedProperty(struct pipes_struct
*p
,
11205 struct spoolss_RpcDeleteJobNamedProperty
*r
)
11207 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11208 return WERR_NOT_SUPPORTED
;
11211 /****************************************************************
11212 _spoolss_RpcEnumJobNamedProperties
11213 ****************************************************************/
11215 WERROR
_spoolss_RpcEnumJobNamedProperties(struct pipes_struct
*p
,
11216 struct spoolss_RpcEnumJobNamedProperties
*r
)
11218 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11219 return WERR_NOT_SUPPORTED
;