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 struct cli_state
*cli
;
142 uint32_t active_connections
;
145 static struct notify_back_channel
*back_channels
;
147 /* Map generic permissions to printer object specific permissions */
149 const struct standard_mapping printer_std_mapping
= {
156 /* Map generic permissions to print server object specific permissions */
158 const struct standard_mapping printserver_std_mapping
= {
165 /* API table for Xcv Monitor functions */
167 struct xcv_api_table
{
169 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, struct security_token
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
172 static void prune_printername_cache(void);
174 /********************************************************************
175 * Canonicalize servername.
176 ********************************************************************/
178 static const char *canon_servername(const char *servername
)
180 const char *pservername
= servername
;
181 while (*pservername
== '\\') {
187 /* translate between internal status numbers and NT status numbers */
188 static int nt_printj_status(int v
)
194 return JOB_STATUS_PAUSED
;
196 return JOB_STATUS_SPOOLING
;
198 return JOB_STATUS_PRINTING
;
200 return JOB_STATUS_ERROR
;
202 return JOB_STATUS_DELETING
;
204 return JOB_STATUS_OFFLINE
;
206 return JOB_STATUS_PAPEROUT
;
208 return JOB_STATUS_PRINTED
;
210 return JOB_STATUS_DELETED
;
212 return JOB_STATUS_BLOCKED_DEVQ
;
213 case LPQ_USER_INTERVENTION
:
214 return JOB_STATUS_USER_INTERVENTION
;
219 static int nt_printq_status(int v
)
223 return PRINTER_STATUS_PAUSED
;
232 /***************************************************************************
233 Disconnect from the client
234 ****************************************************************************/
236 static void srv_spoolss_replycloseprinter(int snum
,
237 struct printer_handle
*prn_hnd
)
243 * Tell the specific printing tdb we no longer want messages for this printer
244 * by deregistering our PID.
247 if (!print_notify_deregister_pid(snum
)) {
248 DEBUG(0, ("Failed to register our pid for printer %s\n",
249 lp_const_servicename(snum
)));
252 /* weird if the test succeeds !!! */
253 if (prn_hnd
->notify
.cli_chan
== NULL
||
254 prn_hnd
->notify
.cli_chan
->cli_pipe
== NULL
||
255 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
== NULL
||
256 prn_hnd
->notify
.cli_chan
->active_connections
== 0) {
257 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
258 DLIST_REMOVE(back_channels
, prn_hnd
->notify
.cli_chan
);
259 TALLOC_FREE(prn_hnd
->notify
.cli_chan
);
263 status
= dcerpc_spoolss_ReplyClosePrinter(
264 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
,
266 &prn_hnd
->notify
.cli_hnd
,
268 if (!NT_STATUS_IS_OK(status
)) {
269 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
271 result
= ntstatus_to_werror(status
);
272 } else if (!W_ERROR_IS_OK(result
)) {
273 DEBUG(0, ("reply_close_printer failed [%s].\n",
274 win_errstr(result
)));
277 /* if it's the last connection, deconnect the IPC$ share */
278 if (prn_hnd
->notify
.cli_chan
->active_connections
== 1) {
280 cli_shutdown(prn_hnd
->notify
.cli_chan
->cli
);
281 DLIST_REMOVE(back_channels
, prn_hnd
->notify
.cli_chan
);
282 TALLOC_FREE(prn_hnd
->notify
.cli_chan
);
284 if (prn_hnd
->notify
.msg_ctx
!= NULL
) {
285 messaging_deregister(prn_hnd
->notify
.msg_ctx
,
286 MSG_PRINTER_NOTIFY2
, NULL
);
290 if (prn_hnd
->notify
.cli_chan
) {
291 prn_hnd
->notify
.cli_chan
->active_connections
--;
292 prn_hnd
->notify
.cli_chan
= NULL
;
296 /****************************************************************************
297 Functions to free a printer entry datastruct.
298 ****************************************************************************/
300 static int printer_entry_destructor(struct printer_handle
*Printer
)
302 if (Printer
->notify
.cli_chan
!= NULL
&&
303 Printer
->notify
.cli_chan
->active_connections
> 0) {
306 switch(Printer
->printer_type
) {
308 srv_spoolss_replycloseprinter(snum
, Printer
);
312 snum
= print_queue_snum(Printer
->sharename
);
314 srv_spoolss_replycloseprinter(snum
, Printer
);
322 Printer
->notify
.flags
=0;
323 Printer
->notify
.options
=0;
324 Printer
->notify
.localmachine
[0]='\0';
325 Printer
->notify
.printerlocal
=0;
326 TALLOC_FREE(Printer
->notify
.option
);
327 TALLOC_FREE(Printer
->devmode
);
329 /* Remove from the internal list. */
330 DLIST_REMOVE(printers_list
, Printer
);
334 /****************************************************************************
335 find printer index by handle
336 ****************************************************************************/
338 static struct printer_handle
*find_printer_index_by_hnd(struct pipes_struct
*p
,
339 struct policy_handle
*hnd
)
341 struct printer_handle
*find_printer
= NULL
;
343 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
344 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
351 /****************************************************************************
352 Close printer index by handle.
353 ****************************************************************************/
355 static bool close_printer_handle(struct pipes_struct
*p
, struct policy_handle
*hnd
)
357 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
360 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
365 close_policy_hnd(p
, hnd
);
370 /****************************************************************************
371 Delete a printer given a handle.
372 ****************************************************************************/
374 static WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, struct security_token
*token
,
375 const char *sharename
,
376 struct messaging_context
*msg_ctx
)
378 char *cmd
= lp_deleteprinter_command(talloc_tos());
379 char *command
= NULL
;
381 bool is_print_op
= false;
383 /* can't fail if we don't try */
388 command
= talloc_asprintf(ctx
,
395 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
397 DEBUG(10,("Running [%s]\n", command
));
399 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
404 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
405 /* Tell everyone we updated smb.conf. */
406 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
412 /********** END SePrintOperatorPrivlege BLOCK **********/
414 DEBUGADD(10,("returned [%d]\n", ret
));
416 TALLOC_FREE(command
);
419 return WERR_BADFID
; /* What to return here? */
424 /****************************************************************************
425 Delete a printer given a handle.
426 ****************************************************************************/
428 static WERROR
delete_printer_handle(struct pipes_struct
*p
, struct policy_handle
*hnd
)
430 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
434 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
440 * It turns out that Windows allows delete printer on a handle
441 * opened by an admin user, then used on a pipe handle created
442 * by an anonymous user..... but they're working on security.... riiight !
446 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
447 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
448 return WERR_ACCESS_DENIED
;
451 /* this does not need a become root since the access check has been
452 done on the handle already */
454 result
= winreg_delete_printer_key_internal(p
->mem_ctx
,
455 get_session_info_system(),
459 if (!W_ERROR_IS_OK(result
)) {
460 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
464 result
= delete_printer_hook(p
->mem_ctx
, p
->session_info
->security_token
,
465 Printer
->sharename
, p
->msg_ctx
);
466 if (!W_ERROR_IS_OK(result
)) {
469 prune_printername_cache();
473 /****************************************************************************
474 Return the snum of a printer corresponding to an handle.
475 ****************************************************************************/
477 static bool get_printer_snum(struct pipes_struct
*p
, struct policy_handle
*hnd
,
478 int *number
, struct share_params
**params
)
480 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
483 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
488 switch (Printer
->printer_type
) {
490 DEBUG(4,("short name:%s\n", Printer
->sharename
));
491 *number
= print_queue_snum(Printer
->sharename
);
492 return (*number
!= -1);
500 /****************************************************************************
501 Set printer handle type.
502 Check if it's \\server or \\server\printer
503 ****************************************************************************/
505 static bool set_printer_hnd_printertype(struct printer_handle
*Printer
, const char *handlename
)
507 DEBUG(3,("Setting printer type=%s\n", handlename
));
509 /* it's a print server */
510 if (handlename
&& *handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
511 DEBUGADD(4,("Printer is a print server\n"));
512 Printer
->printer_type
= SPLHND_SERVER
;
514 /* it's a printer (set_printer_hnd_name() will handle port monitors */
516 DEBUGADD(4,("Printer is a printer\n"));
517 Printer
->printer_type
= SPLHND_PRINTER
;
523 static void prune_printername_cache_fn(const char *key
, const char *value
,
524 time_t timeout
, void *private_data
)
529 static void prune_printername_cache(void)
531 gencache_iterate(prune_printername_cache_fn
, NULL
, "PRINTERNAME/*");
534 /****************************************************************************
535 Set printer handle name.. Accept names like \\server, \\server\printer,
536 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
537 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
538 XcvDataPort() interface.
539 ****************************************************************************/
541 static WERROR
set_printer_hnd_name(TALLOC_CTX
*mem_ctx
,
542 const struct auth_session_info
*session_info
,
543 struct messaging_context
*msg_ctx
,
544 struct printer_handle
*Printer
,
545 const char *handlename
)
548 int n_services
=lp_numservices();
550 const char *printername
;
551 const char *servername
= NULL
;
554 struct spoolss_PrinterInfo2
*info2
= NULL
;
559 * Hopefully nobody names his printers like this. Maybe \ or ,
560 * are illegal in printer names even?
562 const char printer_not_found
[] = "Printer \\, !@#$%^&*( not found";
566 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
,
567 (unsigned long)strlen(handlename
)));
569 aprinter
= discard_const_p(char, handlename
);
570 if ( *handlename
== '\\' ) {
571 servername
= canon_servername(handlename
);
572 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
576 if (!is_myname_or_ipaddr(servername
)) {
577 return WERR_INVALID_PRINTER_NAME
;
579 Printer
->servername
= talloc_asprintf(Printer
, "\\\\%s", servername
);
580 if (Printer
->servername
== NULL
) {
585 if (Printer
->printer_type
== SPLHND_SERVER
) {
589 if (Printer
->printer_type
!= SPLHND_PRINTER
) {
590 return WERR_INVALID_HANDLE
;
593 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
595 p
= strchr(aprinter
, ',');
602 if (strncmp(p
, "DrvConvert", strlen("DrvConvert")) == 0) {
604 } else if (strncmp(p
, "LocalOnly", strlen("LocalOnly")) == 0) {
610 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter
));
613 /* check for the Port Monitor Interface */
614 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
615 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
616 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
619 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
620 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
621 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
626 * With hundreds of printers, the "for" loop iterating all
627 * shares can be quite expensive, as it is done on every
628 * OpenPrinter. The loop maps "aprinter" to "sname", the
629 * result of which we cache in gencache.
632 cache_key
= talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
634 if ((cache_key
!= NULL
) &&
635 gencache_get(cache_key
, talloc_tos(), &tmp
, NULL
)) {
637 found
= (strcmp(tmp
, printer_not_found
) != 0);
639 DEBUG(4, ("Printer %s not found\n", aprinter
));
641 return WERR_INVALID_PRINTER_NAME
;
647 /* Search all sharenames first as this is easier than pulling
648 the printer_info_2 off of disk. Don't use find_service() since
649 that calls out to map_username() */
651 /* do another loop to look for printernames */
652 for (snum
= 0; !found
&& snum
< n_services
; snum
++) {
653 const char *printer
= lp_const_servicename(snum
);
655 /* no point going on if this is not a printer */
656 if (!(lp_snum_ok(snum
) && lp_printable(snum
))) {
660 /* ignore [printers] share */
661 if (strequal(printer
, "printers")) {
665 fstrcpy(sname
, printer
);
666 if (strequal(aprinter
, printer
)) {
671 /* no point looking up the printer object if
672 we aren't allowing printername != sharename */
673 if (lp_force_printername(snum
)) {
677 result
= winreg_get_printer_internal(mem_ctx
,
682 if ( !W_ERROR_IS_OK(result
) ) {
683 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
684 sname
, win_errstr(result
)));
688 printername
= strrchr(info2
->printername
, '\\');
689 if (printername
== NULL
) {
690 printername
= info2
->printername
;
695 if (strequal(printername
, aprinter
)) {
700 DEBUGADD(10, ("printername: %s\n", printername
));
706 if (cache_key
!= NULL
) {
707 gencache_set(cache_key
, printer_not_found
,
709 TALLOC_FREE(cache_key
);
711 DEBUGADD(4,("Printer not found\n"));
712 return WERR_INVALID_PRINTER_NAME
;
715 if (cache_key
!= NULL
) {
716 gencache_set(cache_key
, sname
, time(NULL
)+300);
717 TALLOC_FREE(cache_key
);
720 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
722 strlcpy(Printer
->sharename
, sname
, sizeof(Printer
->sharename
));
727 /****************************************************************************
728 Find first available printer slot. creates a printer handle for you.
729 ****************************************************************************/
731 static WERROR
open_printer_hnd(struct pipes_struct
*p
,
732 struct policy_handle
*hnd
,
734 uint32_t access_granted
)
736 struct printer_handle
*new_printer
;
739 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
741 new_printer
= talloc_zero(p
->mem_ctx
, struct printer_handle
);
742 if (new_printer
== NULL
) {
745 talloc_set_destructor(new_printer
, printer_entry_destructor
);
747 /* This also steals the printer_handle on the policy_handle */
748 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
749 TALLOC_FREE(new_printer
);
750 return WERR_INVALID_HANDLE
;
753 /* Add to the internal list. */
754 DLIST_ADD(printers_list
, new_printer
);
756 new_printer
->notify
.option
=NULL
;
758 if (!set_printer_hnd_printertype(new_printer
, name
)) {
759 close_printer_handle(p
, hnd
);
760 return WERR_INVALID_HANDLE
;
763 result
= set_printer_hnd_name(p
->mem_ctx
,
764 get_session_info_system(),
767 if (!W_ERROR_IS_OK(result
)) {
768 close_printer_handle(p
, hnd
);
772 new_printer
->access_granted
= access_granted
;
774 DEBUG(5, ("%d printer handles active\n",
775 (int)num_pipe_handles(p
)));
780 /***************************************************************************
781 check to see if the client motify handle is monitoring the notification
782 given by (notify_type, notify_field).
783 **************************************************************************/
785 static bool is_monitoring_event_flags(uint32_t flags
, uint16_t notify_type
,
786 uint16_t notify_field
)
791 static bool is_monitoring_event(struct printer_handle
*p
, uint16_t notify_type
,
792 uint16_t notify_field
)
794 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
798 * Flags should always be zero when the change notify
799 * is registered by the client's spooler. A user Win32 app
800 * might use the flags though instead of the NOTIFY_OPTION_INFO
809 return is_monitoring_event_flags(
810 p
->notify
.flags
, notify_type
, notify_field
);
812 for (i
= 0; i
< option
->count
; i
++) {
814 /* Check match for notify_type */
816 if (option
->types
[i
].type
!= notify_type
)
819 /* Check match for field */
821 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
822 if (option
->types
[i
].fields
[j
].field
== notify_field
) {
828 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
829 p
->servername
, p
->sharename
, notify_type
, notify_field
));
834 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
835 _data->data.integer[0] = _integer; \
836 _data->data.integer[1] = 0;
839 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
840 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
841 if (!_data->data.string.string) {\
842 _data->data.string.size = 0; \
844 _data->data.string.size = strlen_m_term(_p) * 2;
846 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
847 _data->data.devmode.devmode = _devmode;
849 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
850 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
851 if (!_data->data.sd.sd) { \
852 _data->data.sd.sd_size = 0; \
854 _data->data.sd.sd_size = \
855 ndr_size_security_descriptor(_data->data.sd.sd, 0);
857 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
862 struct spoolss_Time st
;
866 if (!init_systemtime(&st
, t
)) {
870 p
= talloc_array(mem_ctx
, char, len
);
876 * Systemtime must be linearized as a set of UINT16's.
877 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
880 SSVAL(p
, 0, st
.year
);
881 SSVAL(p
, 2, st
.month
);
882 SSVAL(p
, 4, st
.day_of_week
);
884 SSVAL(p
, 8, st
.hour
);
885 SSVAL(p
, 10, st
.minute
);
886 SSVAL(p
, 12, st
.second
);
887 SSVAL(p
, 14, st
.millisecond
);
893 /* Convert a notification message to a struct spoolss_Notify */
895 static void notify_one_value(struct spoolss_notify_msg
*msg
,
896 struct spoolss_Notify
*data
,
899 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
902 static void notify_string(struct spoolss_notify_msg
*msg
,
903 struct spoolss_Notify
*data
,
906 /* The length of the message includes the trailing \0 */
908 data
->data
.string
.size
= msg
->len
* 2;
909 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
910 if (!data
->data
.string
.string
) {
911 data
->data
.string
.size
= 0;
916 static void notify_system_time(struct spoolss_notify_msg
*msg
,
917 struct spoolss_Notify
*data
,
920 data
->data
.string
.string
= NULL
;
921 data
->data
.string
.size
= 0;
923 if (msg
->len
!= sizeof(time_t)) {
924 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
929 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
930 &data
->data
.string
.string
,
931 &data
->data
.string
.size
);
934 struct notify2_message_table
{
936 void (*fn
)(struct spoolss_notify_msg
*msg
,
937 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
940 static struct notify2_message_table printer_notify_table
[] = {
941 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string
},
942 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string
},
943 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string
},
944 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string
},
945 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string
},
946 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string
},
947 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string
},
948 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL
},
949 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string
},
950 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string
},
951 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL
},
952 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string
},
953 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
954 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value
},
955 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value
},
956 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL
},
957 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL
},
958 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL
},
959 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value
},
962 static struct notify2_message_table job_notify_table
[] = {
963 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL
},
964 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL
},
965 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL
},
966 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string
},
967 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL
},
968 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL
},
969 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL
},
970 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL
},
971 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL
},
972 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL
},
973 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value
},
974 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL
},
975 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
976 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string
},
977 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL
},
978 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL
},
979 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time
},
980 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL
},
981 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL
},
982 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL
},
983 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value
},
984 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL
},
985 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value
},
986 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL
},
990 /***********************************************************************
991 Allocate talloc context for container object
992 **********************************************************************/
994 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
999 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
1004 /***********************************************************************
1005 release all allocated memory and zero out structure
1006 **********************************************************************/
1008 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1014 talloc_destroy(ctr
->ctx
);
1021 /***********************************************************************
1022 **********************************************************************/
1024 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1032 /***********************************************************************
1033 **********************************************************************/
1035 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
1037 if ( !ctr
|| !ctr
->msg_groups
)
1040 if ( idx
>= ctr
->num_groups
)
1043 return &ctr
->msg_groups
[idx
];
1047 /***********************************************************************
1048 How many groups of change messages do we have ?
1049 **********************************************************************/
1051 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1056 return ctr
->num_groups
;
1059 /***********************************************************************
1060 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1061 **********************************************************************/
1063 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
1065 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
1066 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
1067 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
1073 /* loop over all groups looking for a matching printer name */
1075 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
1076 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
1080 /* add a new group? */
1082 if ( i
== ctr
->num_groups
) {
1085 if ( !(groups
= talloc_realloc( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
1086 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1089 ctr
->msg_groups
= groups
;
1091 /* clear the new entry and set the printer name */
1093 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
1094 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
1097 /* add the change messages; 'i' is the correct index now regardless */
1099 msg_grp
= &ctr
->msg_groups
[i
];
1101 msg_grp
->num_msgs
++;
1103 if ( !(msg_list
= talloc_realloc( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
1104 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
1107 msg_grp
->msgs
= msg_list
;
1109 new_slot
= msg_grp
->num_msgs
-1;
1110 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
1112 /* need to allocate own copy of data */
1114 if ( msg
->len
!= 0 )
1115 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
1116 talloc_memdup( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
1118 return ctr
->num_groups
;
1121 static void construct_info_data(struct spoolss_Notify
*info_data
,
1122 enum spoolss_NotifyType type
,
1123 uint16_t field
, int id
);
1125 /***********************************************************************
1126 Send a change notication message on all handles which have a call
1128 **********************************************************************/
1130 static int build_notify2_messages(TALLOC_CTX
*mem_ctx
,
1131 struct printer_handle
*prn_hnd
,
1132 SPOOLSS_NOTIFY_MSG
*messages
,
1134 struct spoolss_Notify
**_notifies
,
1137 struct spoolss_Notify
*notifies
;
1138 SPOOLSS_NOTIFY_MSG
*msg
;
1143 notifies
= talloc_zero_array(mem_ctx
,
1144 struct spoolss_Notify
, num_msgs
);
1149 for (i
= 0; i
< num_msgs
; i
++) {
1153 /* Are we monitoring this event? */
1155 if (!is_monitoring_event(prn_hnd
, msg
->type
, msg
->field
)) {
1159 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1160 "for printer [%s]\n",
1161 msg
->type
, msg
->field
, prn_hnd
->sharename
));
1164 * if the is a printer notification handle and not a job
1165 * notification type, then set the id to 0.
1166 * Otherwise just use what was specified in the message.
1168 * When registering change notification on a print server
1169 * handle we always need to send back the id (snum) matching
1170 * the printer for which the change took place.
1171 * For change notify registered on a printer handle,
1172 * this does not matter and the id should be 0.
1177 if ((msg
->type
== PRINTER_NOTIFY_TYPE
) &&
1178 (prn_hnd
->printer_type
== SPLHND_PRINTER
)) {
1184 /* Convert unix jobid to smb jobid */
1186 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1187 id
= sysjob_to_jobid(msg
->id
);
1190 DEBUG(3, ("no such unix jobid %d\n",
1196 construct_info_data(¬ifies
[count
],
1197 msg
->type
, msg
->field
, id
);
1200 case PRINTER_NOTIFY_TYPE
:
1201 if (printer_notify_table
[msg
->field
].fn
) {
1202 printer_notify_table
[msg
->field
].fn(msg
,
1203 ¬ifies
[count
], mem_ctx
);
1207 case JOB_NOTIFY_TYPE
:
1208 if (job_notify_table
[msg
->field
].fn
) {
1209 job_notify_table
[msg
->field
].fn(msg
,
1210 ¬ifies
[count
], mem_ctx
);
1215 DEBUG(5, ("Unknown notification type %d\n",
1223 *_notifies
= notifies
;
1229 static int send_notify2_printer(TALLOC_CTX
*mem_ctx
,
1230 struct printer_handle
*prn_hnd
,
1231 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
)
1233 struct spoolss_Notify
*notifies
;
1235 union spoolss_ReplyPrinterInfo info
;
1236 struct spoolss_NotifyInfo info0
;
1237 uint32_t reply_result
;
1242 /* Is there notification on this handle? */
1243 if (prn_hnd
->notify
.cli_chan
== NULL
||
1244 prn_hnd
->notify
.cli_chan
->cli_pipe
== NULL
||
1245 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
== NULL
||
1246 prn_hnd
->notify
.cli_chan
->active_connections
== 0) {
1250 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1251 prn_hnd
->servername
, prn_hnd
->sharename
));
1253 /* For this printer? Print servers always receive notifications. */
1254 if ((prn_hnd
->printer_type
== SPLHND_PRINTER
) &&
1255 (!strequal(msg_group
->printername
, prn_hnd
->sharename
))) {
1259 DEBUG(10,("Our printer\n"));
1261 /* build the array of change notifications */
1262 ret
= build_notify2_messages(mem_ctx
, prn_hnd
,
1264 msg_group
->num_msgs
,
1270 info0
.version
= 0x2;
1271 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1272 info0
.count
= count
;
1273 info0
.notifies
= notifies
;
1275 info
.info0
= &info0
;
1277 status
= dcerpc_spoolss_RouterReplyPrinterEx(
1278 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
,
1280 &prn_hnd
->notify
.cli_hnd
,
1281 prn_hnd
->notify
.change
, /* color */
1282 prn_hnd
->notify
.flags
,
1284 0, /* reply_type, must be 0 */
1286 if (!NT_STATUS_IS_OK(status
)) {
1287 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1289 prn_hnd
->notify
.cli_chan
->cli_pipe
->srv_name_slash
,
1290 nt_errstr(status
)));
1291 werr
= ntstatus_to_werror(status
);
1292 } else if (!W_ERROR_IS_OK(werr
)) {
1293 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1295 prn_hnd
->notify
.cli_chan
->cli_pipe
->srv_name_slash
,
1298 switch (reply_result
) {
1301 case PRINTER_NOTIFY_INFO_DISCARDED
:
1302 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1303 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1312 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
1314 struct printer_handle
*p
;
1315 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
1316 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
1320 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1324 if (!msg_group
->msgs
) {
1325 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1329 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
1331 /* loop over all printers */
1333 for (p
= printers_list
; p
; p
= p
->next
) {
1334 ret
= send_notify2_printer(mem_ctx
, p
, msg_group
);
1341 DEBUG(8,("send_notify2_changes: Exit...\n"));
1345 /***********************************************************************
1346 **********************************************************************/
1348 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1351 uint32_t tv_sec
, tv_usec
;
1354 /* Unpack message */
1356 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "f",
1359 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "ddddddd",
1361 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1364 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "dd",
1365 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1367 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "B",
1368 &msg
->len
, &msg
->notify
.data
);
1370 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1371 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1373 tv
->tv_sec
= tv_sec
;
1374 tv
->tv_usec
= tv_usec
;
1377 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1378 msg
->notify
.value
[1]));
1380 dump_data(3, (uint8_t *)msg
->notify
.data
, msg
->len
);
1385 /********************************************************************
1386 Receive a notify2 message list
1387 ********************************************************************/
1389 static void receive_notify2_message_list(struct messaging_context
*msg
,
1392 struct server_id server_id
,
1395 size_t msg_count
, i
;
1396 char *buf
= (char *)data
->data
;
1399 SPOOLSS_NOTIFY_MSG notify
;
1400 SPOOLSS_NOTIFY_MSG_CTR messages
;
1403 if (data
->length
< 4) {
1404 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1408 msg_count
= IVAL(buf
, 0);
1411 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1413 if (msg_count
== 0) {
1414 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1418 /* initialize the container */
1420 ZERO_STRUCT( messages
);
1421 notify_msg_ctr_init( &messages
);
1424 * build message groups for each printer identified
1425 * in a change_notify msg. Remember that a PCN message
1426 * includes the handle returned for the srv_spoolss_replyopenprinter()
1427 * call. Therefore messages are grouped according to printer handle.
1430 for ( i
=0; i
<msg_count
; i
++ ) {
1431 struct timeval msg_tv
;
1433 if (msg_ptr
+ 4 - buf
> data
->length
) {
1434 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1438 msg_len
= IVAL(msg_ptr
,0);
1441 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1442 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1446 /* unpack messages */
1448 ZERO_STRUCT( notify
);
1449 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1452 /* add to correct list in container */
1454 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1456 /* free memory that might have been allocated by notify2_unpack_msg() */
1458 if ( notify
.len
!= 0 )
1459 SAFE_FREE( notify
.notify
.data
);
1462 /* process each group of messages */
1464 num_groups
= notify_msg_ctr_numgroups( &messages
);
1465 for ( i
=0; i
<num_groups
; i
++ )
1466 send_notify2_changes( &messages
, i
);
1471 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1472 (uint32_t)msg_count
));
1474 notify_msg_ctr_destroy( &messages
);
1479 /********************************************************************
1480 Send a message to ourself about new driver being installed
1481 so we can upgrade the information for each printer bound to this
1483 ********************************************************************/
1485 static bool srv_spoolss_drv_upgrade_printer(const char *drivername
,
1486 struct messaging_context
*msg_ctx
)
1488 int len
= strlen(drivername
);
1493 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1496 messaging_send_buf(msg_ctx
, messaging_server_id(msg_ctx
),
1497 MSG_PRINTER_DRVUPGRADE
,
1498 (const uint8_t *)drivername
, len
+1);
1503 void srv_spoolss_cleanup(void)
1505 struct printer_session_counter
*session_counter
;
1507 for (session_counter
= counter_list
;
1508 session_counter
!= NULL
;
1509 session_counter
= counter_list
) {
1510 DLIST_REMOVE(counter_list
, session_counter
);
1511 TALLOC_FREE(session_counter
);
1515 /**********************************************************************
1516 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1517 over all printers, upgrading ones as necessary
1518 This is now *ONLY* called inside the background lpq updater. JRA.
1519 **********************************************************************/
1521 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1524 struct server_id server_id
,
1527 TALLOC_CTX
*tmp_ctx
;
1528 const struct auth_session_info
*session_info
= get_session_info_system();
1529 struct spoolss_PrinterInfo2
*pinfo2
;
1531 const char *drivername
;
1533 int n_services
= lp_numservices();
1534 struct dcerpc_binding_handle
*b
= NULL
;
1536 tmp_ctx
= talloc_new(NULL
);
1537 if (!tmp_ctx
) return;
1539 drivername
= talloc_strndup(tmp_ctx
, (const char *)data
->data
, data
->length
);
1541 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1545 DEBUG(10, ("do_drv_upgrade_printer: "
1546 "Got message for new driver [%s]\n", drivername
));
1548 /* Iterate the printer list */
1550 for (snum
= 0; snum
< n_services
; snum
++) {
1551 if (!lp_snum_ok(snum
) || !lp_printable(snum
)) {
1555 /* ignore [printers] share */
1556 if (strequal(lp_const_servicename(snum
), "printers")) {
1561 result
= winreg_printer_binding_handle(tmp_ctx
,
1565 if (!W_ERROR_IS_OK(result
)) {
1570 result
= winreg_get_printer(tmp_ctx
, b
,
1571 lp_const_servicename(snum
),
1574 if (!W_ERROR_IS_OK(result
)) {
1578 if (!pinfo2
->drivername
) {
1582 if (strcmp(drivername
, pinfo2
->drivername
) != 0) {
1586 DEBUG(6,("Updating printer [%s]\n", pinfo2
->printername
));
1588 /* all we care about currently is the change_id */
1589 result
= winreg_printer_update_changeid(tmp_ctx
, b
,
1590 pinfo2
->printername
);
1592 if (!W_ERROR_IS_OK(result
)) {
1593 DEBUG(3, ("do_drv_upgrade_printer: "
1594 "Failed to update changeid [%s]\n",
1595 win_errstr(result
)));
1601 talloc_free(tmp_ctx
);
1604 /********************************************************************
1605 Update the cache for all printq's with a registered client
1607 ********************************************************************/
1609 void update_monitored_printq_cache(struct messaging_context
*msg_ctx
)
1611 struct printer_handle
*printer
= printers_list
;
1614 /* loop through all printers and update the cache where
1615 a client is connected */
1617 if ((printer
->printer_type
== SPLHND_PRINTER
) &&
1618 ((printer
->notify
.cli_chan
!= NULL
) &&
1619 (printer
->notify
.cli_chan
->active_connections
> 0))) {
1620 snum
= print_queue_snum(printer
->sharename
);
1621 print_queue_status(msg_ctx
, snum
, NULL
, NULL
);
1624 printer
= printer
->next
;
1630 /****************************************************************
1631 _spoolss_OpenPrinter
1632 ****************************************************************/
1634 WERROR
_spoolss_OpenPrinter(struct pipes_struct
*p
,
1635 struct spoolss_OpenPrinter
*r
)
1637 struct spoolss_OpenPrinterEx e
;
1638 struct spoolss_UserLevel1 level1
;
1641 ZERO_STRUCT(level1
);
1643 e
.in
.printername
= r
->in
.printername
;
1644 e
.in
.datatype
= r
->in
.datatype
;
1645 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1646 e
.in
.access_mask
= r
->in
.access_mask
;
1647 e
.in
.userlevel_ctr
.level
= 1;
1648 e
.in
.userlevel_ctr
.user_info
.level1
= &level1
;
1650 e
.out
.handle
= r
->out
.handle
;
1652 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1654 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1655 /* OpenPrinterEx returns this for a bad
1656 * printer name. We must return WERR_INVALID_PRINTER_NAME
1659 werr
= WERR_INVALID_PRINTER_NAME
;
1665 static WERROR
copy_devicemode(TALLOC_CTX
*mem_ctx
,
1666 struct spoolss_DeviceMode
*orig
,
1667 struct spoolss_DeviceMode
**dest
)
1669 struct spoolss_DeviceMode
*dm
;
1671 dm
= talloc(mem_ctx
, struct spoolss_DeviceMode
);
1676 /* copy all values, then duplicate strings and structs */
1679 dm
->devicename
= talloc_strdup(dm
, orig
->devicename
);
1680 if (!dm
->devicename
) {
1683 dm
->formname
= talloc_strdup(dm
, orig
->formname
);
1684 if (!dm
->formname
) {
1687 if (orig
->driverextra_data
.data
) {
1688 dm
->driverextra_data
.data
=
1689 (uint8_t *) talloc_memdup(dm
, orig
->driverextra_data
.data
,
1690 orig
->driverextra_data
.length
);
1691 if (!dm
->driverextra_data
.data
) {
1700 /****************************************************************
1701 _spoolss_OpenPrinterEx
1702 ****************************************************************/
1704 WERROR
_spoolss_OpenPrinterEx(struct pipes_struct
*p
,
1705 struct spoolss_OpenPrinterEx
*r
)
1710 struct printer_handle
*Printer
=NULL
;
1714 if (!r
->in
.printername
) {
1715 return WERR_INVALID_PARAM
;
1718 if (!*r
->in
.printername
) {
1719 return WERR_INVALID_PARAM
;
1722 if (r
->in
.userlevel_ctr
.level
> 3) {
1723 return WERR_INVALID_PARAM
;
1725 if ((r
->in
.userlevel_ctr
.level
== 1 && !r
->in
.userlevel_ctr
.user_info
.level1
) ||
1726 (r
->in
.userlevel_ctr
.level
== 2 && !r
->in
.userlevel_ctr
.user_info
.level2
) ||
1727 (r
->in
.userlevel_ctr
.level
== 3 && !r
->in
.userlevel_ctr
.user_info
.level3
)) {
1728 return WERR_INVALID_PARAM
;
1731 /* some sanity check because you can open a printer or a print server */
1732 /* aka: \\server\printer or \\server */
1734 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1736 result
= open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0);
1737 if (!W_ERROR_IS_OK(result
)) {
1738 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1739 "for printer %s\n", r
->in
.printername
));
1740 ZERO_STRUCTP(r
->out
.handle
);
1744 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1746 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1747 "handle we created for printer %s\n", r
->in
.printername
));
1748 close_printer_handle(p
, r
->out
.handle
);
1749 ZERO_STRUCTP(r
->out
.handle
);
1750 return WERR_INVALID_PARAM
;
1754 * First case: the user is opening the print server:
1756 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1757 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1759 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1760 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1761 * or if the user is listed in the smb.conf printer admin parameter.
1763 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1764 * client view printer folder, but does not show the MSAPW.
1766 * Note: this test needs code to check access rights here too. Jeremy
1767 * could you look at this?
1769 * Second case: the user is opening a printer:
1770 * NT doesn't let us connect to a printer if the connecting user
1771 * doesn't have print permission.
1773 * Third case: user is opening a Port Monitor
1774 * access checks same as opening a handle to the print server.
1777 switch (Printer
->printer_type
)
1780 case SPLHND_PORTMON_TCP
:
1781 case SPLHND_PORTMON_LOCAL
:
1782 /* Printserver handles use global struct... */
1786 /* Map standard access rights to object specific access rights */
1788 se_map_standard(&r
->in
.access_mask
,
1789 &printserver_std_mapping
);
1791 /* Deny any object specific bits that don't apply to print
1792 servers (i.e printer and job specific bits) */
1794 r
->in
.access_mask
&= SEC_MASK_SPECIFIC
;
1796 if (r
->in
.access_mask
&
1797 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1798 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1799 close_printer_handle(p
, r
->out
.handle
);
1800 ZERO_STRUCTP(r
->out
.handle
);
1801 return WERR_ACCESS_DENIED
;
1804 /* Allow admin access */
1806 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1808 if (!lp_show_add_printer_wizard()) {
1809 close_printer_handle(p
, r
->out
.handle
);
1810 ZERO_STRUCTP(r
->out
.handle
);
1811 return WERR_ACCESS_DENIED
;
1814 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1815 and not a printer admin, then fail */
1817 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
1818 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
1819 !nt_token_check_sid(&global_sid_Builtin_Print_Operators
,
1820 p
->session_info
->security_token
)) {
1821 close_printer_handle(p
, r
->out
.handle
);
1822 ZERO_STRUCTP(r
->out
.handle
);
1823 DEBUG(3,("access DENIED as user is not root, "
1824 "has no printoperator privilege, "
1825 "not a member of the printoperator builtin group and "
1826 "is not in printer admin list"));
1827 return WERR_ACCESS_DENIED
;
1830 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1834 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1837 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1838 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1840 /* We fall through to return WERR_OK */
1843 case SPLHND_PRINTER
:
1844 /* NT doesn't let us connect to a printer if the connecting user
1845 doesn't have print permission. */
1847 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1848 close_printer_handle(p
, r
->out
.handle
);
1849 ZERO_STRUCTP(r
->out
.handle
);
1853 if (r
->in
.access_mask
== SEC_FLAG_MAXIMUM_ALLOWED
) {
1854 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1857 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1859 /* map an empty access mask to the minimum access mask */
1860 if (r
->in
.access_mask
== 0x0)
1861 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1864 * If we are not serving the printer driver for this printer,
1865 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1866 * will keep NT clients happy --jerry
1869 if (lp_use_client_driver(snum
)
1870 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1872 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1875 /* check smb.conf parameters and the the sec_desc */
1876 raddr
= tsocket_address_inet_addr_string(p
->remote_address
,
1878 if (raddr
== NULL
) {
1882 rc
= get_remote_hostname(p
->remote_address
,
1888 if (strequal(rhost
, "UNKNOWN")) {
1892 if (!allow_access(lp_hosts_deny(snum
), lp_hosts_allow(snum
),
1894 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1895 ZERO_STRUCTP(r
->out
.handle
);
1896 return WERR_ACCESS_DENIED
;
1899 if (!user_ok_token(uidtoname(p
->session_info
->unix_token
->uid
), NULL
,
1900 p
->session_info
->security_token
, snum
) ||
1901 !W_ERROR_IS_OK(print_access_check(p
->session_info
,
1904 r
->in
.access_mask
))) {
1905 DEBUG(3, ("access DENIED for printer open\n"));
1906 close_printer_handle(p
, r
->out
.handle
);
1907 ZERO_STRUCTP(r
->out
.handle
);
1908 return WERR_ACCESS_DENIED
;
1911 if ((r
->in
.access_mask
& SEC_MASK_SPECIFIC
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1912 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1913 close_printer_handle(p
, r
->out
.handle
);
1914 ZERO_STRUCTP(r
->out
.handle
);
1915 return WERR_ACCESS_DENIED
;
1918 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1919 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1921 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1923 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1924 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1926 winreg_create_printer_internal(p
->mem_ctx
,
1927 get_session_info_system(),
1929 lp_const_servicename(snum
));
1934 /* sanity check to prevent programmer error */
1935 ZERO_STRUCTP(r
->out
.handle
);
1939 Printer
->access_granted
= r
->in
.access_mask
;
1942 * If the client sent a devmode in the OpenPrinter() call, then
1943 * save it here in case we get a job submission on this handle
1946 if ((Printer
->printer_type
!= SPLHND_SERVER
)
1947 && (r
->in
.devmode_ctr
.devmode
!= NULL
)) {
1948 copy_devicemode(NULL
, r
->in
.devmode_ctr
.devmode
,
1955 /****************************************************************
1956 _spoolss_ClosePrinter
1957 ****************************************************************/
1959 WERROR
_spoolss_ClosePrinter(struct pipes_struct
*p
,
1960 struct spoolss_ClosePrinter
*r
)
1962 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1964 if (Printer
&& Printer
->document_started
) {
1965 struct spoolss_EndDocPrinter e
;
1967 e
.in
.handle
= r
->in
.handle
;
1969 _spoolss_EndDocPrinter(p
, &e
);
1972 if (!close_printer_handle(p
, r
->in
.handle
))
1975 /* clear the returned printer handle. Observed behavior
1976 from Win2k server. Don't think this really matters.
1977 Previous code just copied the value of the closed
1980 ZERO_STRUCTP(r
->out
.handle
);
1985 /****************************************************************
1986 _spoolss_DeletePrinter
1987 ****************************************************************/
1989 WERROR
_spoolss_DeletePrinter(struct pipes_struct
*p
,
1990 struct spoolss_DeletePrinter
*r
)
1992 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1996 if (Printer
&& Printer
->document_started
) {
1997 struct spoolss_EndDocPrinter e
;
1999 e
.in
.handle
= r
->in
.handle
;
2001 _spoolss_EndDocPrinter(p
, &e
);
2004 if (get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
2005 winreg_delete_printer_key_internal(p
->mem_ctx
,
2006 get_session_info_system(),
2008 lp_const_servicename(snum
),
2012 result
= delete_printer_handle(p
, r
->in
.handle
);
2017 /*******************************************************************
2018 * static function to lookup the version id corresponding to an
2019 * long architecture string
2020 ******************************************************************/
2022 static const struct print_architecture_table_node archi_table
[]= {
2024 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
2025 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
2026 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
2027 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
2028 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
2029 {"Windows IA64", SPL_ARCH_IA64
, 3 },
2030 {"Windows x64", SPL_ARCH_X64
, 3 },
2034 static const int drv_cversion
[] = {SPOOLSS_DRIVER_VERSION_9X
,
2035 SPOOLSS_DRIVER_VERSION_NT35
,
2036 SPOOLSS_DRIVER_VERSION_NT4
,
2037 SPOOLSS_DRIVER_VERSION_200X
,
2040 static int get_version_id(const char *arch
)
2044 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
2046 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
2047 return (archi_table
[i
].version
);
2053 /****************************************************************
2054 _spoolss_DeletePrinterDriver
2055 ****************************************************************/
2057 WERROR
_spoolss_DeletePrinterDriver(struct pipes_struct
*p
,
2058 struct spoolss_DeletePrinterDriver
*r
)
2061 struct spoolss_DriverInfo8
*info
= NULL
;
2064 struct dcerpc_binding_handle
*b
;
2065 TALLOC_CTX
*tmp_ctx
= NULL
;
2069 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2070 and not a printer admin, then fail */
2072 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
2073 !security_token_has_privilege(p
->session_info
->security_token
,
2074 SEC_PRIV_PRINT_OPERATOR
)) {
2075 return WERR_ACCESS_DENIED
;
2078 /* check that we have a valid driver name first */
2080 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
2081 return WERR_INVALID_ENVIRONMENT
;
2084 tmp_ctx
= talloc_new(p
->mem_ctx
);
2089 status
= winreg_printer_binding_handle(tmp_ctx
,
2090 get_session_info_system(),
2093 if (!W_ERROR_IS_OK(status
)) {
2097 for (found
= false, i
= 0; drv_cversion
[i
] >= 0; i
++) {
2098 status
= winreg_get_driver(tmp_ctx
, b
,
2099 r
->in
.architecture
, r
->in
.driver
,
2100 drv_cversion
[i
], &info
);
2101 if (!W_ERROR_IS_OK(status
)) {
2102 DEBUG(5, ("skipping del of driver with version %d\n",
2108 if (printer_driver_in_use(tmp_ctx
, b
, info
)) {
2109 status
= WERR_PRINTER_DRIVER_IN_USE
;
2113 status
= winreg_del_driver(tmp_ctx
, b
, info
, drv_cversion
[i
]);
2114 if (!W_ERROR_IS_OK(status
)) {
2115 DEBUG(0, ("failed del of driver with version %d\n",
2120 if (found
== false) {
2121 DEBUG(0, ("driver %s not found for deletion\n", r
->in
.driver
));
2122 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2128 talloc_free(tmp_ctx
);
2133 static WERROR
spoolss_dpd_version(TALLOC_CTX
*mem_ctx
,
2134 struct pipes_struct
*p
,
2135 struct spoolss_DeletePrinterDriverEx
*r
,
2136 struct dcerpc_binding_handle
*b
,
2137 struct spoolss_DriverInfo8
*info
)
2142 if (printer_driver_in_use(mem_ctx
, b
, info
)) {
2143 status
= WERR_PRINTER_DRIVER_IN_USE
;
2148 * we have a couple of cases to consider.
2149 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2150 * then the delete should fail if **any** files overlap with
2152 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2153 * non-overlapping files
2154 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2155 * are set, then do not delete any files
2156 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2159 delete_files
= r
->in
.delete_flags
2160 & (DPD_DELETE_ALL_FILES
| DPD_DELETE_UNUSED_FILES
);
2164 bool in_use
= printer_driver_files_in_use(mem_ctx
, b
, info
);
2165 if (in_use
&& (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
)) {
2166 status
= WERR_PRINTER_DRIVER_IN_USE
;
2170 * printer_driver_files_in_use() has trimmed overlapping files
2171 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2176 status
= winreg_del_driver(mem_ctx
, b
, info
, info
->version
);
2177 if (!W_ERROR_IS_OK(status
)) {
2182 * now delete any associated files if delete_files is
2183 * true. Even if this part failes, we return succes
2184 * because the driver doesn not exist any more
2187 delete_driver_files(p
->session_info
, info
);
2194 /****************************************************************
2195 _spoolss_DeletePrinterDriverEx
2196 ****************************************************************/
2198 WERROR
_spoolss_DeletePrinterDriverEx(struct pipes_struct
*p
,
2199 struct spoolss_DeletePrinterDriverEx
*r
)
2201 struct spoolss_DriverInfo8
*info
= NULL
;
2203 struct dcerpc_binding_handle
*b
;
2204 TALLOC_CTX
*tmp_ctx
= NULL
;
2208 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2209 and not a printer admin, then fail */
2211 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
2212 !security_token_has_privilege(p
->session_info
->security_token
,
2213 SEC_PRIV_PRINT_OPERATOR
)) {
2214 return WERR_ACCESS_DENIED
;
2217 /* check that we have a valid driver name first */
2218 if (get_version_id(r
->in
.architecture
) == -1) {
2219 /* this is what NT returns */
2220 return WERR_INVALID_ENVIRONMENT
;
2223 tmp_ctx
= talloc_new(p
->mem_ctx
);
2228 status
= winreg_printer_binding_handle(tmp_ctx
,
2229 get_session_info_system(),
2232 if (!W_ERROR_IS_OK(status
)) {
2236 for (found
= false, i
= 0; drv_cversion
[i
] >= 0; i
++) {
2237 if ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
2238 && (drv_cversion
[i
] != r
->in
.version
)) {
2242 /* check if a driver with this version exists before delete */
2243 status
= winreg_get_driver(tmp_ctx
, b
,
2244 r
->in
.architecture
, r
->in
.driver
,
2245 drv_cversion
[i
], &info
);
2246 if (!W_ERROR_IS_OK(status
)) {
2247 DEBUG(5, ("skipping del of driver with version %d\n",
2253 status
= spoolss_dpd_version(tmp_ctx
, p
, r
, b
, info
);
2254 if (!W_ERROR_IS_OK(status
)) {
2255 DEBUG(0, ("failed to delete driver with version %d\n",
2260 if (found
== false) {
2261 DEBUG(0, ("driver %s not found for deletion\n", r
->in
.driver
));
2262 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2268 talloc_free(tmp_ctx
);
2273 /********************************************************************
2274 GetPrinterData on a printer server Handle.
2275 ********************************************************************/
2277 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2279 enum winreg_Type
*type
,
2280 union spoolss_PrinterData
*data
)
2282 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2284 if (!strcasecmp_m(value
, "W3SvcInstalled")) {
2286 SIVAL(&data
->value
, 0, 0x00);
2290 if (!strcasecmp_m(value
, "BeepEnabled")) {
2292 SIVAL(&data
->value
, 0, 0x00);
2296 if (!strcasecmp_m(value
, "EventLog")) {
2298 /* formally was 0x1b */
2299 SIVAL(&data
->value
, 0, 0x00);
2303 if (!strcasecmp_m(value
, "NetPopup")) {
2305 SIVAL(&data
->value
, 0, 0x00);
2309 if (!strcasecmp_m(value
, "MajorVersion")) {
2312 /* Windows NT 4.0 seems to not allow uploading of drivers
2313 to a server that reports 0x3 as the MajorVersion.
2314 need to investigate more how Win2k gets around this .
2317 if (RA_WINNT
== get_remote_arch()) {
2318 SIVAL(&data
->value
, 0, 0x02);
2320 SIVAL(&data
->value
, 0, 0x03);
2326 if (!strcasecmp_m(value
, "MinorVersion")) {
2328 SIVAL(&data
->value
, 0, 0x00);
2333 * uint32_t size = 0x114
2334 * uint32_t major = 5
2335 * uint32_t minor = [0|1]
2336 * uint32_t build = [2195|2600]
2337 * extra unicode string = e.g. "Service Pack 3"
2339 if (!strcasecmp_m(value
, "OSVersion")) {
2341 enum ndr_err_code ndr_err
;
2342 struct spoolss_OSVersion os
;
2344 os
.major
= lp_parm_int(GLOBAL_SECTION_SNUM
,
2345 "spoolss", "os_major", 5);
2346 /* Windows 2000 == 5.0 */
2347 os
.minor
= lp_parm_int(GLOBAL_SECTION_SNUM
,
2348 "spoolss", "os_minor", 0);
2349 os
.build
= lp_parm_int(GLOBAL_SECTION_SNUM
,
2350 "spoolss", "os_build", 2195);
2351 os
.extra_string
= ""; /* leave extra string empty */
2353 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &os
,
2354 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2355 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2356 return WERR_GENERAL_FAILURE
;
2359 if (DEBUGLEVEL
>= 10) {
2360 NDR_PRINT_DEBUG(spoolss_OSVersion
, &os
);
2364 data
->binary
= blob
;
2370 if (!strcasecmp_m(value
, "DefaultSpoolDirectory")) {
2373 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2374 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2379 if (!strcasecmp_m(value
, "Architecture")) {
2381 data
->string
= talloc_strdup(mem_ctx
,
2382 lp_parm_const_string(GLOBAL_SECTION_SNUM
, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86
));
2383 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2388 if (!strcasecmp_m(value
, "DsPresent")) {
2391 /* only show the publish check box if we are a
2392 member of a AD domain */
2394 if (lp_security() == SEC_ADS
) {
2395 SIVAL(&data
->value
, 0, 0x01);
2397 SIVAL(&data
->value
, 0, 0x00);
2402 if (!strcasecmp_m(value
, "DNSMachineName")) {
2403 const char *hostname
= get_mydnsfullname();
2406 return WERR_BADFILE
;
2410 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2411 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2418 return WERR_INVALID_PARAM
;
2421 /****************************************************************
2422 _spoolss_GetPrinterData
2423 ****************************************************************/
2425 WERROR
_spoolss_GetPrinterData(struct pipes_struct
*p
,
2426 struct spoolss_GetPrinterData
*r
)
2428 struct spoolss_GetPrinterDataEx r2
;
2430 r2
.in
.handle
= r
->in
.handle
;
2431 r2
.in
.key_name
= "PrinterDriverData";
2432 r2
.in
.value_name
= r
->in
.value_name
;
2433 r2
.in
.offered
= r
->in
.offered
;
2434 r2
.out
.type
= r
->out
.type
;
2435 r2
.out
.data
= r
->out
.data
;
2436 r2
.out
.needed
= r
->out
.needed
;
2438 return _spoolss_GetPrinterDataEx(p
, &r2
);
2441 /*********************************************************
2442 Connect to the client machine.
2443 **********************************************************/
2445 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
, struct cli_state
**pp_cli
,
2446 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2449 struct sockaddr_storage rm_addr
;
2450 char addr
[INET6_ADDRSTRLEN
];
2452 if ( is_zero_addr(client_ss
) ) {
2453 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2455 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20, false) ) {
2456 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2459 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2461 rm_addr
= *client_ss
;
2462 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2463 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2467 if (ismyaddr((struct sockaddr
*)(void *)&rm_addr
)) {
2468 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2473 /* setup the connection */
2474 ret
= cli_full_connection( pp_cli
, lp_netbios_name(), remote_machine
,
2475 &rm_addr
, 0, "IPC$", "IPC",
2479 0, lp_client_signing());
2481 if ( !NT_STATUS_IS_OK( ret
) ) {
2482 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2487 if ( smbXcli_conn_protocol((*pp_cli
)->conn
) != PROTOCOL_NT1
) {
2488 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2489 cli_shutdown(*pp_cli
);
2494 * Ok - we have an anonymous connection to the IPC$ share.
2495 * Now start the NT Domain stuff :-).
2498 ret
= cli_rpc_pipe_open_noauth(*pp_cli
, &ndr_table_spoolss
, pp_pipe
);
2499 if (!NT_STATUS_IS_OK(ret
)) {
2500 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2501 remote_machine
, nt_errstr(ret
)));
2502 cli_shutdown(*pp_cli
);
2509 /***************************************************************************
2510 Connect to the client.
2511 ****************************************************************************/
2513 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2514 uint32_t localprinter
,
2515 enum winreg_Type type
,
2516 struct policy_handle
*handle
,
2517 struct notify_back_channel
**_chan
,
2518 struct sockaddr_storage
*client_ss
,
2519 struct messaging_context
*msg_ctx
)
2523 struct notify_back_channel
*chan
;
2525 for (chan
= back_channels
; chan
; chan
= chan
->next
) {
2526 if (memcmp(&chan
->client_address
, client_ss
,
2527 sizeof(struct sockaddr_storage
)) == 0) {
2533 * If it's the first connection, contact the client
2534 * and connect to the IPC$ share anonymously
2537 fstring unix_printer
;
2539 /* the +2 is to strip the leading 2 backslashs */
2540 fstrcpy(unix_printer
, printer
+ 2);
2542 chan
= talloc_zero(NULL
, struct notify_back_channel
);
2546 chan
->client_address
= *client_ss
;
2548 if (!spoolss_connect_to_client(&chan
->cli_pipe
, &chan
->cli
, client_ss
, unix_printer
)) {
2553 DLIST_ADD(back_channels
, chan
);
2555 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_NOTIFY2
,
2556 receive_notify2_message_list
);
2559 if (chan
->cli_pipe
== NULL
||
2560 chan
->cli_pipe
->binding_handle
== NULL
) {
2561 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2562 "NULL %s for printer %s\n",
2563 chan
->cli_pipe
== NULL
?
2564 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2570 * Tell the specific printing tdb we want messages for this printer
2571 * by registering our PID.
2574 if (!print_notify_register_pid(snum
)) {
2575 DEBUG(0, ("Failed to register our pid for printer %s\n",
2579 status
= dcerpc_spoolss_ReplyOpenPrinter(chan
->cli_pipe
->binding_handle
,
2588 if (!NT_STATUS_IS_OK(status
)) {
2589 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status
)));
2590 result
= ntstatus_to_werror(status
);
2591 } else if (!W_ERROR_IS_OK(result
)) {
2592 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result
)));
2595 chan
->active_connections
++;
2598 return (W_ERROR_IS_OK(result
));
2601 /****************************************************************
2602 ****************************************************************/
2604 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2605 const struct spoolss_NotifyOption
*r
)
2607 struct spoolss_NotifyOption
*option
;
2614 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2621 if (!option
->count
) {
2625 option
->types
= talloc_zero_array(option
,
2626 struct spoolss_NotifyOptionType
, option
->count
);
2627 if (!option
->types
) {
2628 talloc_free(option
);
2632 for (i
=0; i
< option
->count
; i
++) {
2633 option
->types
[i
] = r
->types
[i
];
2635 if (option
->types
[i
].count
) {
2636 option
->types
[i
].fields
= talloc_zero_array(option
,
2637 union spoolss_Field
, option
->types
[i
].count
);
2638 if (!option
->types
[i
].fields
) {
2639 talloc_free(option
);
2642 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2643 option
->types
[i
].fields
[k
] =
2644 r
->types
[i
].fields
[k
];
2652 /****************************************************************
2653 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2655 * before replying OK: status=0 a rpc call is made to the workstation
2656 * asking ReplyOpenPrinter
2658 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2659 * called from api_spoolss_rffpcnex
2660 ****************************************************************/
2662 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct
*p
,
2663 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2666 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2667 struct sockaddr_storage client_ss
;
2670 /* store the notify value in the printer struct */
2672 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2675 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2676 "Invalid handle (%s:%u:%u).\n",
2677 OUR_HANDLE(r
->in
.handle
)));
2681 Printer
->notify
.flags
= r
->in
.flags
;
2682 Printer
->notify
.options
= r
->in
.options
;
2683 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2684 Printer
->notify
.msg_ctx
= p
->msg_ctx
;
2686 TALLOC_FREE(Printer
->notify
.option
);
2687 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2689 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2691 /* Connect to the client machine and send a ReplyOpenPrinter */
2693 if ( Printer
->printer_type
== SPLHND_SERVER
)
2695 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2696 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2699 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2700 "remote_address is %s\n",
2701 tsocket_address_string(p
->remote_address
, p
->mem_ctx
)));
2703 if (!lp_print_notify_backchannel(snum
)) {
2704 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2705 "backchannel disabled\n"));
2706 return WERR_SERVER_UNAVAILABLE
;
2709 client_len
= tsocket_address_bsd_sockaddr(p
->remote_address
,
2710 (struct sockaddr
*) &client_ss
,
2711 sizeof(struct sockaddr_storage
));
2712 if (client_len
< 0) {
2716 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2717 Printer
->notify
.printerlocal
, REG_SZ
,
2718 &Printer
->notify
.cli_hnd
,
2719 &Printer
->notify
.cli_chan
,
2720 &client_ss
, p
->msg_ctx
)) {
2721 return WERR_SERVER_UNAVAILABLE
;
2727 /*******************************************************************
2728 * fill a notify_info_data with the servername
2729 ********************************************************************/
2731 static void spoolss_notify_server_name(struct messaging_context
*msg_ctx
,
2733 struct spoolss_Notify
*data
,
2734 print_queue_struct
*queue
,
2735 struct spoolss_PrinterInfo2
*pinfo2
,
2736 TALLOC_CTX
*mem_ctx
)
2738 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->servername
);
2741 /*******************************************************************
2742 * fill a notify_info_data with the printername (not including the servername).
2743 ********************************************************************/
2745 static void spoolss_notify_printer_name(struct messaging_context
*msg_ctx
,
2747 struct spoolss_Notify
*data
,
2748 print_queue_struct
*queue
,
2749 struct spoolss_PrinterInfo2
*pinfo2
,
2750 TALLOC_CTX
*mem_ctx
)
2752 /* the notify name should not contain the \\server\ part */
2753 const char *p
= strrchr(pinfo2
->printername
, '\\');
2756 p
= pinfo2
->printername
;
2761 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2764 /*******************************************************************
2765 * fill a notify_info_data with the servicename
2766 ********************************************************************/
2768 static void spoolss_notify_share_name(struct messaging_context
*msg_ctx
,
2770 struct spoolss_Notify
*data
,
2771 print_queue_struct
*queue
,
2772 struct spoolss_PrinterInfo2
*pinfo2
,
2773 TALLOC_CTX
*mem_ctx
)
2775 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(talloc_tos(), snum
));
2778 /*******************************************************************
2779 * fill a notify_info_data with the port name
2780 ********************************************************************/
2782 static void spoolss_notify_port_name(struct messaging_context
*msg_ctx
,
2784 struct spoolss_Notify
*data
,
2785 print_queue_struct
*queue
,
2786 struct spoolss_PrinterInfo2
*pinfo2
,
2787 TALLOC_CTX
*mem_ctx
)
2789 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->portname
);
2792 /*******************************************************************
2793 * fill a notify_info_data with the printername
2794 * but it doesn't exist, have to see what to do
2795 ********************************************************************/
2797 static void spoolss_notify_driver_name(struct messaging_context
*msg_ctx
,
2799 struct spoolss_Notify
*data
,
2800 print_queue_struct
*queue
,
2801 struct spoolss_PrinterInfo2
*pinfo2
,
2802 TALLOC_CTX
*mem_ctx
)
2804 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->drivername
);
2807 /*******************************************************************
2808 * fill a notify_info_data with the comment
2809 ********************************************************************/
2811 static void spoolss_notify_comment(struct messaging_context
*msg_ctx
,
2813 struct spoolss_Notify
*data
,
2814 print_queue_struct
*queue
,
2815 struct spoolss_PrinterInfo2
*pinfo2
,
2816 TALLOC_CTX
*mem_ctx
)
2820 if (*pinfo2
->comment
== '\0') {
2821 p
= lp_comment(talloc_tos(), snum
);
2823 p
= pinfo2
->comment
;
2826 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2829 /*******************************************************************
2830 * fill a notify_info_data with the comment
2831 * location = "Room 1, floor 2, building 3"
2832 ********************************************************************/
2834 static void spoolss_notify_location(struct messaging_context
*msg_ctx
,
2836 struct spoolss_Notify
*data
,
2837 print_queue_struct
*queue
,
2838 struct spoolss_PrinterInfo2
*pinfo2
,
2839 TALLOC_CTX
*mem_ctx
)
2841 const char *loc
= pinfo2
->location
;
2844 status
= printer_list_get_printer(mem_ctx
,
2849 if (NT_STATUS_IS_OK(status
)) {
2851 loc
= pinfo2
->location
;
2855 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, loc
);
2858 /*******************************************************************
2859 * fill a notify_info_data with the device mode
2860 * jfm:xxxx don't to it for know but that's a real problem !!!
2861 ********************************************************************/
2863 static void spoolss_notify_devmode(struct messaging_context
*msg_ctx
,
2865 struct spoolss_Notify
*data
,
2866 print_queue_struct
*queue
,
2867 struct spoolss_PrinterInfo2
*pinfo2
,
2868 TALLOC_CTX
*mem_ctx
)
2870 /* for a dummy implementation we have to zero the fields */
2871 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2874 /*******************************************************************
2875 * fill a notify_info_data with the separator file name
2876 ********************************************************************/
2878 static void spoolss_notify_sepfile(struct messaging_context
*msg_ctx
,
2880 struct spoolss_Notify
*data
,
2881 print_queue_struct
*queue
,
2882 struct spoolss_PrinterInfo2
*pinfo2
,
2883 TALLOC_CTX
*mem_ctx
)
2885 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->sepfile
);
2888 /*******************************************************************
2889 * fill a notify_info_data with the print processor
2890 * jfm:xxxx return always winprint to indicate we don't do anything to it
2891 ********************************************************************/
2893 static void spoolss_notify_print_processor(struct messaging_context
*msg_ctx
,
2895 struct spoolss_Notify
*data
,
2896 print_queue_struct
*queue
,
2897 struct spoolss_PrinterInfo2
*pinfo2
,
2898 TALLOC_CTX
*mem_ctx
)
2900 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->printprocessor
);
2903 /*******************************************************************
2904 * fill a notify_info_data with the print processor options
2905 * jfm:xxxx send an empty string
2906 ********************************************************************/
2908 static void spoolss_notify_parameters(struct messaging_context
*msg_ctx
,
2910 struct spoolss_Notify
*data
,
2911 print_queue_struct
*queue
,
2912 struct spoolss_PrinterInfo2
*pinfo2
,
2913 TALLOC_CTX
*mem_ctx
)
2915 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->parameters
);
2918 /*******************************************************************
2919 * fill a notify_info_data with the data type
2920 * jfm:xxxx always send RAW as data type
2921 ********************************************************************/
2923 static void spoolss_notify_datatype(struct messaging_context
*msg_ctx
,
2925 struct spoolss_Notify
*data
,
2926 print_queue_struct
*queue
,
2927 struct spoolss_PrinterInfo2
*pinfo2
,
2928 TALLOC_CTX
*mem_ctx
)
2930 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->datatype
);
2933 /*******************************************************************
2934 * fill a notify_info_data with the security descriptor
2935 * jfm:xxxx send an null pointer to say no security desc
2936 * have to implement security before !
2937 ********************************************************************/
2939 static void spoolss_notify_security_desc(struct messaging_context
*msg_ctx
,
2941 struct spoolss_Notify
*data
,
2942 print_queue_struct
*queue
,
2943 struct spoolss_PrinterInfo2
*pinfo2
,
2944 TALLOC_CTX
*mem_ctx
)
2946 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
, pinfo2
->secdesc
);
2949 /*******************************************************************
2950 * fill a notify_info_data with the attributes
2951 * jfm:xxxx a samba printer is always shared
2952 ********************************************************************/
2954 static void spoolss_notify_attributes(struct messaging_context
*msg_ctx
,
2956 struct spoolss_Notify
*data
,
2957 print_queue_struct
*queue
,
2958 struct spoolss_PrinterInfo2
*pinfo2
,
2959 TALLOC_CTX
*mem_ctx
)
2961 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->attributes
);
2964 /*******************************************************************
2965 * fill a notify_info_data with the priority
2966 ********************************************************************/
2968 static void spoolss_notify_priority(struct messaging_context
*msg_ctx
,
2970 struct spoolss_Notify
*data
,
2971 print_queue_struct
*queue
,
2972 struct spoolss_PrinterInfo2
*pinfo2
,
2973 TALLOC_CTX
*mem_ctx
)
2975 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->priority
);
2978 /*******************************************************************
2979 * fill a notify_info_data with the default priority
2980 ********************************************************************/
2982 static void spoolss_notify_default_priority(struct messaging_context
*msg_ctx
,
2984 struct spoolss_Notify
*data
,
2985 print_queue_struct
*queue
,
2986 struct spoolss_PrinterInfo2
*pinfo2
,
2987 TALLOC_CTX
*mem_ctx
)
2989 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->defaultpriority
);
2992 /*******************************************************************
2993 * fill a notify_info_data with the start time
2994 ********************************************************************/
2996 static void spoolss_notify_start_time(struct messaging_context
*msg_ctx
,
2998 struct spoolss_Notify
*data
,
2999 print_queue_struct
*queue
,
3000 struct spoolss_PrinterInfo2
*pinfo2
,
3001 TALLOC_CTX
*mem_ctx
)
3003 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->starttime
);
3006 /*******************************************************************
3007 * fill a notify_info_data with the until time
3008 ********************************************************************/
3010 static void spoolss_notify_until_time(struct messaging_context
*msg_ctx
,
3012 struct spoolss_Notify
*data
,
3013 print_queue_struct
*queue
,
3014 struct spoolss_PrinterInfo2
*pinfo2
,
3015 TALLOC_CTX
*mem_ctx
)
3017 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->untiltime
);
3020 /*******************************************************************
3021 * fill a notify_info_data with the status
3022 ********************************************************************/
3024 static void spoolss_notify_status(struct messaging_context
*msg_ctx
,
3026 struct spoolss_Notify
*data
,
3027 print_queue_struct
*queue
,
3028 struct spoolss_PrinterInfo2
*pinfo2
,
3029 TALLOC_CTX
*mem_ctx
)
3031 print_status_struct status
;
3033 print_queue_length(msg_ctx
, snum
, &status
);
3034 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
3037 /*******************************************************************
3038 * fill a notify_info_data with the number of jobs queued
3039 ********************************************************************/
3041 static void spoolss_notify_cjobs(struct messaging_context
*msg_ctx
,
3043 struct spoolss_Notify
*data
,
3044 print_queue_struct
*queue
,
3045 struct spoolss_PrinterInfo2
*pinfo2
,
3046 TALLOC_CTX
*mem_ctx
)
3048 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3049 data
, print_queue_length(msg_ctx
, snum
, NULL
));
3052 /*******************************************************************
3053 * fill a notify_info_data with the average ppm
3054 ********************************************************************/
3056 static void spoolss_notify_average_ppm(struct messaging_context
*msg_ctx
,
3058 struct spoolss_Notify
*data
,
3059 print_queue_struct
*queue
,
3060 struct spoolss_PrinterInfo2
*pinfo2
,
3061 TALLOC_CTX
*mem_ctx
)
3063 /* always respond 8 pages per minutes */
3064 /* a little hard ! */
3065 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->averageppm
);
3068 /*******************************************************************
3069 * fill a notify_info_data with username
3070 ********************************************************************/
3072 static void spoolss_notify_username(struct messaging_context
*msg_ctx
,
3074 struct spoolss_Notify
*data
,
3075 print_queue_struct
*queue
,
3076 struct spoolss_PrinterInfo2
*pinfo2
,
3077 TALLOC_CTX
*mem_ctx
)
3079 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
3082 /*******************************************************************
3083 * fill a notify_info_data with job status
3084 ********************************************************************/
3086 static void spoolss_notify_job_status(struct messaging_context
*msg_ctx
,
3088 struct spoolss_Notify
*data
,
3089 print_queue_struct
*queue
,
3090 struct spoolss_PrinterInfo2
*pinfo2
,
3091 TALLOC_CTX
*mem_ctx
)
3093 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
3096 /*******************************************************************
3097 * fill a notify_info_data with job name
3098 ********************************************************************/
3100 static void spoolss_notify_job_name(struct messaging_context
*msg_ctx
,
3102 struct spoolss_Notify
*data
,
3103 print_queue_struct
*queue
,
3104 struct spoolss_PrinterInfo2
*pinfo2
,
3105 TALLOC_CTX
*mem_ctx
)
3107 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
3110 /*******************************************************************
3111 * fill a notify_info_data with job status
3112 ********************************************************************/
3114 static void spoolss_notify_job_status_string(struct messaging_context
*msg_ctx
,
3116 struct spoolss_Notify
*data
,
3117 print_queue_struct
*queue
,
3118 struct spoolss_PrinterInfo2
*pinfo2
,
3119 TALLOC_CTX
*mem_ctx
)
3122 * Now we're returning job status codes we just return a "" here. JRA.
3127 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3130 switch (queue
->status
) {
3135 p
= ""; /* NT provides the paused string */
3144 #endif /* NO LONGER NEEDED. */
3146 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
3149 /*******************************************************************
3150 * fill a notify_info_data with job time
3151 ********************************************************************/
3153 static void spoolss_notify_job_time(struct messaging_context
*msg_ctx
,
3155 struct spoolss_Notify
*data
,
3156 print_queue_struct
*queue
,
3157 struct spoolss_PrinterInfo2
*pinfo2
,
3158 TALLOC_CTX
*mem_ctx
)
3160 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3163 /*******************************************************************
3164 * fill a notify_info_data with job size
3165 ********************************************************************/
3167 static void spoolss_notify_job_size(struct messaging_context
*msg_ctx
,
3169 struct spoolss_Notify
*data
,
3170 print_queue_struct
*queue
,
3171 struct spoolss_PrinterInfo2
*pinfo2
,
3172 TALLOC_CTX
*mem_ctx
)
3174 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
3177 /*******************************************************************
3178 * fill a notify_info_data with page info
3179 ********************************************************************/
3180 static void spoolss_notify_total_pages(struct messaging_context
*msg_ctx
,
3182 struct spoolss_Notify
*data
,
3183 print_queue_struct
*queue
,
3184 struct spoolss_PrinterInfo2
*pinfo2
,
3185 TALLOC_CTX
*mem_ctx
)
3187 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
3190 /*******************************************************************
3191 * fill a notify_info_data with pages printed info.
3192 ********************************************************************/
3193 static void spoolss_notify_pages_printed(struct messaging_context
*msg_ctx
,
3195 struct spoolss_Notify
*data
,
3196 print_queue_struct
*queue
,
3197 struct spoolss_PrinterInfo2
*pinfo2
,
3198 TALLOC_CTX
*mem_ctx
)
3200 /* Add code when back-end tracks this */
3201 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3204 /*******************************************************************
3205 Fill a notify_info_data with job position.
3206 ********************************************************************/
3208 static void spoolss_notify_job_position(struct messaging_context
*msg_ctx
,
3210 struct spoolss_Notify
*data
,
3211 print_queue_struct
*queue
,
3212 struct spoolss_PrinterInfo2
*pinfo2
,
3213 TALLOC_CTX
*mem_ctx
)
3215 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->sysjob
);
3218 /*******************************************************************
3219 Fill a notify_info_data with submitted time.
3220 ********************************************************************/
3222 static void spoolss_notify_submitted_time(struct messaging_context
*msg_ctx
,
3224 struct spoolss_Notify
*data
,
3225 print_queue_struct
*queue
,
3226 struct spoolss_PrinterInfo2
*pinfo2
,
3227 TALLOC_CTX
*mem_ctx
)
3229 data
->data
.string
.string
= NULL
;
3230 data
->data
.string
.size
= 0;
3232 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
3233 &data
->data
.string
.string
,
3234 &data
->data
.string
.size
);
3238 struct s_notify_info_data_table
3240 enum spoolss_NotifyType type
;
3243 enum spoolss_NotifyTable variable_type
;
3244 void (*fn
) (struct messaging_context
*msg_ctx
,
3245 int snum
, struct spoolss_Notify
*data
,
3246 print_queue_struct
*queue
,
3247 struct spoolss_PrinterInfo2
*pinfo2
,
3248 TALLOC_CTX
*mem_ctx
);
3251 /* A table describing the various print notification constants and
3252 whether the notification data is a pointer to a variable sized
3253 buffer, a one value uint32_t or a two value uint32_t. */
3255 static const struct s_notify_info_data_table notify_info_data_table
[] =
3257 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3258 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3259 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
3260 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3261 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3262 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
3263 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
3264 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3265 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
3266 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3267 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3268 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3269 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
3270 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
3271 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3272 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
3273 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3274 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3275 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
3276 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
3277 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
3278 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3279 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3280 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3281 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3282 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3283 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3284 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3285 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3286 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3287 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3288 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3289 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3290 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3291 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3292 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3293 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3294 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3295 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3296 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3297 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3298 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3299 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3300 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3301 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3302 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3303 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3304 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3305 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3308 /*******************************************************************
3309 Return the variable_type of info_data structure.
3310 ********************************************************************/
3312 static enum spoolss_NotifyTable
variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3317 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3318 if ( (notify_info_data_table
[i
].type
== type
) &&
3319 (notify_info_data_table
[i
].field
== field
) ) {
3320 return notify_info_data_table
[i
].variable_type
;
3324 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3326 return (enum spoolss_NotifyTable
) 0;
3329 /****************************************************************************
3330 ****************************************************************************/
3332 static bool search_notify(enum spoolss_NotifyType type
,
3338 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3339 if (notify_info_data_table
[i
].type
== type
&&
3340 notify_info_data_table
[i
].field
== field
&&
3341 notify_info_data_table
[i
].fn
!= NULL
) {
3350 /****************************************************************************
3351 ****************************************************************************/
3353 static void construct_info_data(struct spoolss_Notify
*info_data
,
3354 enum spoolss_NotifyType type
,
3355 uint16_t field
, int id
)
3357 info_data
->type
= type
;
3358 info_data
->field
.field
= field
;
3359 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3360 info_data
->job_id
= id
;
3363 /*******************************************************************
3365 * fill a notify_info struct with info asked
3367 ********************************************************************/
3369 static bool construct_notify_printer_info(struct messaging_context
*msg_ctx
,
3370 struct printer_handle
*print_hnd
,
3371 struct spoolss_NotifyInfo
*info
,
3372 struct spoolss_PrinterInfo2
*pinfo2
,
3374 const struct spoolss_NotifyOptionType
*option_type
,
3376 TALLOC_CTX
*mem_ctx
)
3379 enum spoolss_NotifyType type
;
3382 struct spoolss_Notify
*current_data
;
3384 type
= option_type
->type
;
3386 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3387 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3388 option_type
->count
, lp_servicename(talloc_tos(), snum
)));
3390 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3391 field
= option_type
->fields
[field_num
].field
;
3393 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3395 if (!search_notify(type
, field
, &j
) )
3398 info
->notifies
= talloc_realloc(info
, info
->notifies
,
3399 struct spoolss_Notify
,
3401 if (info
->notifies
== NULL
) {
3402 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3406 current_data
= &info
->notifies
[info
->count
];
3408 construct_info_data(current_data
, type
, field
, id
);
3410 DEBUG(10, ("construct_notify_printer_info: "
3411 "calling [%s] snum=%d printername=[%s])\n",
3412 notify_info_data_table
[j
].name
, snum
,
3413 pinfo2
->printername
));
3415 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3416 NULL
, pinfo2
, mem_ctx
);
3424 /*******************************************************************
3426 * fill a notify_info struct with info asked
3428 ********************************************************************/
3430 static bool construct_notify_jobs_info(struct messaging_context
*msg_ctx
,
3431 print_queue_struct
*queue
,
3432 struct spoolss_NotifyInfo
*info
,
3433 struct spoolss_PrinterInfo2
*pinfo2
,
3435 const struct spoolss_NotifyOptionType
*option_type
,
3437 TALLOC_CTX
*mem_ctx
)
3440 enum spoolss_NotifyType type
;
3442 struct spoolss_Notify
*current_data
;
3444 DEBUG(4,("construct_notify_jobs_info\n"));
3446 type
= option_type
->type
;
3448 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3449 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3450 option_type
->count
));
3452 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3453 field
= option_type
->fields
[field_num
].field
;
3455 if (!search_notify(type
, field
, &j
) )
3458 info
->notifies
= talloc_realloc(info
, info
->notifies
,
3459 struct spoolss_Notify
,
3461 if (info
->notifies
== NULL
) {
3462 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3466 current_data
=&(info
->notifies
[info
->count
]);
3468 construct_info_data(current_data
, type
, field
, id
);
3469 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3470 queue
, pinfo2
, mem_ctx
);
3478 * JFM: The enumeration is not that simple, it's even non obvious.
3480 * let's take an example: I want to monitor the PRINTER SERVER for
3481 * the printer's name and the number of jobs currently queued.
3482 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3483 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3485 * I have 3 printers on the back of my server.
3487 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3490 * 1 printer 1 name 1
3491 * 2 printer 1 cjob 1
3492 * 3 printer 2 name 2
3493 * 4 printer 2 cjob 2
3494 * 5 printer 3 name 3
3495 * 6 printer 3 name 3
3497 * that's the print server case, the printer case is even worse.
3500 /*******************************************************************
3502 * enumerate all printers on the printserver
3503 * fill a notify_info struct with info asked
3505 ********************************************************************/
3507 static WERROR
printserver_notify_info(struct pipes_struct
*p
,
3508 struct policy_handle
*hnd
,
3509 struct spoolss_NotifyInfo
*info
,
3510 TALLOC_CTX
*mem_ctx
)
3513 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3514 int n_services
=lp_numservices();
3516 struct spoolss_NotifyOption
*option
;
3517 struct spoolss_NotifyOptionType option_type
;
3518 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3521 DEBUG(4,("printserver_notify_info\n"));
3526 option
= Printer
->notify
.option
;
3529 info
->notifies
= NULL
;
3532 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3533 sending a ffpcn() request first */
3538 for (i
=0; i
<option
->count
; i
++) {
3539 option_type
= option
->types
[i
];
3541 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3544 for (snum
= 0; snum
< n_services
; snum
++) {
3545 if (!lp_browseable(snum
) ||
3546 !lp_snum_ok(snum
) ||
3547 !lp_printable(snum
)) {
3548 continue; /* skip */
3551 /* Maybe we should use the SYSTEM session_info here... */
3552 result
= winreg_get_printer_internal(mem_ctx
,
3553 get_session_info_system(),
3555 lp_servicename(talloc_tos(), snum
),
3557 if (!W_ERROR_IS_OK(result
)) {
3558 DEBUG(4, ("printserver_notify_info: "
3559 "Failed to get printer [%s]\n",
3560 lp_servicename(talloc_tos(), snum
)));
3565 construct_notify_printer_info(p
->msg_ctx
,
3571 TALLOC_FREE(pinfo2
);
3577 * Debugging information, don't delete.
3580 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3581 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3582 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3584 for (i
=0; i
<info
->count
; i
++) {
3585 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3586 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3587 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3594 /*******************************************************************
3596 * fill a notify_info struct with info asked
3598 ********************************************************************/
3600 static WERROR
printer_notify_info(struct pipes_struct
*p
,
3601 struct policy_handle
*hnd
,
3602 struct spoolss_NotifyInfo
*info
,
3603 TALLOC_CTX
*mem_ctx
)
3606 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3609 struct spoolss_NotifyOption
*option
;
3610 struct spoolss_NotifyOptionType option_type
;
3612 print_queue_struct
*queue
=NULL
;
3613 print_status_struct status
;
3614 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3616 struct tdb_print_db
*pdb
;
3618 DEBUG(4,("printer_notify_info\n"));
3623 option
= Printer
->notify
.option
;
3627 info
->notifies
= NULL
;
3630 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3631 sending a ffpcn() request first */
3636 if (!get_printer_snum(p
, hnd
, &snum
, NULL
)) {
3640 pdb
= get_print_db_byname(Printer
->sharename
);
3645 /* Maybe we should use the SYSTEM session_info here... */
3646 result
= winreg_get_printer_internal(mem_ctx
,
3647 get_session_info_system(),
3649 lp_servicename(talloc_tos(), snum
), &pinfo2
);
3650 if (!W_ERROR_IS_OK(result
)) {
3651 result
= WERR_BADFID
;
3656 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3657 * correct servername.
3659 pinfo2
->servername
= talloc_strdup(pinfo2
, Printer
->servername
);
3660 if (pinfo2
->servername
== NULL
) {
3661 result
= WERR_NOMEM
;
3665 for (i
= 0; i
< option
->count
; i
++) {
3666 option_type
= option
->types
[i
];
3668 switch (option_type
.type
) {
3669 case PRINTER_NOTIFY_TYPE
:
3670 if (construct_notify_printer_info(p
->msg_ctx
,
3679 case JOB_NOTIFY_TYPE
:
3681 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
,
3684 for (j
= 0; j
< count
; j
++) {
3686 jobid
= sysjob_to_jobid_pdb(pdb
,
3688 if (jobid
== (uint32_t)-1) {
3689 DEBUG(2, ("ignoring untracked job %d\n",
3693 /* FIXME check return value */
3694 construct_notify_jobs_info(p
->msg_ctx
,
3708 * Debugging information, don't delete.
3711 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3712 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3713 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3715 for (i=0; i<info->count; i++) {
3716 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3717 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3718 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3722 talloc_free(pinfo2
);
3725 release_print_db(pdb
);
3729 /****************************************************************
3730 _spoolss_RouterRefreshPrinterChangeNotify
3731 ****************************************************************/
3733 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct
*p
,
3734 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3736 struct spoolss_NotifyInfo
*info
;
3738 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3739 WERROR result
= WERR_BADFID
;
3741 /* we always have a spoolss_NotifyInfo struct */
3742 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3744 result
= WERR_NOMEM
;
3748 *r
->out
.info
= info
;
3751 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3752 "Invalid handle (%s:%u:%u).\n",
3753 OUR_HANDLE(r
->in
.handle
)));
3757 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3760 * We are now using the change value, and
3761 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3762 * I don't have a global notification system, I'm sending back all the
3763 * information even when _NOTHING_ has changed.
3766 /* We need to keep track of the change value to send back in
3767 RRPCN replies otherwise our updates are ignored. */
3769 Printer
->notify
.fnpcn
= true;
3771 if (Printer
->notify
.cli_chan
!= NULL
&&
3772 Printer
->notify
.cli_chan
->active_connections
> 0) {
3773 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3774 "Saving change value in request [%x]\n",
3776 Printer
->notify
.change
= r
->in
.change_low
;
3779 /* just ignore the spoolss_NotifyOption */
3781 switch (Printer
->printer_type
) {
3783 result
= printserver_notify_info(p
, r
->in
.handle
,
3787 case SPLHND_PRINTER
:
3788 result
= printer_notify_info(p
, r
->in
.handle
,
3793 Printer
->notify
.fnpcn
= false;
3799 /********************************************************************
3800 ********************************************************************/
3802 static WERROR
create_printername(TALLOC_CTX
*mem_ctx
,
3803 const char *servername
,
3804 const char *printername
,
3805 const char **printername_p
)
3807 /* FIXME: add lp_force_printername() */
3809 if (servername
== NULL
) {
3810 *printername_p
= talloc_strdup(mem_ctx
, printername
);
3811 W_ERROR_HAVE_NO_MEMORY(*printername_p
);
3815 if (servername
[0] == '\\' && servername
[1] == '\\') {
3819 *printername_p
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s", servername
, printername
);
3820 W_ERROR_HAVE_NO_MEMORY(*printername_p
);
3825 /********************************************************************
3826 ********************************************************************/
3828 static void compose_devicemode_devicename(struct spoolss_DeviceMode
*dm
,
3829 const char *printername
)
3835 dm
->devicename
= talloc_strndup(dm
, printername
,
3836 MIN(strlen(printername
), 31));
3839 /********************************************************************
3840 * construct_printer_info_0
3841 * fill a printer_info_0 struct
3842 ********************************************************************/
3844 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3845 const struct auth_session_info
*session_info
,
3846 struct messaging_context
*msg_ctx
,
3847 struct spoolss_PrinterInfo2
*info2
,
3848 const char *servername
,
3849 struct spoolss_PrinterInfo0
*r
,
3853 struct printer_session_counter
*session_counter
;
3854 struct timeval setuptime
;
3855 print_status_struct status
;
3858 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
3859 if (!W_ERROR_IS_OK(result
)) {
3864 r
->servername
= talloc_strdup(mem_ctx
, servername
);
3865 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3867 r
->servername
= NULL
;
3870 count
= print_queue_length(msg_ctx
, snum
, &status
);
3872 /* check if we already have a counter for this printer */
3873 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3874 if (session_counter
->snum
== snum
)
3878 /* it's the first time, add it to the list */
3879 if (session_counter
== NULL
) {
3880 session_counter
= talloc_zero(counter_list
, struct printer_session_counter
);
3881 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3882 session_counter
->snum
= snum
;
3883 session_counter
->counter
= 0;
3884 DLIST_ADD(counter_list
, session_counter
);
3888 session_counter
->counter
++;
3894 get_startup_time(&setuptime
);
3895 init_systemtime(&r
->time
, gmtime(&setuptime
.tv_sec
));
3898 * the global_counter should be stored in a TDB as it's common to all the clients
3899 * and should be zeroed on samba startup
3901 r
->global_counter
= session_counter
->counter
;
3903 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3904 SSVAL(&r
->version
, 0, 0x0005); /* NT 5 */
3905 SSVAL(&r
->version
, 2, 0x0893); /* build 2195 */
3906 r
->free_build
= SPOOLSS_RELEASE_BUILD
;
3908 r
->max_spooling
= 0;
3909 r
->session_counter
= session_counter
->counter
;
3910 r
->num_error_out_of_paper
= 0x0;
3911 r
->num_error_not_ready
= 0x0; /* number of print failure */
3913 r
->number_of_processors
= 0x1;
3914 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3915 r
->high_part_total_bytes
= 0x0;
3917 /* ChangeID in milliseconds*/
3918 winreg_printer_get_changeid_internal(mem_ctx
, session_info
, msg_ctx
,
3919 info2
->sharename
, &r
->change_id
);
3921 r
->last_error
= WERR_OK
;
3922 r
->status
= nt_printq_status(status
.status
);
3923 r
->enumerate_network_printers
= 0x0;
3924 r
->c_setprinter
= 0x0;
3925 r
->processor_architecture
= PROCESSOR_ARCHITECTURE_INTEL
;
3926 r
->processor_level
= 0x6; /* 6 ???*/
3935 /********************************************************************
3936 * construct_printer_info1
3937 * fill a spoolss_PrinterInfo1 struct
3938 ********************************************************************/
3940 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
3941 const struct spoolss_PrinterInfo2
*info2
,
3943 const char *servername
,
3944 struct spoolss_PrinterInfo1
*r
,
3951 if (info2
->comment
== NULL
|| info2
->comment
[0] == '\0') {
3952 r
->comment
= lp_comment(mem_ctx
, snum
);
3954 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
); /* saved comment */
3956 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3958 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->name
);
3959 if (!W_ERROR_IS_OK(result
)) {
3963 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
3967 W_ERROR_HAVE_NO_MEMORY(r
->description
);
3972 /********************************************************************
3973 * construct_printer_info2
3974 * fill a spoolss_PrinterInfo2 struct
3975 ********************************************************************/
3977 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
3978 struct messaging_context
*msg_ctx
,
3979 const struct spoolss_PrinterInfo2
*info2
,
3980 const char *servername
,
3981 struct spoolss_PrinterInfo2
*r
,
3985 print_status_struct status
;
3988 count
= print_queue_length(msg_ctx
, snum
, &status
);
3991 r
->servername
= talloc_strdup(mem_ctx
, servername
);
3992 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3994 r
->servername
= NULL
;
3997 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
3998 if (!W_ERROR_IS_OK(result
)) {
4002 r
->sharename
= lp_servicename(mem_ctx
, snum
);
4003 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
4004 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
4005 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4006 r
->drivername
= talloc_strdup(mem_ctx
, info2
->drivername
);
4007 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
4009 if (info2
->comment
[0] == '\0') {
4010 r
->comment
= lp_comment(mem_ctx
, snum
);
4012 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
);
4014 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
4016 r
->location
= talloc_strdup(mem_ctx
, info2
->location
);
4017 if (info2
->location
[0] == '\0') {
4018 const char *loc
= NULL
;
4021 nt_status
= printer_list_get_printer(mem_ctx
,
4026 if (NT_STATUS_IS_OK(nt_status
)) {
4028 r
->location
= talloc_strdup(mem_ctx
, loc
);
4032 W_ERROR_HAVE_NO_MEMORY(r
->location
);
4034 r
->sepfile
= talloc_strdup(mem_ctx
, info2
->sepfile
);
4035 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
4036 r
->printprocessor
= talloc_strdup(mem_ctx
, info2
->printprocessor
);
4037 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
4038 r
->datatype
= talloc_strdup(mem_ctx
, info2
->datatype
);
4039 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
4040 r
->parameters
= talloc_strdup(mem_ctx
, info2
->parameters
);
4041 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
4043 r
->attributes
= info2
->attributes
;
4045 r
->priority
= info2
->priority
;
4046 r
->defaultpriority
= info2
->defaultpriority
;
4047 r
->starttime
= info2
->starttime
;
4048 r
->untiltime
= info2
->untiltime
;
4049 r
->status
= nt_printq_status(status
.status
);
4051 r
->averageppm
= info2
->averageppm
;
4053 if (info2
->devmode
!= NULL
) {
4054 result
= copy_devicemode(mem_ctx
,
4057 if (!W_ERROR_IS_OK(result
)) {
4060 } else if (lp_default_devmode(snum
)) {
4061 result
= spoolss_create_default_devmode(mem_ctx
,
4064 if (!W_ERROR_IS_OK(result
)) {
4069 DEBUG(8,("Returning NULL Devicemode!\n"));
4072 compose_devicemode_devicename(r
->devmode
, r
->printername
);
4076 if (info2
->secdesc
!= NULL
) {
4077 /* don't use talloc_steal() here unless you do a deep steal of all
4078 the SEC_DESC members */
4080 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
4086 /********************************************************************
4087 * construct_printer_info3
4088 * fill a spoolss_PrinterInfo3 struct
4089 ********************************************************************/
4091 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
4092 const struct spoolss_PrinterInfo2
*info2
,
4093 const char *servername
,
4094 struct spoolss_PrinterInfo3
*r
,
4097 /* These are the components of the SD we are returning. */
4099 if (info2
->secdesc
!= NULL
) {
4100 /* don't use talloc_steal() here unless you do a deep steal of all
4101 the SEC_DESC members */
4103 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
4104 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
4110 /********************************************************************
4111 * construct_printer_info4
4112 * fill a spoolss_PrinterInfo4 struct
4113 ********************************************************************/
4115 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
4116 const struct spoolss_PrinterInfo2
*info2
,
4117 const char *servername
,
4118 struct spoolss_PrinterInfo4
*r
,
4123 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4124 if (!W_ERROR_IS_OK(result
)) {
4129 r
->servername
= talloc_strdup(mem_ctx
, servername
);
4130 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4132 r
->servername
= NULL
;
4135 r
->attributes
= info2
->attributes
;
4140 /********************************************************************
4141 * construct_printer_info5
4142 * fill a spoolss_PrinterInfo5 struct
4143 ********************************************************************/
4145 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
4146 const struct spoolss_PrinterInfo2
*info2
,
4147 const char *servername
,
4148 struct spoolss_PrinterInfo5
*r
,
4153 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4154 if (!W_ERROR_IS_OK(result
)) {
4158 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
4159 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4161 r
->attributes
= info2
->attributes
;
4163 /* these two are not used by NT+ according to MSDN */
4164 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4165 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4170 /********************************************************************
4171 * construct_printer_info_6
4172 * fill a spoolss_PrinterInfo6 struct
4173 ********************************************************************/
4175 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
4176 struct messaging_context
*msg_ctx
,
4177 const struct spoolss_PrinterInfo2
*info2
,
4178 const char *servername
,
4179 struct spoolss_PrinterInfo6
*r
,
4182 print_status_struct status
;
4184 print_queue_length(msg_ctx
, snum
, &status
);
4186 r
->status
= nt_printq_status(status
.status
);
4191 /********************************************************************
4192 * construct_printer_info7
4193 * fill a spoolss_PrinterInfo7 struct
4194 ********************************************************************/
4196 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
4197 struct messaging_context
*msg_ctx
,
4198 const char *servername
,
4199 struct spoolss_PrinterInfo7
*r
,
4202 const struct auth_session_info
*session_info
;
4205 TALLOC_CTX
*tmp_ctx
= talloc_new(mem_ctx
);
4206 if (tmp_ctx
== NULL
) {
4210 session_info
= get_session_info_system();
4211 SMB_ASSERT(session_info
!= NULL
);
4213 printer
= lp_servicename(tmp_ctx
, snum
);
4214 if (printer
== NULL
) {
4215 DEBUG(0, ("invalid printer snum %d\n", snum
));
4216 werr
= WERR_INVALID_PARAM
;
4220 if (is_printer_published(tmp_ctx
, session_info
, msg_ctx
,
4221 servername
, printer
, NULL
)) {
4223 werr
= nt_printer_guid_get(tmp_ctx
, session_info
, msg_ctx
,
4225 if (!W_ERROR_IS_OK(werr
)) {
4228 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
4229 r
->action
= DSPRINT_PUBLISH
;
4231 r
->guid
= talloc_strdup(mem_ctx
, "");
4232 r
->action
= DSPRINT_UNPUBLISH
;
4234 if (r
->guid
== NULL
) {
4241 talloc_free(tmp_ctx
);
4245 /********************************************************************
4246 * construct_printer_info8
4247 * fill a spoolss_PrinterInfo8 struct
4248 ********************************************************************/
4250 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
4251 const struct spoolss_PrinterInfo2
*info2
,
4252 const char *servername
,
4253 struct spoolss_DeviceModeInfo
*r
,
4257 const char *printername
;
4259 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &printername
);
4260 if (!W_ERROR_IS_OK(result
)) {
4264 if (info2
->devmode
!= NULL
) {
4265 result
= copy_devicemode(mem_ctx
,
4268 if (!W_ERROR_IS_OK(result
)) {
4271 } else if (lp_default_devmode(snum
)) {
4272 result
= spoolss_create_default_devmode(mem_ctx
,
4275 if (!W_ERROR_IS_OK(result
)) {
4280 DEBUG(8,("Returning NULL Devicemode!\n"));
4283 compose_devicemode_devicename(r
->devmode
, printername
);
4289 /********************************************************************
4290 ********************************************************************/
4292 static bool snum_is_shared_printer(int snum
)
4294 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_printable(snum
));
4297 /********************************************************************
4298 Spoolss_enumprinters.
4299 ********************************************************************/
4301 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
4302 const struct auth_session_info
*session_info
,
4303 struct messaging_context
*msg_ctx
,
4304 const char *servername
,
4307 union spoolss_PrinterInfo
**info_p
,
4311 int n_services
= lp_numservices();
4312 union spoolss_PrinterInfo
*info
= NULL
;
4314 WERROR result
= WERR_OK
;
4315 struct dcerpc_binding_handle
*b
= NULL
;
4316 TALLOC_CTX
*tmp_ctx
= NULL
;
4318 tmp_ctx
= talloc_new(mem_ctx
);
4326 for (snum
= 0; snum
< n_services
; snum
++) {
4328 const char *printer
;
4329 struct spoolss_PrinterInfo2
*info2
;
4331 if (!snum_is_shared_printer(snum
)) {
4335 printer
= lp_const_servicename(snum
);
4337 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4341 result
= winreg_printer_binding_handle(tmp_ctx
,
4345 if (!W_ERROR_IS_OK(result
)) {
4350 result
= winreg_create_printer(tmp_ctx
, b
,
4352 if (!W_ERROR_IS_OK(result
)) {
4356 info
= talloc_realloc(tmp_ctx
, info
,
4357 union spoolss_PrinterInfo
,
4360 result
= WERR_NOMEM
;
4364 result
= winreg_get_printer(tmp_ctx
, b
,
4366 if (!W_ERROR_IS_OK(result
)) {
4372 result
= construct_printer_info0(info
, session_info
,
4375 &info
[count
].info0
, snum
);
4378 result
= construct_printer_info1(info
, info2
, flags
,
4380 &info
[count
].info1
, snum
);
4383 result
= construct_printer_info2(info
, msg_ctx
, info2
,
4385 &info
[count
].info2
, snum
);
4388 result
= construct_printer_info4(info
, info2
,
4390 &info
[count
].info4
, snum
);
4393 result
= construct_printer_info5(info
, info2
,
4395 &info
[count
].info5
, snum
);
4399 result
= WERR_UNKNOWN_LEVEL
;
4403 if (!W_ERROR_IS_OK(result
)) {
4411 if (W_ERROR_IS_OK(result
)) {
4412 *info_p
= talloc_move(mem_ctx
, &info
);
4416 talloc_free(tmp_ctx
);
4421 /********************************************************************
4422 * handle enumeration of printers at level 0
4423 ********************************************************************/
4425 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
4426 const struct auth_session_info
*session_info
,
4427 struct messaging_context
*msg_ctx
,
4429 const char *servername
,
4430 union spoolss_PrinterInfo
**info
,
4433 DEBUG(4,("enum_all_printers_info_0\n"));
4435 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4436 servername
, 0, flags
, info
, count
);
4440 /********************************************************************
4441 ********************************************************************/
4443 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4444 const struct auth_session_info
*session_info
,
4445 struct messaging_context
*msg_ctx
,
4446 const char *servername
,
4448 union spoolss_PrinterInfo
**info
,
4451 DEBUG(4,("enum_all_printers_info_1\n"));
4453 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4454 servername
, 1, flags
, info
, count
);
4457 /********************************************************************
4458 enum_all_printers_info_1_local.
4459 *********************************************************************/
4461 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4462 const struct auth_session_info
*session_info
,
4463 struct messaging_context
*msg_ctx
,
4464 const char *servername
,
4465 union spoolss_PrinterInfo
**info
,
4468 DEBUG(4,("enum_all_printers_info_1_local\n"));
4470 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4471 servername
, PRINTER_ENUM_ICON8
, info
, count
);
4474 /********************************************************************
4475 enum_all_printers_info_1_name.
4476 *********************************************************************/
4478 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4479 const struct auth_session_info
*session_info
,
4480 struct messaging_context
*msg_ctx
,
4481 const char *servername
,
4482 union spoolss_PrinterInfo
**info
,
4485 const char *s
= servername
;
4487 DEBUG(4,("enum_all_printers_info_1_name\n"));
4489 if (servername
!= NULL
&&
4490 (servername
[0] == '\\') && (servername
[1] == '\\')) {
4494 if (!is_myname_or_ipaddr(s
)) {
4495 return WERR_INVALID_NAME
;
4498 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4499 servername
, PRINTER_ENUM_ICON8
, info
, count
);
4502 /********************************************************************
4503 enum_all_printers_info_1_network.
4504 *********************************************************************/
4506 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4507 const struct auth_session_info
*session_info
,
4508 struct messaging_context
*msg_ctx
,
4509 const char *servername
,
4510 union spoolss_PrinterInfo
**info
,
4513 const char *s
= servername
;
4515 DEBUG(4,("enum_all_printers_info_1_network\n"));
4517 /* If we respond to a enum_printers level 1 on our name with flags
4518 set to PRINTER_ENUM_REMOTE with a list of printers then these
4519 printers incorrectly appear in the APW browse list.
4520 Specifically the printers for the server appear at the workgroup
4521 level where all the other servers in the domain are
4522 listed. Windows responds to this call with a
4523 WERR_CAN_NOT_COMPLETE so we should do the same. */
4525 if (servername
!= NULL
&&
4526 (servername
[0] == '\\') && (servername
[1] == '\\')) {
4530 if (is_myname_or_ipaddr(s
)) {
4531 return WERR_CAN_NOT_COMPLETE
;
4534 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4535 servername
, PRINTER_ENUM_NAME
, info
, count
);
4538 /********************************************************************
4539 * api_spoolss_enumprinters
4541 * called from api_spoolss_enumprinters (see this to understand)
4542 ********************************************************************/
4544 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4545 const struct auth_session_info
*session_info
,
4546 struct messaging_context
*msg_ctx
,
4547 const char *servername
,
4548 union spoolss_PrinterInfo
**info
,
4551 DEBUG(4,("enum_all_printers_info_2\n"));
4553 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4554 servername
, 2, 0, info
, count
);
4557 /********************************************************************
4558 * handle enumeration of printers at level 1
4559 ********************************************************************/
4561 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4562 const struct auth_session_info
*session_info
,
4563 struct messaging_context
*msg_ctx
,
4565 const char *servername
,
4566 union spoolss_PrinterInfo
**info
,
4569 /* Not all the flags are equals */
4571 if (flags
& PRINTER_ENUM_LOCAL
) {
4572 return enum_all_printers_info_1_local(mem_ctx
, session_info
,
4573 msg_ctx
, servername
, info
, count
);
4576 if (flags
& PRINTER_ENUM_NAME
) {
4577 return enum_all_printers_info_1_name(mem_ctx
, session_info
,
4578 msg_ctx
, servername
, info
,
4582 if (flags
& PRINTER_ENUM_NETWORK
) {
4583 return enum_all_printers_info_1_network(mem_ctx
, session_info
,
4584 msg_ctx
, servername
, info
,
4588 return WERR_OK
; /* NT4sp5 does that */
4591 /********************************************************************
4592 * handle enumeration of printers at level 2
4593 ********************************************************************/
4595 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4596 const struct auth_session_info
*session_info
,
4597 struct messaging_context
*msg_ctx
,
4599 const char *servername
,
4600 union spoolss_PrinterInfo
**info
,
4603 if (flags
& PRINTER_ENUM_LOCAL
) {
4605 return enum_all_printers_info_2(mem_ctx
, session_info
, msg_ctx
,
4610 if (flags
& PRINTER_ENUM_NAME
) {
4611 if (servername
&& !is_myname_or_ipaddr(canon_servername(servername
))) {
4612 return WERR_INVALID_NAME
;
4615 return enum_all_printers_info_2(mem_ctx
, session_info
, msg_ctx
,
4620 if (flags
& PRINTER_ENUM_REMOTE
) {
4621 return WERR_UNKNOWN_LEVEL
;
4627 /********************************************************************
4628 * handle enumeration of printers at level 4
4629 ********************************************************************/
4631 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4632 const struct auth_session_info
*session_info
,
4633 struct messaging_context
*msg_ctx
,
4635 const char *servername
,
4636 union spoolss_PrinterInfo
**info
,
4639 DEBUG(4,("enum_all_printers_info_4\n"));
4641 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4642 servername
, 4, flags
, info
, count
);
4646 /********************************************************************
4647 * handle enumeration of printers at level 5
4648 ********************************************************************/
4650 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4651 const struct auth_session_info
*session_info
,
4652 struct messaging_context
*msg_ctx
,
4654 const char *servername
,
4655 union spoolss_PrinterInfo
**info
,
4658 DEBUG(4,("enum_all_printers_info_5\n"));
4660 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4661 servername
, 5, flags
, info
, count
);
4664 /****************************************************************
4665 _spoolss_EnumPrinters
4666 ****************************************************************/
4668 WERROR
_spoolss_EnumPrinters(struct pipes_struct
*p
,
4669 struct spoolss_EnumPrinters
*r
)
4671 const struct auth_session_info
*session_info
= get_session_info_system();
4674 /* that's an [in out] buffer */
4676 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4677 return WERR_INVALID_PARAM
;
4680 DEBUG(4,("_spoolss_EnumPrinters\n"));
4684 *r
->out
.info
= NULL
;
4688 * flags==PRINTER_ENUM_NAME
4689 * if name=="" then enumerates all printers
4690 * if name!="" then enumerate the printer
4691 * flags==PRINTER_ENUM_REMOTE
4692 * name is NULL, enumerate printers
4693 * Level 2: name!="" enumerates printers, name can't be NULL
4694 * Level 3: doesn't exist
4695 * Level 4: does a local registry lookup
4696 * Level 5: same as Level 2
4699 if (r
->in
.server
&& r
->in
.server
[0] == '\0') {
4700 r
->in
.server
= NULL
;
4703 switch (r
->in
.level
) {
4705 result
= enumprinters_level0(p
->mem_ctx
, session_info
,
4706 p
->msg_ctx
, r
->in
.flags
,
4708 r
->out
.info
, r
->out
.count
);
4711 result
= enumprinters_level1(p
->mem_ctx
, session_info
,
4712 p
->msg_ctx
, r
->in
.flags
,
4714 r
->out
.info
, r
->out
.count
);
4717 result
= enumprinters_level2(p
->mem_ctx
, session_info
,
4718 p
->msg_ctx
, r
->in
.flags
,
4720 r
->out
.info
, r
->out
.count
);
4723 result
= enumprinters_level4(p
->mem_ctx
, session_info
,
4724 p
->msg_ctx
, r
->in
.flags
,
4726 r
->out
.info
, r
->out
.count
);
4729 result
= enumprinters_level5(p
->mem_ctx
, session_info
,
4730 p
->msg_ctx
, r
->in
.flags
,
4732 r
->out
.info
, r
->out
.count
);
4735 return WERR_UNKNOWN_LEVEL
;
4738 if (!W_ERROR_IS_OK(result
)) {
4742 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4743 spoolss_EnumPrinters
,
4744 *r
->out
.info
, r
->in
.level
,
4746 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4747 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4749 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4752 /****************************************************************
4754 ****************************************************************/
4756 WERROR
_spoolss_GetPrinter(struct pipes_struct
*p
,
4757 struct spoolss_GetPrinter
*r
)
4759 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4760 struct spoolss_PrinterInfo2
*info2
= NULL
;
4761 WERROR result
= WERR_OK
;
4764 /* that's an [in out] buffer */
4766 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4767 return WERR_INVALID_PARAM
;
4772 if (Printer
== NULL
) {
4776 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4780 result
= winreg_get_printer_internal(p
->mem_ctx
,
4781 get_session_info_system(),
4783 lp_const_servicename(snum
),
4785 if (!W_ERROR_IS_OK(result
)) {
4789 switch (r
->in
.level
) {
4791 result
= construct_printer_info0(p
->mem_ctx
,
4792 get_session_info_system(),
4795 Printer
->servername
,
4796 &r
->out
.info
->info0
,
4800 result
= construct_printer_info1(p
->mem_ctx
, info2
,
4802 Printer
->servername
,
4803 &r
->out
.info
->info1
, snum
);
4806 result
= construct_printer_info2(p
->mem_ctx
, p
->msg_ctx
, info2
,
4807 Printer
->servername
,
4808 &r
->out
.info
->info2
, snum
);
4811 result
= construct_printer_info3(p
->mem_ctx
, info2
,
4812 Printer
->servername
,
4813 &r
->out
.info
->info3
, snum
);
4816 result
= construct_printer_info4(p
->mem_ctx
, info2
,
4817 Printer
->servername
,
4818 &r
->out
.info
->info4
, snum
);
4821 result
= construct_printer_info5(p
->mem_ctx
, info2
,
4822 Printer
->servername
,
4823 &r
->out
.info
->info5
, snum
);
4826 result
= construct_printer_info6(p
->mem_ctx
, p
->msg_ctx
, info2
,
4827 Printer
->servername
,
4828 &r
->out
.info
->info6
, snum
);
4831 result
= construct_printer_info7(p
->mem_ctx
, p
->msg_ctx
,
4832 Printer
->servername
,
4833 &r
->out
.info
->info7
, snum
);
4836 result
= construct_printer_info8(p
->mem_ctx
, info2
,
4837 Printer
->servername
,
4838 &r
->out
.info
->info8
, snum
);
4841 result
= WERR_UNKNOWN_LEVEL
;
4847 if (!W_ERROR_IS_OK(result
)) {
4848 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4849 r
->in
.level
, win_errstr(result
)));
4850 TALLOC_FREE(r
->out
.info
);
4854 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
,
4855 r
->out
.info
, r
->in
.level
);
4856 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4858 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4861 /********************************************************************
4862 ********************************************************************/
4864 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4866 if (in && strlen(in)) { \
4867 out = talloc_strdup(mem_ctx, in); \
4869 out = talloc_strdup(mem_ctx, ""); \
4871 W_ERROR_HAVE_NO_MEMORY(out); \
4874 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4876 if (in && strlen(in)) { \
4877 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4879 out = talloc_strdup(mem_ctx, ""); \
4881 W_ERROR_HAVE_NO_MEMORY(out); \
4884 static WERROR
string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4885 const char **string_array
,
4886 const char ***presult
,
4887 const char *cservername
,
4891 int i
, num_strings
= 0;
4892 const char **array
= NULL
;
4894 if (string_array
== NULL
) {
4895 return WERR_INVALID_PARAMETER
;
4898 for (i
=0; string_array
[i
] && string_array
[i
][0] != '\0'; i
++) {
4899 const char *str
= NULL
;
4901 if (cservername
== NULL
|| arch
== NULL
) {
4902 FILL_DRIVER_STRING(mem_ctx
, string_array
[i
], str
);
4904 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
, arch
, version
, string_array
[i
], str
);
4907 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4914 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4915 &array
, &num_strings
);
4918 if (presult
!= NULL
) {
4927 /********************************************************************
4928 * fill a spoolss_DriverInfo1 struct
4929 ********************************************************************/
4931 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4932 struct spoolss_DriverInfo1
*r
,
4933 const struct spoolss_DriverInfo8
*driver
,
4934 const char *servername
)
4936 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4937 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4942 /********************************************************************
4943 * fill a spoolss_DriverInfo2 struct
4944 ********************************************************************/
4946 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4947 struct spoolss_DriverInfo2
*r
,
4948 const struct spoolss_DriverInfo8
*driver
,
4949 const char *servername
)
4952 const char *cservername
= canon_servername(servername
);
4954 r
->version
= driver
->version
;
4956 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4957 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4958 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4959 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4961 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4962 driver
->architecture
,
4964 driver
->driver_path
,
4967 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4968 driver
->architecture
,
4973 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4974 driver
->architecture
,
4976 driver
->config_file
,
4982 /********************************************************************
4983 * fill a spoolss_DriverInfo3 struct
4984 ********************************************************************/
4986 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4987 struct spoolss_DriverInfo3
*r
,
4988 const struct spoolss_DriverInfo8
*driver
,
4989 const char *servername
)
4991 const char *cservername
= canon_servername(servername
);
4993 r
->version
= driver
->version
;
4995 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4996 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4997 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4998 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5000 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5001 driver
->architecture
,
5003 driver
->driver_path
,
5006 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5007 driver
->architecture
,
5012 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5013 driver
->architecture
,
5015 driver
->config_file
,
5018 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5019 driver
->architecture
,
5024 FILL_DRIVER_STRING(mem_ctx
,
5025 driver
->monitor_name
,
5028 FILL_DRIVER_STRING(mem_ctx
,
5029 driver
->default_datatype
,
5030 r
->default_datatype
);
5032 return string_array_from_driver_info(mem_ctx
,
5033 driver
->dependent_files
,
5034 &r
->dependent_files
,
5036 driver
->architecture
,
5040 /********************************************************************
5041 * fill a spoolss_DriverInfo4 struct
5042 ********************************************************************/
5044 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
5045 struct spoolss_DriverInfo4
*r
,
5046 const struct spoolss_DriverInfo8
*driver
,
5047 const char *servername
)
5049 const char *cservername
= canon_servername(servername
);
5052 r
->version
= driver
->version
;
5054 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5055 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5056 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5057 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5059 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5060 driver
->architecture
,
5062 driver
->driver_path
,
5065 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5066 driver
->architecture
,
5071 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5072 driver
->architecture
,
5074 driver
->config_file
,
5077 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5078 driver
->architecture
,
5083 result
= string_array_from_driver_info(mem_ctx
,
5084 driver
->dependent_files
,
5085 &r
->dependent_files
,
5087 driver
->architecture
,
5089 if (!W_ERROR_IS_OK(result
)) {
5093 FILL_DRIVER_STRING(mem_ctx
,
5094 driver
->monitor_name
,
5097 FILL_DRIVER_STRING(mem_ctx
,
5098 driver
->default_datatype
,
5099 r
->default_datatype
);
5102 result
= string_array_from_driver_info(mem_ctx
,
5103 driver
->previous_names
,
5110 /********************************************************************
5111 * fill a spoolss_DriverInfo5 struct
5112 ********************************************************************/
5114 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
5115 struct spoolss_DriverInfo5
*r
,
5116 const struct spoolss_DriverInfo8
*driver
,
5117 const char *servername
)
5119 const char *cservername
= canon_servername(servername
);
5121 r
->version
= driver
->version
;
5123 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5124 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5125 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5126 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5128 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5129 driver
->architecture
,
5131 driver
->driver_path
,
5134 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5135 driver
->architecture
,
5140 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5141 driver
->architecture
,
5143 driver
->config_file
,
5146 r
->driver_attributes
= 0;
5147 r
->config_version
= 0;
5148 r
->driver_version
= 0;
5152 /********************************************************************
5153 * fill a spoolss_DriverInfo6 struct
5154 ********************************************************************/
5156 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
5157 struct spoolss_DriverInfo6
*r
,
5158 const struct spoolss_DriverInfo8
*driver
,
5159 const char *servername
)
5161 const char *cservername
= canon_servername(servername
);
5164 r
->version
= driver
->version
;
5166 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5167 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5168 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5169 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5171 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5172 driver
->architecture
,
5174 driver
->driver_path
,
5177 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5178 driver
->architecture
,
5183 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5184 driver
->architecture
,
5186 driver
->config_file
,
5189 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5190 driver
->architecture
,
5195 FILL_DRIVER_STRING(mem_ctx
,
5196 driver
->monitor_name
,
5199 FILL_DRIVER_STRING(mem_ctx
,
5200 driver
->default_datatype
,
5201 r
->default_datatype
);
5203 result
= string_array_from_driver_info(mem_ctx
,
5204 driver
->dependent_files
,
5205 &r
->dependent_files
,
5207 driver
->architecture
,
5209 if (!W_ERROR_IS_OK(result
)) {
5213 result
= string_array_from_driver_info(mem_ctx
,
5214 driver
->previous_names
,
5217 if (!W_ERROR_IS_OK(result
)) {
5221 r
->driver_date
= driver
->driver_date
;
5222 r
->driver_version
= driver
->driver_version
;
5224 FILL_DRIVER_STRING(mem_ctx
,
5225 driver
->manufacturer_name
,
5226 r
->manufacturer_name
);
5227 FILL_DRIVER_STRING(mem_ctx
,
5228 driver
->manufacturer_url
,
5229 r
->manufacturer_url
);
5230 FILL_DRIVER_STRING(mem_ctx
,
5231 driver
->hardware_id
,
5233 FILL_DRIVER_STRING(mem_ctx
,
5240 /********************************************************************
5241 * fill a spoolss_DriverInfo8 struct
5242 ********************************************************************/
5244 static WERROR
fill_printer_driver_info8(TALLOC_CTX
*mem_ctx
,
5245 struct spoolss_DriverInfo8
*r
,
5246 const struct spoolss_DriverInfo8
*driver
,
5247 const char *servername
)
5249 const char *cservername
= canon_servername(servername
);
5252 r
->version
= driver
->version
;
5254 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5255 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5256 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5257 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5259 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5260 driver
->architecture
,
5262 driver
->driver_path
,
5265 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5266 driver
->architecture
,
5271 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5272 driver
->architecture
,
5274 driver
->config_file
,
5277 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5278 driver
->architecture
,
5283 FILL_DRIVER_STRING(mem_ctx
,
5284 driver
->monitor_name
,
5287 FILL_DRIVER_STRING(mem_ctx
,
5288 driver
->default_datatype
,
5289 r
->default_datatype
);
5291 result
= string_array_from_driver_info(mem_ctx
,
5292 driver
->dependent_files
,
5293 &r
->dependent_files
,
5295 driver
->architecture
,
5297 if (!W_ERROR_IS_OK(result
)) {
5301 result
= string_array_from_driver_info(mem_ctx
,
5302 driver
->previous_names
,
5305 if (!W_ERROR_IS_OK(result
)) {
5309 r
->driver_date
= driver
->driver_date
;
5310 r
->driver_version
= driver
->driver_version
;
5312 FILL_DRIVER_STRING(mem_ctx
,
5313 driver
->manufacturer_name
,
5314 r
->manufacturer_name
);
5315 FILL_DRIVER_STRING(mem_ctx
,
5316 driver
->manufacturer_url
,
5317 r
->manufacturer_url
);
5318 FILL_DRIVER_STRING(mem_ctx
,
5319 driver
->hardware_id
,
5321 FILL_DRIVER_STRING(mem_ctx
,
5325 FILL_DRIVER_STRING(mem_ctx
,
5326 driver
->print_processor
,
5327 r
->print_processor
);
5328 FILL_DRIVER_STRING(mem_ctx
,
5329 driver
->vendor_setup
,
5332 result
= string_array_from_driver_info(mem_ctx
,
5333 driver
->color_profiles
,
5336 if (!W_ERROR_IS_OK(result
)) {
5340 FILL_DRIVER_STRING(mem_ctx
,
5344 r
->printer_driver_attributes
= driver
->printer_driver_attributes
;
5346 result
= string_array_from_driver_info(mem_ctx
,
5347 driver
->core_driver_dependencies
,
5348 &r
->core_driver_dependencies
,
5350 if (!W_ERROR_IS_OK(result
)) {
5354 r
->min_inbox_driver_ver_date
= driver
->min_inbox_driver_ver_date
;
5355 r
->min_inbox_driver_ver_version
= driver
->min_inbox_driver_ver_version
;
5360 #if 0 /* disabled until marshalling issues are resolved - gd */
5361 /********************************************************************
5362 ********************************************************************/
5364 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
5365 struct spoolss_DriverFileInfo
*r
,
5366 const char *cservername
,
5367 const char *file_name
,
5368 enum spoolss_DriverFileType file_type
,
5369 uint32_t file_version
)
5371 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
5372 cservername
, file_name
);
5373 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
5374 r
->file_type
= file_type
;
5375 r
->file_version
= file_version
;
5380 /********************************************************************
5381 ********************************************************************/
5383 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
5384 const struct spoolss_DriverInfo8
*driver
,
5385 const char *cservername
,
5386 struct spoolss_DriverFileInfo
**info_p
,
5389 struct spoolss_DriverFileInfo
*info
= NULL
;
5397 if (strlen(driver
->driver_path
)) {
5398 info
= talloc_realloc(mem_ctx
, info
,
5399 struct spoolss_DriverFileInfo
,
5401 W_ERROR_HAVE_NO_MEMORY(info
);
5402 result
= fill_spoolss_DriverFileInfo(info
,
5405 driver
->driver_path
,
5406 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
5408 W_ERROR_NOT_OK_RETURN(result
);
5412 if (strlen(driver
->config_file
)) {
5413 info
= talloc_realloc(mem_ctx
, info
,
5414 struct spoolss_DriverFileInfo
,
5416 W_ERROR_HAVE_NO_MEMORY(info
);
5417 result
= fill_spoolss_DriverFileInfo(info
,
5420 driver
->config_file
,
5421 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
5423 W_ERROR_NOT_OK_RETURN(result
);
5427 if (strlen(driver
->data_file
)) {
5428 info
= talloc_realloc(mem_ctx
, info
,
5429 struct spoolss_DriverFileInfo
,
5431 W_ERROR_HAVE_NO_MEMORY(info
);
5432 result
= fill_spoolss_DriverFileInfo(info
,
5436 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
5438 W_ERROR_NOT_OK_RETURN(result
);
5442 if (strlen(driver
->help_file
)) {
5443 info
= talloc_realloc(mem_ctx
, info
,
5444 struct spoolss_DriverFileInfo
,
5446 W_ERROR_HAVE_NO_MEMORY(info
);
5447 result
= fill_spoolss_DriverFileInfo(info
,
5451 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
5453 W_ERROR_NOT_OK_RETURN(result
);
5457 for (i
=0; driver
->dependent_files
[i
] && driver
->dependent_files
[i
][0] != '\0'; i
++) {
5458 info
= talloc_realloc(mem_ctx
, info
,
5459 struct spoolss_DriverFileInfo
,
5461 W_ERROR_HAVE_NO_MEMORY(info
);
5462 result
= fill_spoolss_DriverFileInfo(info
,
5465 driver
->dependent_files
[i
],
5466 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
5468 W_ERROR_NOT_OK_RETURN(result
);
5478 /********************************************************************
5479 * fill a spoolss_DriverInfo101 struct
5480 ********************************************************************/
5482 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
5483 struct spoolss_DriverInfo101
*r
,
5484 const struct spoolss_DriverInfo8
*driver
,
5485 const char *servername
)
5487 const char *cservername
= canon_servername(servername
);
5490 r
->version
= driver
->version
;
5492 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5493 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5494 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5495 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5497 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
5501 if (!W_ERROR_IS_OK(result
)) {
5505 FILL_DRIVER_STRING(mem_ctx
,
5506 driver
->monitor_name
,
5509 FILL_DRIVER_STRING(mem_ctx
,
5510 driver
->default_datatype
,
5511 r
->default_datatype
);
5513 result
= string_array_from_driver_info(mem_ctx
,
5514 driver
->previous_names
,
5517 if (!W_ERROR_IS_OK(result
)) {
5521 r
->driver_date
= driver
->driver_date
;
5522 r
->driver_version
= driver
->driver_version
;
5524 FILL_DRIVER_STRING(mem_ctx
,
5525 driver
->manufacturer_name
,
5526 r
->manufacturer_name
);
5527 FILL_DRIVER_STRING(mem_ctx
,
5528 driver
->manufacturer_url
,
5529 r
->manufacturer_url
);
5530 FILL_DRIVER_STRING(mem_ctx
,
5531 driver
->hardware_id
,
5533 FILL_DRIVER_STRING(mem_ctx
,
5540 /********************************************************************
5541 ********************************************************************/
5543 static WERROR
construct_printer_driver_info_level(TALLOC_CTX
*mem_ctx
,
5544 const struct auth_session_info
*session_info
,
5545 struct messaging_context
*msg_ctx
,
5547 union spoolss_DriverInfo
*r
,
5549 const char *servername
,
5550 const char *architecture
,
5553 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
5554 struct spoolss_DriverInfo8
*driver
;
5556 struct dcerpc_binding_handle
*b
;
5557 TALLOC_CTX
*tmp_ctx
= NULL
;
5560 return WERR_UNKNOWN_LEVEL
;
5563 tmp_ctx
= talloc_new(mem_ctx
);
5568 result
= winreg_printer_binding_handle(tmp_ctx
,
5572 if (!W_ERROR_IS_OK(result
)) {
5576 result
= winreg_get_printer(tmp_ctx
, b
,
5577 lp_const_servicename(snum
),
5580 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5581 win_errstr(result
)));
5583 if (!W_ERROR_IS_OK(result
)) {
5584 result
= WERR_INVALID_PRINTER_NAME
;
5588 result
= winreg_get_driver(tmp_ctx
, b
,
5590 pinfo2
->drivername
, version
, &driver
);
5592 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5593 win_errstr(result
)));
5595 if (!W_ERROR_IS_OK(result
)) {
5597 * Is this a W2k client ?
5601 result
= WERR_UNKNOWN_PRINTER_DRIVER
;
5605 /* Yes - try again with a WinNT driver. */
5607 result
= winreg_get_driver(tmp_ctx
, b
,
5611 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5612 win_errstr(result
)));
5613 if (!W_ERROR_IS_OK(result
)) {
5614 result
= WERR_UNKNOWN_PRINTER_DRIVER
;
5619 /* these are allocated on mem_ctx and not tmp_ctx because they are
5620 * the 'return value' and need to utlive this call */
5623 result
= fill_printer_driver_info1(mem_ctx
, &r
->info1
, driver
, servername
);
5626 result
= fill_printer_driver_info2(mem_ctx
, &r
->info2
, driver
, servername
);
5629 result
= fill_printer_driver_info3(mem_ctx
, &r
->info3
, driver
, servername
);
5632 result
= fill_printer_driver_info4(mem_ctx
, &r
->info4
, driver
, servername
);
5635 result
= fill_printer_driver_info5(mem_ctx
, &r
->info5
, driver
, servername
);
5638 result
= fill_printer_driver_info6(mem_ctx
, &r
->info6
, driver
, servername
);
5641 result
= fill_printer_driver_info8(mem_ctx
, &r
->info8
, driver
, servername
);
5643 #if 0 /* disabled until marshalling issues are resolved - gd */
5645 result
= fill_printer_driver_info101(mem_ctx
, &r
->info101
, driver
, servername
);
5649 result
= WERR_UNKNOWN_LEVEL
;
5654 talloc_free(tmp_ctx
);
5658 /****************************************************************
5659 _spoolss_GetPrinterDriver2
5660 ****************************************************************/
5662 WERROR
_spoolss_GetPrinterDriver2(struct pipes_struct
*p
,
5663 struct spoolss_GetPrinterDriver2
*r
)
5665 struct printer_handle
*printer
;
5667 uint32_t version
= r
->in
.client_major_version
;
5671 /* that's an [in out] buffer */
5673 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5674 return WERR_INVALID_PARAM
;
5677 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5679 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5680 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5681 return WERR_INVALID_PRINTER_NAME
;
5685 *r
->out
.server_major_version
= 0;
5686 *r
->out
.server_minor_version
= 0;
5688 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5692 if (r
->in
.client_major_version
== SPOOLSS_DRIVER_VERSION_2012
) {
5693 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5694 "downgrading to v3\n"));
5695 version
= SPOOLSS_DRIVER_VERSION_200X
;
5698 result
= construct_printer_driver_info_level(p
->mem_ctx
,
5699 get_session_info_system(),
5701 r
->in
.level
, r
->out
.info
,
5702 snum
, printer
->servername
,
5705 if (!W_ERROR_IS_OK(result
)) {
5706 TALLOC_FREE(r
->out
.info
);
5710 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
,
5711 r
->out
.info
, r
->in
.level
);
5712 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5714 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5718 /****************************************************************
5719 _spoolss_StartPagePrinter
5720 ****************************************************************/
5722 WERROR
_spoolss_StartPagePrinter(struct pipes_struct
*p
,
5723 struct spoolss_StartPagePrinter
*r
)
5725 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5728 DEBUG(3,("_spoolss_StartPagePrinter: "
5729 "Error in startpageprinter printer handle\n"));
5733 Printer
->page_started
= true;
5737 /****************************************************************
5738 _spoolss_EndPagePrinter
5739 ****************************************************************/
5741 WERROR
_spoolss_EndPagePrinter(struct pipes_struct
*p
,
5742 struct spoolss_EndPagePrinter
*r
)
5746 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5749 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5750 OUR_HANDLE(r
->in
.handle
)));
5754 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5757 Printer
->page_started
= false;
5758 print_job_endpage(p
->msg_ctx
, snum
, Printer
->jobid
);
5763 /****************************************************************
5764 _spoolss_StartDocPrinter
5765 ****************************************************************/
5767 WERROR
_spoolss_StartDocPrinter(struct pipes_struct
*p
,
5768 struct spoolss_StartDocPrinter
*r
)
5770 struct spoolss_DocumentInfo1
*info_1
;
5772 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5778 DEBUG(2,("_spoolss_StartDocPrinter: "
5779 "Invalid handle (%s:%u:%u)\n",
5780 OUR_HANDLE(r
->in
.handle
)));
5784 if (Printer
->jobid
) {
5785 DEBUG(2, ("_spoolss_StartDocPrinter: "
5786 "StartDocPrinter called twice! "
5787 "(existing jobid = %d)\n", Printer
->jobid
));
5788 return WERR_INVALID_HANDLE
;
5791 if (r
->in
.info_ctr
->level
!= 1) {
5792 return WERR_UNKNOWN_LEVEL
;
5795 info_1
= r
->in
.info_ctr
->info
.info1
;
5798 * a nice thing with NT is it doesn't listen to what you tell it.
5799 * when asked to send _only_ RAW datas, it tries to send datas
5802 * So I add checks like in NT Server ...
5805 if (info_1
->datatype
) {
5807 * The v4 driver model used in Windows 8 declares print jobs
5808 * intended to bypass the XPS processing layer by setting
5809 * datatype to "XPS_PASS" instead of "RAW".
5811 if ((strcmp(info_1
->datatype
, "RAW") != 0)
5812 && (strcmp(info_1
->datatype
, "XPS_PASS") != 0)) {
5814 return WERR_INVALID_DATATYPE
;
5818 /* get the share number of the printer */
5819 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5823 rc
= get_remote_hostname(p
->remote_address
,
5829 if (strequal(rhost
,"UNKNOWN")) {
5830 rhost
= tsocket_address_inet_addr_string(p
->remote_address
,
5832 if (rhost
== NULL
) {
5837 werr
= print_job_start(p
->session_info
,
5841 info_1
->document_name
,
5842 info_1
->output_file
,
5846 /* An error occured in print_job_start() so return an appropriate
5849 if (!W_ERROR_IS_OK(werr
)) {
5853 Printer
->document_started
= true;
5854 *r
->out
.job_id
= Printer
->jobid
;
5859 /****************************************************************
5860 _spoolss_EndDocPrinter
5861 ****************************************************************/
5863 WERROR
_spoolss_EndDocPrinter(struct pipes_struct
*p
,
5864 struct spoolss_EndDocPrinter
*r
)
5866 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5871 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5872 OUR_HANDLE(r
->in
.handle
)));
5876 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5880 Printer
->document_started
= false;
5881 status
= print_job_end(p
->msg_ctx
, snum
, Printer
->jobid
, NORMAL_CLOSE
);
5882 if (!NT_STATUS_IS_OK(status
)) {
5883 DEBUG(2, ("_spoolss_EndDocPrinter: "
5884 "print_job_end failed [%s]\n",
5885 nt_errstr(status
)));
5889 return ntstatus_to_werror(status
);
5892 /****************************************************************
5893 _spoolss_WritePrinter
5894 ****************************************************************/
5896 WERROR
_spoolss_WritePrinter(struct pipes_struct
*p
,
5897 struct spoolss_WritePrinter
*r
)
5899 ssize_t buffer_written
;
5901 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5904 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5905 OUR_HANDLE(r
->in
.handle
)));
5906 *r
->out
.num_written
= r
->in
._data_size
;
5910 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5913 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5914 buffer_written
= print_job_write(server_event_context(),p
->msg_ctx
,
5915 snum
, Printer
->jobid
,
5916 (const char *)r
->in
.data
.data
,
5917 (size_t)r
->in
._data_size
);
5918 if (buffer_written
== (ssize_t
)-1) {
5919 *r
->out
.num_written
= 0;
5920 if (errno
== ENOSPC
)
5921 return WERR_NO_SPOOL_SPACE
;
5923 return WERR_ACCESS_DENIED
;
5926 *r
->out
.num_written
= r
->in
._data_size
;
5931 /********************************************************************
5932 * api_spoolss_getprinter
5933 * called from the spoolss dispatcher
5935 ********************************************************************/
5937 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5938 struct pipes_struct
*p
)
5940 const struct auth_session_info
*session_info
= p
->session_info
;
5942 WERROR errcode
= WERR_BADFUNC
;
5943 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
5946 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5947 OUR_HANDLE(handle
)));
5951 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5955 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5956 errcode
= print_queue_pause(session_info
, p
->msg_ctx
, snum
);
5958 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5959 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5960 errcode
= print_queue_resume(session_info
, p
->msg_ctx
, snum
);
5962 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5963 errcode
= print_queue_purge(session_info
, p
->msg_ctx
, snum
);
5966 return WERR_UNKNOWN_LEVEL
;
5973 /****************************************************************
5974 _spoolss_AbortPrinter
5975 * From MSDN: "Deletes printer's spool file if printer is configured
5977 ****************************************************************/
5979 WERROR
_spoolss_AbortPrinter(struct pipes_struct
*p
,
5980 struct spoolss_AbortPrinter
*r
)
5982 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5984 WERROR errcode
= WERR_OK
;
5987 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5988 OUR_HANDLE(r
->in
.handle
)));
5992 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5995 if (!Printer
->document_started
) {
5996 return WERR_SPL_NO_STARTDOC
;
5999 errcode
= print_job_delete(p
->session_info
,
6007 /********************************************************************
6008 * called by spoolss_api_setprinter
6009 * when updating a printer description
6010 ********************************************************************/
6012 static WERROR
update_printer_sec(struct policy_handle
*handle
,
6013 struct pipes_struct
*p
,
6014 struct sec_desc_buf
*secdesc_ctr
)
6016 struct spoolss_security_descriptor
*new_secdesc
= NULL
;
6017 struct spoolss_security_descriptor
*old_secdesc
= NULL
;
6018 const char *printer
;
6021 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6022 struct dcerpc_binding_handle
*b
;
6023 TALLOC_CTX
*tmp_ctx
= NULL
;
6025 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
6026 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6027 OUR_HANDLE(handle
)));
6029 result
= WERR_BADFID
;
6033 if (secdesc_ctr
== NULL
) {
6034 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6035 result
= WERR_INVALID_PARAM
;
6038 printer
= lp_const_servicename(snum
);
6040 /* Check the user has permissions to change the security
6041 descriptor. By experimentation with two NT machines, the user
6042 requires Full Access to the printer to change security
6045 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6046 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6047 result
= WERR_ACCESS_DENIED
;
6051 tmp_ctx
= talloc_new(p
->mem_ctx
);
6056 result
= winreg_printer_binding_handle(tmp_ctx
,
6057 get_session_info_system(),
6060 if (!W_ERROR_IS_OK(result
)) {
6064 /* NT seems to like setting the security descriptor even though
6065 nothing may have actually changed. */
6066 result
= winreg_get_printer_secdesc(tmp_ctx
, b
,
6069 if (!W_ERROR_IS_OK(result
)) {
6070 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6071 result
= WERR_BADFID
;
6075 if (DEBUGLEVEL
>= 10) {
6076 struct security_acl
*the_acl
;
6079 the_acl
= old_secdesc
->dacl
;
6080 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6081 printer
, the_acl
->num_aces
));
6083 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6084 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6085 &the_acl
->aces
[i
].trustee
),
6086 the_acl
->aces
[i
].access_mask
));
6089 the_acl
= secdesc_ctr
->sd
->dacl
;
6092 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6093 printer
, the_acl
->num_aces
));
6095 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6096 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6097 &the_acl
->aces
[i
].trustee
),
6098 the_acl
->aces
[i
].access_mask
));
6101 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6105 new_secdesc
= sec_desc_merge(tmp_ctx
, secdesc_ctr
->sd
, old_secdesc
);
6106 if (new_secdesc
== NULL
) {
6107 result
= WERR_NOMEM
;
6111 if (security_descriptor_equal(new_secdesc
, old_secdesc
)) {
6116 result
= winreg_set_printer_secdesc(tmp_ctx
, b
,
6121 talloc_free(tmp_ctx
);
6125 /********************************************************************
6126 Canonicalize printer info from a client
6127 ********************************************************************/
6129 static bool check_printer_ok(TALLOC_CTX
*mem_ctx
,
6130 struct spoolss_SetPrinterInfo2
*info2
,
6133 fstring printername
;
6136 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6137 "portname=%s drivername=%s comment=%s location=%s\n",
6138 info2
->servername
, info2
->printername
, info2
->sharename
,
6139 info2
->portname
, info2
->drivername
, info2
->comment
,
6142 /* we force some elements to "correct" values */
6143 info2
->servername
= talloc_asprintf(mem_ctx
, "\\\\%s", lp_netbios_name());
6144 if (info2
->servername
== NULL
) {
6147 info2
->sharename
= talloc_strdup(mem_ctx
, lp_const_servicename(snum
));
6148 if (info2
->sharename
== NULL
) {
6152 /* check to see if we allow printername != sharename */
6153 if (lp_force_printername(snum
)) {
6154 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6155 lp_netbios_name(), info2
->sharename
);
6157 /* make sure printername is in \\server\printername format */
6158 fstrcpy(printername
, info2
->printername
);
6160 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
6161 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
6165 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6166 lp_netbios_name(), p
);
6168 if (info2
->printername
== NULL
) {
6172 info2
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
6173 info2
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
6178 /****************************************************************************
6179 ****************************************************************************/
6181 static WERROR
add_port_hook(TALLOC_CTX
*ctx
, struct security_token
*token
, const char *portname
, const char *uri
)
6183 char *cmd
= lp_addport_command(talloc_tos());
6184 char *command
= NULL
;
6186 bool is_print_op
= false;
6189 return WERR_ACCESS_DENIED
;
6192 command
= talloc_asprintf(ctx
,
6193 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
6199 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
6201 DEBUG(10,("Running [%s]\n", command
));
6203 /********* BEGIN SePrintOperatorPrivilege **********/
6208 ret
= smbrun(command
, NULL
);
6213 /********* END SePrintOperatorPrivilege **********/
6215 DEBUGADD(10,("returned [%d]\n", ret
));
6217 TALLOC_FREE(command
);
6220 return WERR_ACCESS_DENIED
;
6226 /****************************************************************************
6227 ****************************************************************************/
6229 static bool spoolss_conn_snum_used(struct smbd_server_connection
*sconn
,
6233 * As we do not know if we are embedded in the file server process
6234 * or not, we have to pretend that all shares are in use.
6239 static bool add_printer_hook(TALLOC_CTX
*ctx
, struct security_token
*token
,
6240 struct spoolss_SetPrinterInfo2
*info2
,
6241 const char *remote_machine
,
6242 struct messaging_context
*msg_ctx
)
6244 char *cmd
= lp_addprinter_command(talloc_tos());
6246 char *command
= NULL
;
6250 bool is_print_op
= false;
6252 if (!remote_machine
) {
6256 command
= talloc_asprintf(ctx
,
6257 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6258 cmd
, info2
->printername
, info2
->sharename
,
6259 info2
->portname
, info2
->drivername
,
6260 info2
->location
, info2
->comment
, remote_machine
);
6266 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
6268 DEBUG(10,("Running [%s]\n", command
));
6270 /********* BEGIN SePrintOperatorPrivilege **********/
6275 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6276 /* Tell everyone we updated smb.conf. */
6277 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
6283 /********* END SePrintOperatorPrivilege **********/
6285 DEBUGADD(10,("returned [%d]\n", ret
));
6287 TALLOC_FREE(command
);
6295 /* reload our services immediately */
6297 reload_services(NULL
, spoolss_conn_snum_used
, false);
6301 /* Get lines and convert them back to dos-codepage */
6302 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
6303 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6306 /* Set the portname to what the script says the portname should be. */
6307 /* but don't require anything to be return from the script exit a good error code */
6310 /* Set the portname to what the script says the portname should be. */
6311 info2
->portname
= talloc_strdup(ctx
, qlines
[0]);
6312 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6315 TALLOC_FREE(qlines
);
6319 static WERROR
update_dsspooler(TALLOC_CTX
*mem_ctx
,
6320 const struct auth_session_info
*session_info
,
6321 struct messaging_context
*msg_ctx
,
6323 struct spoolss_SetPrinterInfo2
*printer
,
6324 struct spoolss_PrinterInfo2
*old_printer
)
6326 bool force_update
= (old_printer
== NULL
);
6327 const char *dnsdomname
;
6328 const char *longname
;
6329 const char *uncname
;
6330 const char *spooling
;
6332 WERROR result
= WERR_OK
;
6333 struct dcerpc_binding_handle
*b
;
6334 TALLOC_CTX
*tmp_ctx
;
6337 tmp_ctx
= talloc_new(mem_ctx
);
6342 result
= winreg_printer_binding_handle(tmp_ctx
,
6346 if (!W_ERROR_IS_OK(result
)) {
6350 if (printer
->drivername
!= NULL
&&
6352 !strequal(printer
->drivername
, old_printer
->drivername
))) {
6353 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->drivername
);
6355 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME
));
6356 result
= WERR_INVALID_DATA
;
6359 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6361 SPOOL_DSSPOOLER_KEY
,
6362 SPOOL_REG_DRIVERNAME
,
6366 if (!W_ERROR_IS_OK(result
)) {
6367 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME
));
6371 if (!force_update
) {
6372 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6373 printer
->drivername
));
6375 notify_printer_driver(server_event_context(), msg_ctx
,
6376 snum
, printer
->drivername
?
6377 printer
->drivername
: "");
6381 if (printer
->comment
!= NULL
&&
6383 !strequal(printer
->comment
, old_printer
->comment
))) {
6384 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->comment
);
6386 DEBUG(0, ("comment data corrupted\n"));
6387 result
= WERR_INVALID_DATA
;
6390 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6392 SPOOL_DSSPOOLER_KEY
,
6393 SPOOL_REG_DESCRIPTION
,
6397 if (!W_ERROR_IS_OK(result
)) {
6398 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION
));
6402 if (!force_update
) {
6403 notify_printer_comment(server_event_context(), msg_ctx
,
6404 snum
, printer
->comment
?
6405 printer
->comment
: "");
6409 if (printer
->sharename
!= NULL
&&
6411 !strequal(printer
->sharename
, old_printer
->sharename
))) {
6412 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->sharename
);
6414 DEBUG(0, ("sharename data corrupted\n"));
6415 result
= WERR_INVALID_DATA
;
6418 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6420 SPOOL_DSSPOOLER_KEY
,
6421 SPOOL_REG_PRINTSHARENAME
,
6425 if (!W_ERROR_IS_OK(result
)) {
6426 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME
));
6430 if (!force_update
) {
6431 notify_printer_sharename(server_event_context(),
6433 snum
, printer
->sharename
?
6434 printer
->sharename
: "");
6438 if (printer
->printername
!= NULL
&&
6440 !strequal(printer
->printername
, old_printer
->printername
))) {
6443 p
= strrchr(printer
->printername
, '\\' );
6447 p
= printer
->printername
;
6450 ok
= push_reg_sz(tmp_ctx
, &buffer
, p
);
6452 DEBUG(0, ("printername data corrupted\n"));
6453 result
= WERR_INVALID_DATA
;
6456 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6458 SPOOL_DSSPOOLER_KEY
,
6459 SPOOL_REG_PRINTERNAME
,
6463 if (!W_ERROR_IS_OK(result
)) {
6464 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME
));
6468 if (!force_update
) {
6469 notify_printer_printername(server_event_context(),
6470 msg_ctx
, snum
, p
? p
: "");
6474 if (printer
->portname
!= NULL
&&
6476 !strequal(printer
->portname
, old_printer
->portname
))) {
6477 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->portname
);
6479 DEBUG(0, ("portname data corrupted\n"));
6480 result
= WERR_INVALID_DATA
;
6483 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6485 SPOOL_DSSPOOLER_KEY
,
6490 if (!W_ERROR_IS_OK(result
)) {
6491 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME
));
6495 if (!force_update
) {
6496 notify_printer_port(server_event_context(),
6497 msg_ctx
, snum
, printer
->portname
?
6498 printer
->portname
: "");
6502 if (printer
->location
!= NULL
&&
6504 !strequal(printer
->location
, old_printer
->location
))) {
6505 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->location
);
6507 DEBUG(0, ("location data corrupted\n"));
6508 result
= WERR_INVALID_DATA
;
6511 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6513 SPOOL_DSSPOOLER_KEY
,
6518 if (!W_ERROR_IS_OK(result
)) {
6519 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION
));
6523 if (!force_update
) {
6524 notify_printer_location(server_event_context(),
6527 printer
->location
: "");
6531 if (printer
->sepfile
!= NULL
&&
6533 !strequal(printer
->sepfile
, old_printer
->sepfile
))) {
6534 ok
= push_reg_sz(tmp_ctx
, &buffer
, printer
->sepfile
);
6536 DEBUG(0, ("sepfile data corrupted\n"));
6537 result
= WERR_INVALID_DATA
;
6540 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6542 SPOOL_DSSPOOLER_KEY
,
6543 SPOOL_REG_PRINTSEPARATORFILE
,
6547 if (!W_ERROR_IS_OK(result
)) {
6548 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE
));
6552 if (!force_update
) {
6553 notify_printer_sepfile(server_event_context(),
6556 printer
->sepfile
: "");
6560 if (printer
->starttime
!= 0 &&
6562 printer
->starttime
!= old_printer
->starttime
)) {
6563 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6564 SIVAL(buffer
.data
, 0, printer
->starttime
);
6565 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6567 SPOOL_DSSPOOLER_KEY
,
6568 SPOOL_REG_PRINTSTARTTIME
,
6572 if (!W_ERROR_IS_OK(result
)) {
6573 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME
));
6578 if (printer
->untiltime
!= 0 &&
6580 printer
->untiltime
!= old_printer
->untiltime
)) {
6581 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6582 SIVAL(buffer
.data
, 0, printer
->untiltime
);
6583 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6585 SPOOL_DSSPOOLER_KEY
,
6586 SPOOL_REG_PRINTENDTIME
,
6590 if (!W_ERROR_IS_OK(result
)) {
6591 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME
));
6596 if (force_update
|| printer
->priority
!= old_printer
->priority
) {
6597 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6598 SIVAL(buffer
.data
, 0, printer
->priority
);
6599 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6601 SPOOL_DSSPOOLER_KEY
,
6606 if (!W_ERROR_IS_OK(result
)) {
6607 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME
));
6612 if (force_update
|| printer
->attributes
!= old_printer
->attributes
) {
6613 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6614 SIVAL(buffer
.data
, 0, (printer
->attributes
&
6615 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
6616 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6618 SPOOL_DSSPOOLER_KEY
,
6619 SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
6623 if (!W_ERROR_IS_OK(result
)) {
6624 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME
));
6628 switch (printer
->attributes
& 0x3) {
6630 spooling
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
6633 spooling
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
6636 spooling
= SPOOL_REGVAL_PRINTDIRECT
;
6639 spooling
= "unknown";
6641 ok
= push_reg_sz(tmp_ctx
, &buffer
, spooling
);
6643 DEBUG(0, ("printSpooling data corrupted\n"));
6644 result
= WERR_INVALID_DATA
;
6647 winreg_set_printer_dataex(tmp_ctx
, b
,
6649 SPOOL_DSSPOOLER_KEY
,
6650 SPOOL_REG_PRINTSPOOLING
,
6656 ok
= push_reg_sz(tmp_ctx
, &buffer
, lp_netbios_name());
6658 DEBUG(0, ("shortServerName data corrupted\n"));
6659 result
= WERR_INVALID_DATA
;
6662 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6664 SPOOL_DSSPOOLER_KEY
,
6665 SPOOL_REG_SHORTSERVERNAME
,
6669 if (!W_ERROR_IS_OK(result
)) {
6670 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME
));
6674 dnsdomname
= get_mydnsfullname();
6675 if (dnsdomname
!= NULL
&& dnsdomname
[0] != '\0') {
6676 longname
= talloc_strdup(tmp_ctx
, dnsdomname
);
6678 longname
= talloc_strdup(tmp_ctx
, lp_netbios_name());
6680 if (longname
== NULL
) {
6681 result
= WERR_NOMEM
;
6685 ok
= push_reg_sz(tmp_ctx
, &buffer
, longname
);
6687 DEBUG(0, ("longname data corrupted\n"));
6688 result
= WERR_INVALID_DATA
;
6691 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6693 SPOOL_DSSPOOLER_KEY
,
6694 SPOOL_REG_SERVERNAME
,
6698 if (!W_ERROR_IS_OK(result
)) {
6699 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME
));
6703 uncname
= talloc_asprintf(tmp_ctx
, "\\\\%s\\%s",
6704 lp_netbios_name(), printer
->sharename
);
6705 ok
= push_reg_sz(tmp_ctx
, &buffer
, uncname
);
6707 DEBUG(0, ("uncName data corrupted\n"));
6708 result
= WERR_INVALID_DATA
;
6711 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
6713 SPOOL_DSSPOOLER_KEY
,
6718 if (!W_ERROR_IS_OK(result
)) {
6719 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME
));
6724 talloc_free(tmp_ctx
);
6728 /********************************************************************
6729 * Called by spoolss_api_setprinter
6730 * when updating a printer description.
6731 ********************************************************************/
6733 static WERROR
update_printer(struct pipes_struct
*p
,
6734 struct policy_handle
*handle
,
6735 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
6736 struct spoolss_DeviceMode
*devmode
)
6738 uint32_t printer_mask
= SPOOLSS_PRINTER_INFO_ALL
;
6739 struct spoolss_SetPrinterInfo2
*printer
= info_ctr
->info
.info2
;
6740 struct spoolss_PrinterInfo2
*old_printer
;
6741 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6743 WERROR result
= WERR_OK
;
6744 TALLOC_CTX
*tmp_ctx
;
6745 struct dcerpc_binding_handle
*b
;
6747 DEBUG(8,("update_printer\n"));
6749 tmp_ctx
= talloc_new(p
->mem_ctx
);
6750 if (tmp_ctx
== NULL
) {
6755 result
= WERR_BADFID
;
6759 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6760 result
= WERR_BADFID
;
6764 result
= winreg_printer_binding_handle(tmp_ctx
,
6765 get_session_info_system(),
6768 if (!W_ERROR_IS_OK(result
)) {
6772 result
= winreg_get_printer(tmp_ctx
, b
,
6773 lp_const_servicename(snum
),
6775 if (!W_ERROR_IS_OK(result
)) {
6776 result
= WERR_BADFID
;
6780 /* Do sanity check on the requested changes for Samba */
6781 if (!check_printer_ok(tmp_ctx
, printer
, snum
)) {
6782 result
= WERR_INVALID_PARAM
;
6786 /* FIXME!!! If the driver has changed we really should verify that
6787 it is installed before doing much else --jerry */
6789 /* Check calling user has permission to update printer description */
6790 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6791 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6792 result
= WERR_ACCESS_DENIED
;
6796 /* Call addprinter hook */
6797 /* Check changes to see if this is really needed */
6799 if (*lp_addprinter_command(talloc_tos()) &&
6800 (!strequal(printer
->drivername
, old_printer
->drivername
) ||
6801 !strequal(printer
->comment
, old_printer
->comment
) ||
6802 !strequal(printer
->portname
, old_printer
->portname
) ||
6803 !strequal(printer
->location
, old_printer
->location
)) )
6807 raddr
= tsocket_address_inet_addr_string(p
->remote_address
,
6809 if (raddr
== NULL
) {
6813 /* add_printer_hook() will call reload_services() */
6814 if (!add_printer_hook(tmp_ctx
, p
->session_info
->security_token
,
6817 result
= WERR_ACCESS_DENIED
;
6822 result
= update_dsspooler(tmp_ctx
,
6823 get_session_info_system(),
6828 if (!W_ERROR_IS_OK(result
)) {
6832 printer_mask
&= ~SPOOLSS_PRINTER_INFO_SECDESC
;
6834 if (devmode
== NULL
) {
6835 printer_mask
&= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
6837 result
= winreg_update_printer(tmp_ctx
, b
,
6845 talloc_free(tmp_ctx
);
6850 /****************************************************************************
6851 ****************************************************************************/
6852 static WERROR
publish_or_unpublish_printer(struct pipes_struct
*p
,
6853 struct policy_handle
*handle
,
6854 struct spoolss_SetPrinterInfo7
*info7
)
6857 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
6860 struct printer_handle
*Printer
;
6862 if ( lp_security() != SEC_ADS
) {
6863 return WERR_UNKNOWN_LEVEL
;
6866 Printer
= find_printer_index_by_hnd(p
, handle
);
6868 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6873 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6876 result
= winreg_get_printer_internal(p
->mem_ctx
,
6877 get_session_info_system(),
6879 lp_servicename(talloc_tos(), snum
),
6881 if (!W_ERROR_IS_OK(result
)) {
6885 nt_printer_publish(pinfo2
,
6886 get_session_info_system(),
6891 TALLOC_FREE(pinfo2
);
6894 return WERR_UNKNOWN_LEVEL
;
6898 /********************************************************************
6899 ********************************************************************/
6901 static WERROR
update_printer_devmode(struct pipes_struct
*p
,
6902 struct policy_handle
*handle
,
6903 struct spoolss_DeviceMode
*devmode
)
6906 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6907 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_DEVMODE
;
6909 DEBUG(8,("update_printer_devmode\n"));
6915 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6919 /* Check calling user has permission to update printer description */
6920 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6921 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6922 return WERR_ACCESS_DENIED
;
6925 return winreg_update_printer_internal(p
->mem_ctx
,
6926 get_session_info_system(),
6928 lp_const_servicename(snum
),
6936 /****************************************************************
6938 ****************************************************************/
6940 WERROR
_spoolss_SetPrinter(struct pipes_struct
*p
,
6941 struct spoolss_SetPrinter
*r
)
6945 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6948 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6949 OUR_HANDLE(r
->in
.handle
)));
6953 /* check the level */
6954 switch (r
->in
.info_ctr
->level
) {
6956 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
6958 result
= update_printer(p
, r
->in
.handle
,
6960 r
->in
.devmode_ctr
->devmode
);
6961 if (!W_ERROR_IS_OK(result
))
6963 if (r
->in
.secdesc_ctr
->sd
)
6964 result
= update_printer_sec(r
->in
.handle
, p
,
6968 return update_printer_sec(r
->in
.handle
, p
,
6971 return publish_or_unpublish_printer(p
, r
->in
.handle
,
6972 r
->in
.info_ctr
->info
.info7
);
6974 return update_printer_devmode(p
, r
->in
.handle
,
6975 r
->in
.devmode_ctr
->devmode
);
6977 return WERR_UNKNOWN_LEVEL
;
6981 /****************************************************************
6982 _spoolss_FindClosePrinterNotify
6983 ****************************************************************/
6985 WERROR
_spoolss_FindClosePrinterNotify(struct pipes_struct
*p
,
6986 struct spoolss_FindClosePrinterNotify
*r
)
6988 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6991 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6992 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
6996 if (Printer
->notify
.cli_chan
!= NULL
&&
6997 Printer
->notify
.cli_chan
->active_connections
> 0) {
7000 if (Printer
->printer_type
== SPLHND_PRINTER
) {
7001 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7006 srv_spoolss_replycloseprinter(snum
, Printer
);
7009 Printer
->notify
.flags
=0;
7010 Printer
->notify
.options
=0;
7011 Printer
->notify
.localmachine
[0]='\0';
7012 Printer
->notify
.printerlocal
=0;
7013 TALLOC_FREE(Printer
->notify
.option
);
7018 /****************************************************************
7020 ****************************************************************/
7022 WERROR
_spoolss_AddJob(struct pipes_struct
*p
,
7023 struct spoolss_AddJob
*r
)
7025 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7026 return WERR_INVALID_PARAM
;
7029 /* this is what a NT server returns for AddJob. AddJob must fail on
7030 * non-local printers */
7032 if (r
->in
.level
!= 1) {
7033 return WERR_UNKNOWN_LEVEL
;
7036 return WERR_INVALID_PARAM
;
7039 /****************************************************************************
7041 ****************************************************************************/
7043 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
7044 struct spoolss_JobInfo1
*r
,
7045 const print_queue_struct
*queue
,
7046 int position
, int snum
,
7047 struct spoolss_PrinterInfo2
*pinfo2
)
7051 t
= gmtime(&queue
->time
);
7053 r
->job_id
= queue
->sysjob
;
7055 r
->printer_name
= lp_servicename(mem_ctx
, snum
);
7056 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
7057 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
7058 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
7059 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
7060 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
7061 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
7062 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
7063 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
7064 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
7065 r
->text_status
= talloc_strdup(mem_ctx
, "");
7066 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
7068 r
->status
= nt_printj_status(queue
->status
);
7069 r
->priority
= queue
->priority
;
7070 r
->position
= position
;
7071 r
->total_pages
= queue
->page_count
;
7072 r
->pages_printed
= 0; /* ??? */
7074 init_systemtime(&r
->submitted
, t
);
7079 /****************************************************************************
7081 ****************************************************************************/
7083 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
7084 struct spoolss_JobInfo2
*r
,
7085 const print_queue_struct
*queue
,
7086 int position
, int snum
,
7087 struct spoolss_PrinterInfo2
*pinfo2
,
7088 struct spoolss_DeviceMode
*devmode
)
7092 t
= gmtime(&queue
->time
);
7094 r
->job_id
= queue
->sysjob
;
7096 r
->printer_name
= lp_servicename(mem_ctx
, snum
);
7097 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
7098 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
7099 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
7100 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
7101 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
7102 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
7103 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
7104 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
7105 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
7106 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
7107 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
7108 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
7109 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
7110 r
->parameters
= talloc_strdup(mem_ctx
, "");
7111 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
7112 r
->driver_name
= talloc_strdup(mem_ctx
, pinfo2
->drivername
);
7113 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
7115 r
->devmode
= devmode
;
7117 r
->text_status
= talloc_strdup(mem_ctx
, "");
7118 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
7122 r
->status
= nt_printj_status(queue
->status
);
7123 r
->priority
= queue
->priority
;
7124 r
->position
= position
;
7127 r
->total_pages
= queue
->page_count
;
7128 r
->size
= queue
->size
;
7129 init_systemtime(&r
->submitted
, t
);
7131 r
->pages_printed
= 0; /* ??? */
7136 /****************************************************************************
7138 ****************************************************************************/
7140 static WERROR
fill_job_info3(TALLOC_CTX
*mem_ctx
,
7141 struct spoolss_JobInfo3
*r
,
7142 const print_queue_struct
*queue
,
7143 const print_queue_struct
*next_queue
,
7144 int position
, int snum
,
7145 struct spoolss_PrinterInfo2
*pinfo2
)
7147 r
->job_id
= queue
->sysjob
;
7150 r
->next_job_id
= next_queue
->sysjob
;
7157 /****************************************************************************
7158 Enumjobs at level 1.
7159 ****************************************************************************/
7161 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
7162 const print_queue_struct
*queue
,
7163 uint32_t num_queues
, int snum
,
7164 struct spoolss_PrinterInfo2
*pinfo2
,
7165 union spoolss_JobInfo
**info_p
,
7168 union spoolss_JobInfo
*info
;
7170 WERROR result
= WERR_OK
;
7172 info
= talloc_array(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7173 W_ERROR_HAVE_NO_MEMORY(info
);
7175 *count
= num_queues
;
7177 for (i
=0; i
<*count
; i
++) {
7178 result
= fill_job_info1(info
,
7184 if (!W_ERROR_IS_OK(result
)) {
7190 if (!W_ERROR_IS_OK(result
)) {
7201 /****************************************************************************
7202 Enumjobs at level 2.
7203 ****************************************************************************/
7205 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
7206 const print_queue_struct
*queue
,
7207 uint32_t num_queues
, int snum
,
7208 struct spoolss_PrinterInfo2
*pinfo2
,
7209 union spoolss_JobInfo
**info_p
,
7212 union spoolss_JobInfo
*info
;
7214 WERROR result
= WERR_OK
;
7216 info
= talloc_array(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7217 W_ERROR_HAVE_NO_MEMORY(info
);
7219 *count
= num_queues
;
7221 for (i
=0; i
<*count
; i
++) {
7222 struct spoolss_DeviceMode
*devmode
;
7224 result
= spoolss_create_default_devmode(info
,
7225 pinfo2
->printername
,
7227 if (!W_ERROR_IS_OK(result
)) {
7228 DEBUG(3, ("Can't proceed w/o a devmode!"));
7232 result
= fill_job_info2(info
,
7239 if (!W_ERROR_IS_OK(result
)) {
7245 if (!W_ERROR_IS_OK(result
)) {
7256 /****************************************************************************
7257 Enumjobs at level 3.
7258 ****************************************************************************/
7260 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
7261 const print_queue_struct
*queue
,
7262 uint32_t num_queues
, int snum
,
7263 struct spoolss_PrinterInfo2
*pinfo2
,
7264 union spoolss_JobInfo
**info_p
,
7267 union spoolss_JobInfo
*info
;
7269 WERROR result
= WERR_OK
;
7271 info
= talloc_array(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7272 W_ERROR_HAVE_NO_MEMORY(info
);
7274 *count
= num_queues
;
7276 for (i
=0; i
<*count
; i
++) {
7277 const print_queue_struct
*next_queue
= NULL
;
7280 next_queue
= &queue
[i
+1];
7283 result
= fill_job_info3(info
,
7290 if (!W_ERROR_IS_OK(result
)) {
7296 if (!W_ERROR_IS_OK(result
)) {
7307 /****************************************************************
7309 ****************************************************************/
7311 WERROR
_spoolss_EnumJobs(struct pipes_struct
*p
,
7312 struct spoolss_EnumJobs
*r
)
7315 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
7317 print_status_struct prt_status
;
7318 print_queue_struct
*queue
= NULL
;
7321 /* that's an [in out] buffer */
7323 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7324 return WERR_INVALID_PARAM
;
7327 DEBUG(4,("_spoolss_EnumJobs\n"));
7331 *r
->out
.info
= NULL
;
7333 /* lookup the printer snum and tdb entry */
7335 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7339 result
= winreg_get_printer_internal(p
->mem_ctx
,
7340 get_session_info_system(),
7342 lp_const_servicename(snum
),
7344 if (!W_ERROR_IS_OK(result
)) {
7348 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
7349 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7350 count
, prt_status
.status
, prt_status
.message
));
7354 TALLOC_FREE(pinfo2
);
7358 switch (r
->in
.level
) {
7360 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
7361 pinfo2
, r
->out
.info
, r
->out
.count
);
7364 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
7365 pinfo2
, r
->out
.info
, r
->out
.count
);
7368 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
7369 pinfo2
, r
->out
.info
, r
->out
.count
);
7372 result
= WERR_UNKNOWN_LEVEL
;
7377 TALLOC_FREE(pinfo2
);
7379 if (!W_ERROR_IS_OK(result
)) {
7383 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7385 *r
->out
.info
, r
->in
.level
,
7387 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7388 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7390 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7393 /****************************************************************
7394 _spoolss_ScheduleJob
7395 ****************************************************************/
7397 WERROR
_spoolss_ScheduleJob(struct pipes_struct
*p
,
7398 struct spoolss_ScheduleJob
*r
)
7403 /****************************************************************
7404 ****************************************************************/
7406 static WERROR
spoolss_setjob_1(TALLOC_CTX
*mem_ctx
,
7407 struct messaging_context
*msg_ctx
,
7408 const char *printer_name
,
7410 struct spoolss_SetJobInfo1
*r
)
7414 if (!print_job_get_name(mem_ctx
, printer_name
, job_id
, &old_doc_name
)) {
7418 if (strequal(old_doc_name
, r
->document_name
)) {
7422 if (!print_job_set_name(server_event_context(), msg_ctx
,
7423 printer_name
, job_id
, r
->document_name
)) {
7430 /****************************************************************
7432 ****************************************************************/
7434 WERROR
_spoolss_SetJob(struct pipes_struct
*p
,
7435 struct spoolss_SetJob
*r
)
7437 const struct auth_session_info
*session_info
= p
->session_info
;
7439 WERROR errcode
= WERR_BADFUNC
;
7441 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7445 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
7446 return WERR_INVALID_PRINTER_NAME
;
7449 switch (r
->in
.command
) {
7450 case SPOOLSS_JOB_CONTROL_CANCEL
:
7451 case SPOOLSS_JOB_CONTROL_DELETE
:
7452 errcode
= print_job_delete(session_info
, p
->msg_ctx
,
7453 snum
, r
->in
.job_id
);
7454 if (W_ERROR_EQUAL(errcode
, WERR_PRINTER_HAS_JOBS_QUEUED
)) {
7458 case SPOOLSS_JOB_CONTROL_PAUSE
:
7459 errcode
= print_job_pause(session_info
, p
->msg_ctx
,
7460 snum
, r
->in
.job_id
);
7462 case SPOOLSS_JOB_CONTROL_RESTART
:
7463 case SPOOLSS_JOB_CONTROL_RESUME
:
7464 errcode
= print_job_resume(session_info
, p
->msg_ctx
,
7465 snum
, r
->in
.job_id
);
7471 return WERR_UNKNOWN_LEVEL
;
7474 if (!W_ERROR_IS_OK(errcode
)) {
7478 if (r
->in
.ctr
== NULL
) {
7482 switch (r
->in
.ctr
->level
) {
7484 errcode
= spoolss_setjob_1(p
->mem_ctx
, p
->msg_ctx
,
7485 lp_const_servicename(snum
),
7487 r
->in
.ctr
->info
.info1
);
7493 return WERR_UNKNOWN_LEVEL
;
7499 /****************************************************************************
7500 Enumerates all printer drivers by level and architecture.
7501 ****************************************************************************/
7503 static WERROR
enumprinterdrivers_level_by_architecture(TALLOC_CTX
*mem_ctx
,
7504 const struct auth_session_info
*session_info
,
7505 struct messaging_context
*msg_ctx
,
7506 const char *servername
,
7507 const char *architecture
,
7509 union spoolss_DriverInfo
**info_p
,
7514 struct spoolss_DriverInfo8
*driver
;
7515 union spoolss_DriverInfo
*info
= NULL
;
7517 WERROR result
= WERR_OK
;
7518 uint32_t num_drivers
;
7519 const char **drivers
;
7520 struct dcerpc_binding_handle
*b
;
7521 TALLOC_CTX
*tmp_ctx
= NULL
;
7526 tmp_ctx
= talloc_new(mem_ctx
);
7531 result
= winreg_printer_binding_handle(tmp_ctx
,
7535 if (!W_ERROR_IS_OK(result
)) {
7539 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
7540 result
= winreg_get_driver_list(tmp_ctx
, b
,
7541 architecture
, version
,
7542 &num_drivers
, &drivers
);
7543 if (!W_ERROR_IS_OK(result
)) {
7546 DEBUG(4, ("we have:[%d] drivers in environment"
7547 " [%s] and version [%d]\n",
7548 num_drivers
, architecture
, version
));
7550 if (num_drivers
!= 0) {
7551 info
= talloc_realloc(tmp_ctx
, info
,
7552 union spoolss_DriverInfo
,
7553 count
+ num_drivers
);
7555 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7556 "failed to enlarge driver info buffer!\n"));
7557 result
= WERR_NOMEM
;
7562 for (i
= 0; i
< num_drivers
; i
++) {
7563 DEBUG(5, ("\tdriver: [%s]\n", drivers
[i
]));
7565 result
= winreg_get_driver(tmp_ctx
, b
,
7566 architecture
, drivers
[i
],
7568 if (!W_ERROR_IS_OK(result
)) {
7574 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
7575 driver
, servername
);
7578 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
7579 driver
, servername
);
7582 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
7583 driver
, servername
);
7586 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
7587 driver
, servername
);
7590 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
7591 driver
, servername
);
7594 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
7595 driver
, servername
);
7598 result
= fill_printer_driver_info8(info
, &info
[count
+i
].info8
,
7599 driver
, servername
);
7602 result
= WERR_UNKNOWN_LEVEL
;
7606 TALLOC_FREE(driver
);
7608 if (!W_ERROR_IS_OK(result
)) {
7613 count
+= num_drivers
;
7614 TALLOC_FREE(drivers
);
7618 if (W_ERROR_IS_OK(result
)) {
7619 *info_p
= talloc_move(mem_ctx
, &info
);
7623 talloc_free(tmp_ctx
);
7627 /****************************************************************************
7628 Enumerates all printer drivers by level.
7629 ****************************************************************************/
7631 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
7632 const struct auth_session_info
*session_info
,
7633 struct messaging_context
*msg_ctx
,
7634 const char *servername
,
7635 const char *architecture
,
7637 union spoolss_DriverInfo
**info_p
,
7641 WERROR result
= WERR_OK
;
7643 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_ALL
)) {
7645 for (a
=0; archi_table
[a
].long_archi
!= NULL
; a
++) {
7647 union spoolss_DriverInfo
*info
= NULL
;
7650 result
= enumprinterdrivers_level_by_architecture(mem_ctx
,
7654 archi_table
[a
].long_archi
,
7658 if (!W_ERROR_IS_OK(result
)) {
7662 for (i
=0; i
< count
; i
++) {
7663 ADD_TO_ARRAY(mem_ctx
, union spoolss_DriverInfo
,
7664 info
[i
], info_p
, count_p
);
7671 return enumprinterdrivers_level_by_architecture(mem_ctx
,
7681 /****************************************************************
7682 _spoolss_EnumPrinterDrivers
7683 ****************************************************************/
7685 WERROR
_spoolss_EnumPrinterDrivers(struct pipes_struct
*p
,
7686 struct spoolss_EnumPrinterDrivers
*r
)
7688 const char *cservername
;
7691 /* that's an [in out] buffer */
7693 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7694 return WERR_INVALID_PARAM
;
7697 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7701 *r
->out
.info
= NULL
;
7703 cservername
= canon_servername(r
->in
.server
);
7705 if (!is_myname_or_ipaddr(cservername
)) {
7706 return WERR_UNKNOWN_PRINTER_DRIVER
;
7709 result
= enumprinterdrivers_level(p
->mem_ctx
,
7710 get_session_info_system(),
7717 if (!W_ERROR_IS_OK(result
)) {
7721 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7722 spoolss_EnumPrinterDrivers
,
7723 *r
->out
.info
, r
->in
.level
,
7725 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7726 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7728 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7731 /****************************************************************
7733 ****************************************************************/
7735 WERROR
_spoolss_EnumForms(struct pipes_struct
*p
,
7736 struct spoolss_EnumForms
*r
)
7742 *r
->out
.info
= NULL
;
7744 /* that's an [in out] buffer */
7746 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
7747 return WERR_INVALID_PARAM
;
7750 DEBUG(4,("_spoolss_EnumForms\n"));
7751 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7752 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7754 switch (r
->in
.level
) {
7756 result
= winreg_printer_enumforms1_internal(p
->mem_ctx
,
7757 get_session_info_system(),
7763 result
= WERR_UNKNOWN_LEVEL
;
7767 if (!W_ERROR_IS_OK(result
)) {
7771 if (*r
->out
.count
== 0) {
7772 return WERR_NO_MORE_ITEMS
;
7775 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7777 *r
->out
.info
, r
->in
.level
,
7779 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7780 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7782 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7785 /****************************************************************
7787 ****************************************************************/
7789 WERROR
_spoolss_GetForm(struct pipes_struct
*p
,
7790 struct spoolss_GetForm
*r
)
7794 /* that's an [in out] buffer */
7796 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7797 return WERR_INVALID_PARAM
;
7800 DEBUG(4,("_spoolss_GetForm\n"));
7801 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7802 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7804 switch (r
->in
.level
) {
7806 result
= winreg_printer_getform1_internal(p
->mem_ctx
,
7807 get_session_info_system(),
7810 &r
->out
.info
->info1
);
7813 result
= WERR_UNKNOWN_LEVEL
;
7817 if (!W_ERROR_IS_OK(result
)) {
7818 TALLOC_FREE(r
->out
.info
);
7822 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
,
7823 r
->out
.info
, r
->in
.level
);
7824 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7826 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7829 /****************************************************************************
7830 ****************************************************************************/
7832 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
7833 struct spoolss_PortInfo1
*r
,
7836 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7837 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7842 /****************************************************************************
7843 TODO: This probably needs distinguish between TCP/IP and Local ports
7845 ****************************************************************************/
7847 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
7848 struct spoolss_PortInfo2
*r
,
7851 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7852 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7854 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
7855 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
7857 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
7858 W_ERROR_HAVE_NO_MEMORY(r
->description
);
7860 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
7867 /****************************************************************************
7868 wrapper around the enumer ports command
7869 ****************************************************************************/
7871 static WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
7873 char *cmd
= lp_enumports_command(talloc_tos());
7874 char **qlines
= NULL
;
7875 char *command
= NULL
;
7883 /* if no hook then just fill in the default port */
7886 if (!(qlines
= talloc_array( NULL
, char*, 2 ))) {
7889 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
7890 TALLOC_FREE(qlines
);
7897 /* we have a valid enumport command */
7899 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
7904 DEBUG(10,("Running [%s]\n", command
));
7905 ret
= smbrun(command
, &fd
);
7906 DEBUG(10,("Returned [%d]\n", ret
));
7907 TALLOC_FREE(command
);
7912 return WERR_ACCESS_DENIED
;
7916 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
7917 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7927 /****************************************************************************
7929 ****************************************************************************/
7931 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
7932 union spoolss_PortInfo
**info_p
,
7935 union spoolss_PortInfo
*info
= NULL
;
7937 WERROR result
= WERR_OK
;
7938 char **qlines
= NULL
;
7941 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7942 if (!W_ERROR_IS_OK(result
)) {
7947 info
= talloc_array(mem_ctx
, union spoolss_PortInfo
, numlines
);
7949 DEBUG(10,("Returning WERR_NOMEM\n"));
7950 result
= WERR_NOMEM
;
7954 for (i
=0; i
<numlines
; i
++) {
7955 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7956 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7957 if (!W_ERROR_IS_OK(result
)) {
7962 TALLOC_FREE(qlines
);
7965 if (!W_ERROR_IS_OK(result
)) {
7967 TALLOC_FREE(qlines
);
7979 /****************************************************************************
7981 ****************************************************************************/
7983 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7984 union spoolss_PortInfo
**info_p
,
7987 union spoolss_PortInfo
*info
= NULL
;
7989 WERROR result
= WERR_OK
;
7990 char **qlines
= NULL
;
7993 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7994 if (!W_ERROR_IS_OK(result
)) {
7999 info
= talloc_array(mem_ctx
, union spoolss_PortInfo
, numlines
);
8001 DEBUG(10,("Returning WERR_NOMEM\n"));
8002 result
= WERR_NOMEM
;
8006 for (i
=0; i
<numlines
; i
++) {
8007 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
8008 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
8009 if (!W_ERROR_IS_OK(result
)) {
8014 TALLOC_FREE(qlines
);
8017 if (!W_ERROR_IS_OK(result
)) {
8019 TALLOC_FREE(qlines
);
8031 /****************************************************************
8033 ****************************************************************/
8035 WERROR
_spoolss_EnumPorts(struct pipes_struct
*p
,
8036 struct spoolss_EnumPorts
*r
)
8040 /* that's an [in out] buffer */
8042 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8043 return WERR_INVALID_PARAM
;
8046 DEBUG(4,("_spoolss_EnumPorts\n"));
8050 *r
->out
.info
= NULL
;
8052 switch (r
->in
.level
) {
8054 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
8058 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
8062 return WERR_UNKNOWN_LEVEL
;
8065 if (!W_ERROR_IS_OK(result
)) {
8069 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8071 *r
->out
.info
, r
->in
.level
,
8073 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8074 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8076 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8079 /****************************************************************************
8080 ****************************************************************************/
8082 static WERROR
spoolss_addprinterex_level_2(struct pipes_struct
*p
,
8084 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
8085 struct spoolss_DeviceMode
*devmode
,
8086 struct security_descriptor
*secdesc
,
8087 struct spoolss_UserLevelCtr
*user_ctr
,
8088 struct policy_handle
*handle
)
8090 struct spoolss_SetPrinterInfo2
*info2
= info_ctr
->info
.info2
;
8091 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_ALL
;
8093 WERROR err
= WERR_OK
;
8095 /* samba does not have a concept of local, non-shared printers yet, so
8096 * make sure we always setup sharename - gd */
8097 if ((info2
->sharename
== NULL
|| info2
->sharename
[0] == '\0') &&
8098 (info2
->printername
!= NULL
&& info2
->printername
[0] != '\0')) {
8099 DEBUG(5, ("spoolss_addprinterex_level_2: "
8100 "no sharename has been set, setting printername %s as sharename\n",
8101 info2
->printername
));
8102 info2
->sharename
= info2
->printername
;
8105 /* check to see if the printer already exists */
8106 if ((snum
= print_queue_snum(info2
->sharename
)) != -1) {
8107 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8109 return WERR_PRINTER_ALREADY_EXISTS
;
8112 if (!lp_force_printername(GLOBAL_SECTION_SNUM
)) {
8113 if ((snum
= print_queue_snum(info2
->printername
)) != -1) {
8114 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8115 info2
->printername
));
8116 return WERR_PRINTER_ALREADY_EXISTS
;
8120 /* validate printer info struct */
8121 if (!info2
->printername
|| strlen(info2
->printername
) == 0) {
8122 return WERR_INVALID_PRINTER_NAME
;
8124 if (!info2
->portname
|| strlen(info2
->portname
) == 0) {
8125 return WERR_UNKNOWN_PORT
;
8127 if (!info2
->drivername
|| strlen(info2
->drivername
) == 0) {
8128 return WERR_UNKNOWN_PRINTER_DRIVER
;
8130 if (!info2
->printprocessor
|| strlen(info2
->printprocessor
) == 0) {
8131 return WERR_UNKNOWN_PRINTPROCESSOR
;
8134 /* FIXME!!! smbd should check to see if the driver is installed before
8135 trying to add a printer like this --jerry */
8137 if (*lp_addprinter_command(talloc_tos()) ) {
8140 raddr
= tsocket_address_inet_addr_string(p
->remote_address
,
8142 if (raddr
== NULL
) {
8146 if ( !add_printer_hook(p
->mem_ctx
, p
->session_info
->security_token
,
8149 return WERR_ACCESS_DENIED
;
8152 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8153 "smb.conf parameter \"addprinter command\" is defined. This "
8154 "parameter must exist for this call to succeed\n",
8155 info2
->sharename
));
8158 if ((snum
= print_queue_snum(info2
->sharename
)) == -1) {
8159 return WERR_ACCESS_DENIED
;
8162 /* you must be a printer admin to add a new printer */
8163 if (!W_ERROR_IS_OK(print_access_check(p
->session_info
,
8166 PRINTER_ACCESS_ADMINISTER
))) {
8167 return WERR_ACCESS_DENIED
;
8171 * Do sanity check on the requested changes for Samba.
8174 if (!check_printer_ok(p
->mem_ctx
, info2
, snum
)) {
8175 return WERR_INVALID_PARAM
;
8178 if (devmode
== NULL
) {
8179 info2_mask
= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
8182 err
= update_dsspooler(p
->mem_ctx
,
8183 get_session_info_system(),
8188 if (!W_ERROR_IS_OK(err
)) {
8192 err
= winreg_update_printer_internal(p
->mem_ctx
,
8193 get_session_info_system(),
8200 if (!W_ERROR_IS_OK(err
)) {
8204 err
= open_printer_hnd(p
, handle
, info2
->printername
, PRINTER_ACCESS_ADMINISTER
);
8205 if (!W_ERROR_IS_OK(err
)) {
8206 /* Handle open failed - remove addition. */
8207 ZERO_STRUCTP(handle
);
8214 /****************************************************************
8215 _spoolss_AddPrinterEx
8216 ****************************************************************/
8218 WERROR
_spoolss_AddPrinterEx(struct pipes_struct
*p
,
8219 struct spoolss_AddPrinterEx
*r
)
8221 switch (r
->in
.info_ctr
->level
) {
8223 /* we don't handle yet */
8224 /* but I know what to do ... */
8225 return WERR_UNKNOWN_LEVEL
;
8227 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
8229 r
->in
.devmode_ctr
->devmode
,
8230 r
->in
.secdesc_ctr
->sd
,
8231 r
->in
.userlevel_ctr
,
8234 return WERR_UNKNOWN_LEVEL
;
8238 /****************************************************************
8240 ****************************************************************/
8242 WERROR
_spoolss_AddPrinter(struct pipes_struct
*p
,
8243 struct spoolss_AddPrinter
*r
)
8245 struct spoolss_AddPrinterEx a
;
8246 struct spoolss_UserLevelCtr userlevel_ctr
;
8248 ZERO_STRUCT(userlevel_ctr
);
8250 userlevel_ctr
.level
= 1;
8252 a
.in
.server
= r
->in
.server
;
8253 a
.in
.info_ctr
= r
->in
.info_ctr
;
8254 a
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
8255 a
.in
.secdesc_ctr
= r
->in
.secdesc_ctr
;
8256 a
.in
.userlevel_ctr
= &userlevel_ctr
;
8257 a
.out
.handle
= r
->out
.handle
;
8259 return _spoolss_AddPrinterEx(p
, &a
);
8262 /****************************************************************
8263 _spoolss_AddPrinterDriverEx
8264 ****************************************************************/
8266 WERROR
_spoolss_AddPrinterDriverEx(struct pipes_struct
*p
,
8267 struct spoolss_AddPrinterDriverEx
*r
)
8269 WERROR err
= WERR_OK
;
8270 const char *driver_name
= NULL
;
8275 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
8276 fn
= "_spoolss_AddPrinterDriver";
8278 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
8279 fn
= "_spoolss_AddPrinterDriverEx";
8282 return WERR_INVALID_PARAM
;
8286 * we only support the semantics of AddPrinterDriver()
8287 * i.e. only copy files that are newer than existing ones
8290 if (r
->in
.flags
== 0) {
8291 return WERR_INVALID_PARAM
;
8294 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
8295 return WERR_ACCESS_DENIED
;
8299 if (r
->in
.info_ctr
->level
!= 3 && r
->in
.info_ctr
->level
!= 6) {
8300 /* Clever hack from Martin Zielinski <mz@seh.de>
8301 * to allow downgrade from level 8 (Vista).
8303 DEBUG(0,("%s: level %d not yet implemented\n", fn
,
8304 r
->in
.info_ctr
->level
));
8305 return WERR_UNKNOWN_LEVEL
;
8308 DEBUG(5,("Cleaning driver's information\n"));
8309 err
= clean_up_driver_struct(p
->mem_ctx
, p
->session_info
, r
->in
.info_ctr
);
8310 if (!W_ERROR_IS_OK(err
))
8313 DEBUG(5,("Moving driver to final destination\n"));
8314 err
= move_driver_to_download_area(p
->session_info
, r
->in
.info_ctr
);
8315 if (!W_ERROR_IS_OK(err
)) {
8319 err
= winreg_add_driver_internal(p
->mem_ctx
,
8320 get_session_info_system(),
8325 if (!W_ERROR_IS_OK(err
)) {
8330 * I think this is where he DrvUpgradePrinter() hook would be
8331 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8332 * server. Right now, we just need to send ourselves a message
8333 * to update each printer bound to this driver. --jerry
8336 if (!srv_spoolss_drv_upgrade_printer(driver_name
, p
->msg_ctx
)) {
8337 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8345 /****************************************************************
8346 _spoolss_AddPrinterDriver
8347 ****************************************************************/
8349 WERROR
_spoolss_AddPrinterDriver(struct pipes_struct
*p
,
8350 struct spoolss_AddPrinterDriver
*r
)
8352 struct spoolss_AddPrinterDriverEx a
;
8354 switch (r
->in
.info_ctr
->level
) {
8361 return WERR_UNKNOWN_LEVEL
;
8364 a
.in
.servername
= r
->in
.servername
;
8365 a
.in
.info_ctr
= r
->in
.info_ctr
;
8366 a
.in
.flags
= APD_COPY_NEW_FILES
;
8368 return _spoolss_AddPrinterDriverEx(p
, &a
);
8371 /****************************************************************************
8372 ****************************************************************************/
8374 struct _spoolss_paths
{
8380 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
8382 static const struct _spoolss_paths spoolss_paths
[]= {
8383 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
8384 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
8387 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
8388 const char *servername
,
8389 const char *environment
,
8393 const char *pservername
= NULL
;
8394 const char *long_archi
;
8395 const char *short_archi
;
8399 /* environment may be empty */
8400 if (environment
&& strlen(environment
)) {
8401 long_archi
= environment
;
8403 long_archi
= lp_parm_const_string(GLOBAL_SECTION_SNUM
,
8404 "spoolss", "architecture",
8405 SPOOLSS_ARCHITECTURE_NT_X86
);
8408 /* servername may be empty */
8409 if (servername
&& strlen(servername
)) {
8410 pservername
= canon_servername(servername
);
8412 if (!is_myname_or_ipaddr(pservername
)) {
8413 return WERR_INVALID_PARAM
;
8417 if (!(short_archi
= get_short_archi(long_archi
))) {
8418 return WERR_INVALID_ENVIRONMENT
;
8421 switch (component
) {
8422 case SPOOLSS_PRTPROCS_PATH
:
8423 case SPOOLSS_DRIVER_PATH
:
8425 *path
= talloc_asprintf(mem_ctx
,
8428 spoolss_paths
[component
].share
,
8431 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
8432 SPOOLSS_DEFAULT_SERVER_PATH
,
8433 spoolss_paths
[component
].dir
,
8438 return WERR_INVALID_PARAM
;
8448 /****************************************************************************
8449 ****************************************************************************/
8451 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
8452 const char *servername
,
8453 const char *environment
,
8454 struct spoolss_DriverDirectoryInfo1
*r
)
8459 werr
= compose_spoolss_server_path(mem_ctx
,
8462 SPOOLSS_DRIVER_PATH
,
8464 if (!W_ERROR_IS_OK(werr
)) {
8468 DEBUG(4,("printer driver directory: [%s]\n", path
));
8470 r
->directory_name
= path
;
8475 /****************************************************************
8476 _spoolss_GetPrinterDriverDirectory
8477 ****************************************************************/
8479 WERROR
_spoolss_GetPrinterDriverDirectory(struct pipes_struct
*p
,
8480 struct spoolss_GetPrinterDriverDirectory
*r
)
8484 /* that's an [in out] buffer */
8486 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8487 return WERR_INVALID_PARAM
;
8490 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8495 /* r->in.level is ignored */
8497 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
8500 &r
->out
.info
->info1
);
8501 if (!W_ERROR_IS_OK(werror
)) {
8502 TALLOC_FREE(r
->out
.info
);
8506 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
,
8507 r
->out
.info
, r
->in
.level
);
8508 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8510 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8513 /****************************************************************
8514 _spoolss_EnumPrinterData
8515 ****************************************************************/
8517 WERROR
_spoolss_EnumPrinterData(struct pipes_struct
*p
,
8518 struct spoolss_EnumPrinterData
*r
)
8521 struct spoolss_EnumPrinterDataEx r2
;
8523 struct spoolss_PrinterEnumValues
*info
, *val
= NULL
;
8526 r2
.in
.handle
= r
->in
.handle
;
8527 r2
.in
.key_name
= "PrinterDriverData";
8529 r2
.out
.count
= &count
;
8530 r2
.out
.info
= &info
;
8531 r2
.out
.needed
= &needed
;
8533 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
8534 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
8535 r2
.in
.offered
= needed
;
8536 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
8538 if (!W_ERROR_IS_OK(result
)) {
8543 * The NT machine wants to know the biggest size of value and data
8545 * cf: MSDN EnumPrinterData remark section
8548 if (!r
->in
.value_offered
&& !r
->in
.data_offered
) {
8549 uint32_t biggest_valuesize
= 0;
8550 uint32_t biggest_datasize
= 0;
8553 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8555 for (i
=0; i
<count
; i
++) {
8557 name_length
= strlen(info
[i
].value_name
);
8558 if (strlen(info
[i
].value_name
) > biggest_valuesize
) {
8559 biggest_valuesize
= name_length
;
8562 if (info
[i
].data_length
> biggest_datasize
) {
8563 biggest_datasize
= info
[i
].data_length
;
8566 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
8570 /* the value is an UNICODE string but real_value_size is the length
8571 in bytes including the trailing 0 */
8573 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
8574 *r
->out
.data_needed
= biggest_datasize
;
8576 DEBUG(6,("final values: [%d], [%d]\n",
8577 *r
->out
.value_needed
, *r
->out
.data_needed
));
8582 if (r
->in
.enum_index
< count
) {
8583 val
= &info
[r
->in
.enum_index
];
8587 /* out_value should default to "" or else NT4 has
8588 problems unmarshalling the response */
8590 if (r
->in
.value_offered
) {
8591 *r
->out
.value_needed
= 1;
8592 r
->out
.value_name
= talloc_strdup(r
, "");
8593 if (!r
->out
.value_name
) {
8597 r
->out
.value_name
= NULL
;
8598 *r
->out
.value_needed
= 0;
8601 /* the data is counted in bytes */
8603 *r
->out
.data_needed
= r
->in
.data_offered
;
8605 result
= WERR_NO_MORE_ITEMS
;
8609 * - counted in bytes in the request
8610 * - counted in UNICODE chars in the max reply
8611 * - counted in bytes in the real size
8613 * take a pause *before* coding not *during* coding
8617 if (r
->in
.value_offered
) {
8618 r
->out
.value_name
= talloc_strdup(r
, val
->value_name
);
8619 if (!r
->out
.value_name
) {
8622 *r
->out
.value_needed
= val
->value_name_len
;
8624 r
->out
.value_name
= NULL
;
8625 *r
->out
.value_needed
= 0;
8630 *r
->out
.type
= val
->type
;
8632 /* data - counted in bytes */
8635 * See the section "Dynamically Typed Query Parameters"
8639 if (r
->out
.data
&& val
->data
&& val
->data
->data
&&
8640 val
->data_length
&& r
->in
.data_offered
) {
8641 memcpy(r
->out
.data
, val
->data
->data
,
8642 MIN(val
->data_length
,r
->in
.data_offered
));
8645 *r
->out
.data_needed
= val
->data_length
;
8653 /****************************************************************
8654 _spoolss_SetPrinterData
8655 ****************************************************************/
8657 WERROR
_spoolss_SetPrinterData(struct pipes_struct
*p
,
8658 struct spoolss_SetPrinterData
*r
)
8660 struct spoolss_SetPrinterDataEx r2
;
8662 r2
.in
.handle
= r
->in
.handle
;
8663 r2
.in
.key_name
= "PrinterDriverData";
8664 r2
.in
.value_name
= r
->in
.value_name
;
8665 r2
.in
.type
= r
->in
.type
;
8666 r2
.in
.data
= r
->in
.data
;
8667 r2
.in
.offered
= r
->in
.offered
;
8669 return _spoolss_SetPrinterDataEx(p
, &r2
);
8672 /****************************************************************
8673 _spoolss_ResetPrinter
8674 ****************************************************************/
8676 WERROR
_spoolss_ResetPrinter(struct pipes_struct
*p
,
8677 struct spoolss_ResetPrinter
*r
)
8679 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8682 DEBUG(5,("_spoolss_ResetPrinter\n"));
8685 * All we do is to check to see if the handle and queue is valid.
8686 * This call really doesn't mean anything to us because we only
8687 * support RAW printing. --jerry
8691 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8692 OUR_HANDLE(r
->in
.handle
)));
8696 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8700 /* blindly return success */
8704 /****************************************************************
8705 _spoolss_DeletePrinterData
8706 ****************************************************************/
8708 WERROR
_spoolss_DeletePrinterData(struct pipes_struct
*p
,
8709 struct spoolss_DeletePrinterData
*r
)
8711 struct spoolss_DeletePrinterDataEx r2
;
8713 r2
.in
.handle
= r
->in
.handle
;
8714 r2
.in
.key_name
= "PrinterDriverData";
8715 r2
.in
.value_name
= r
->in
.value_name
;
8717 return _spoolss_DeletePrinterDataEx(p
, &r2
);
8720 /****************************************************************
8722 ****************************************************************/
8724 WERROR
_spoolss_AddForm(struct pipes_struct
*p
,
8725 struct spoolss_AddForm
*r
)
8727 struct spoolss_AddFormInfo1
*form
;
8729 WERROR status
= WERR_OK
;
8730 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8731 struct dcerpc_binding_handle
*b
;
8732 TALLOC_CTX
*tmp_ctx
= NULL
;
8734 DEBUG(5,("_spoolss_AddForm\n"));
8737 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8738 OUR_HANDLE(r
->in
.handle
)));
8742 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8743 and not a printer admin, then fail */
8745 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
8746 !security_token_has_privilege(p
->session_info
->security_token
,
8747 SEC_PRIV_PRINT_OPERATOR
)) {
8748 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8749 return WERR_ACCESS_DENIED
;
8752 if (r
->in
.info_ctr
->level
!= 1) {
8753 return WERR_INVALID_LEVEL
;
8756 form
= r
->in
.info_ctr
->info
.info1
;
8758 return WERR_INVALID_PARAM
;
8761 switch (form
->flags
) {
8762 case SPOOLSS_FORM_USER
:
8763 case SPOOLSS_FORM_BUILTIN
:
8764 case SPOOLSS_FORM_PRINTER
:
8767 return WERR_INVALID_PARAM
;
8770 tmp_ctx
= talloc_new(p
->mem_ctx
);
8775 status
= winreg_printer_binding_handle(tmp_ctx
,
8776 get_session_info_system(),
8779 if (!W_ERROR_IS_OK(status
)) {
8783 status
= winreg_printer_addform1(tmp_ctx
, b
, form
);
8784 if (!W_ERROR_IS_OK(status
)) {
8789 * ChangeID must always be set if this is a printer
8791 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8792 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8793 status
= WERR_BADFID
;
8797 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
8798 lp_const_servicename(snum
));
8802 talloc_free(tmp_ctx
);
8806 /****************************************************************
8808 ****************************************************************/
8810 WERROR
_spoolss_DeleteForm(struct pipes_struct
*p
,
8811 struct spoolss_DeleteForm
*r
)
8813 const char *form_name
= r
->in
.form_name
;
8814 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8816 WERROR status
= WERR_OK
;
8817 struct dcerpc_binding_handle
*b
;
8818 TALLOC_CTX
*tmp_ctx
= NULL
;
8820 DEBUG(5,("_spoolss_DeleteForm\n"));
8823 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8824 OUR_HANDLE(r
->in
.handle
)));
8828 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
8829 !security_token_has_privilege(p
->session_info
->security_token
,
8830 SEC_PRIV_PRINT_OPERATOR
)) {
8831 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8832 return WERR_ACCESS_DENIED
;
8835 tmp_ctx
= talloc_new(p
->mem_ctx
);
8840 status
= winreg_printer_binding_handle(tmp_ctx
,
8841 get_session_info_system(),
8844 if (!W_ERROR_IS_OK(status
)) {
8848 status
= winreg_printer_deleteform1(tmp_ctx
, b
, form_name
);
8849 if (!W_ERROR_IS_OK(status
)) {
8854 * ChangeID must always be set if this is a printer
8856 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8857 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8858 status
= WERR_BADFID
;
8862 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
8863 lp_const_servicename(snum
));
8867 talloc_free(tmp_ctx
);
8871 /****************************************************************
8873 ****************************************************************/
8875 WERROR
_spoolss_SetForm(struct pipes_struct
*p
,
8876 struct spoolss_SetForm
*r
)
8878 struct spoolss_AddFormInfo1
*form
;
8879 const char *form_name
= r
->in
.form_name
;
8881 WERROR status
= WERR_OK
;
8882 struct dcerpc_binding_handle
*b
;
8883 TALLOC_CTX
*tmp_ctx
= NULL
;
8885 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8887 DEBUG(5,("_spoolss_SetForm\n"));
8890 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8891 OUR_HANDLE(r
->in
.handle
)));
8895 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8896 and not a printer admin, then fail */
8898 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
8899 !security_token_has_privilege(p
->session_info
->security_token
,
8900 SEC_PRIV_PRINT_OPERATOR
)) {
8901 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8902 return WERR_ACCESS_DENIED
;
8905 if (r
->in
.info_ctr
->level
!= 1) {
8906 return WERR_INVALID_LEVEL
;
8909 form
= r
->in
.info_ctr
->info
.info1
;
8911 return WERR_INVALID_PARAM
;
8914 tmp_ctx
= talloc_new(p
->mem_ctx
);
8919 status
= winreg_printer_binding_handle(tmp_ctx
,
8920 get_session_info_system(),
8923 if (!W_ERROR_IS_OK(status
)) {
8927 status
= winreg_printer_setform1(tmp_ctx
, b
,
8930 if (!W_ERROR_IS_OK(status
)) {
8935 * ChangeID must always be set if this is a printer
8937 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8938 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8939 status
= WERR_BADFID
;
8943 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
8944 lp_const_servicename(snum
));
8948 talloc_free(tmp_ctx
);
8952 /****************************************************************************
8953 fill_print_processor1
8954 ****************************************************************************/
8956 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8957 struct spoolss_PrintProcessorInfo1
*r
,
8958 const char *print_processor_name
)
8960 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8961 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8966 /****************************************************************************
8967 enumprintprocessors level 1.
8968 ****************************************************************************/
8970 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8971 union spoolss_PrintProcessorInfo
**info_p
,
8974 union spoolss_PrintProcessorInfo
*info
;
8977 info
= talloc_array(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8978 W_ERROR_HAVE_NO_MEMORY(info
);
8982 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8983 if (!W_ERROR_IS_OK(result
)) {
8988 if (!W_ERROR_IS_OK(result
)) {
8999 /****************************************************************
9000 _spoolss_EnumPrintProcessors
9001 ****************************************************************/
9003 WERROR
_spoolss_EnumPrintProcessors(struct pipes_struct
*p
,
9004 struct spoolss_EnumPrintProcessors
*r
)
9008 /* that's an [in out] buffer */
9010 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9011 return WERR_INVALID_PARAM
;
9014 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9017 * Enumerate the print processors ...
9019 * Just reply with "winprint", to keep NT happy
9020 * and I can use my nice printer checker.
9025 *r
->out
.info
= NULL
;
9027 if (!get_short_archi(r
->in
.environment
)) {
9028 return WERR_INVALID_ENVIRONMENT
;
9031 switch (r
->in
.level
) {
9033 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
9037 return WERR_UNKNOWN_LEVEL
;
9040 if (!W_ERROR_IS_OK(result
)) {
9044 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
9045 spoolss_EnumPrintProcessors
,
9046 *r
->out
.info
, r
->in
.level
,
9048 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9049 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
9051 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9054 /****************************************************************************
9055 fill_printprocdatatype1
9056 ****************************************************************************/
9058 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
9059 struct spoolss_PrintProcDataTypesInfo1
*r
,
9060 const char *name_array
)
9062 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
9063 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
9068 /****************************************************************************
9069 enumprintprocdatatypes level 1.
9070 ****************************************************************************/
9072 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
9073 union spoolss_PrintProcDataTypesInfo
**info_p
,
9077 union spoolss_PrintProcDataTypesInfo
*info
;
9079 info
= talloc_array(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
9080 W_ERROR_HAVE_NO_MEMORY(info
);
9084 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
9085 if (!W_ERROR_IS_OK(result
)) {
9090 if (!W_ERROR_IS_OK(result
)) {
9101 /****************************************************************
9102 _spoolss_EnumPrintProcDataTypes
9103 ****************************************************************/
9105 WERROR
_spoolss_EnumPrintProcDataTypes(struct pipes_struct
*p
,
9106 struct spoolss_EnumPrintProcDataTypes
*r
)
9110 /* that's an [in out] buffer */
9112 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9113 return WERR_INVALID_PARAM
;
9116 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9120 *r
->out
.info
= NULL
;
9122 if (r
->in
.print_processor_name
== NULL
||
9123 !strequal(r
->in
.print_processor_name
, "winprint")) {
9124 return WERR_UNKNOWN_PRINTPROCESSOR
;
9127 switch (r
->in
.level
) {
9129 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
9133 return WERR_UNKNOWN_LEVEL
;
9136 if (!W_ERROR_IS_OK(result
)) {
9140 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
9141 spoolss_EnumPrintProcDataTypes
,
9142 *r
->out
.info
, r
->in
.level
,
9144 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9145 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
9147 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9150 /****************************************************************************
9152 ****************************************************************************/
9154 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
9155 struct spoolss_MonitorInfo1
*r
,
9156 const char *monitor_name
)
9158 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
9159 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
9164 /****************************************************************************
9166 ****************************************************************************/
9168 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
9169 struct spoolss_MonitorInfo2
*r
,
9170 const char *monitor_name
,
9171 const char *environment
,
9172 const char *dll_name
)
9174 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
9175 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
9176 r
->environment
= talloc_strdup(mem_ctx
, environment
);
9177 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
9178 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
9179 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
9184 /****************************************************************************
9185 enumprintmonitors level 1.
9186 ****************************************************************************/
9188 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
9189 union spoolss_MonitorInfo
**info_p
,
9192 union spoolss_MonitorInfo
*info
;
9193 WERROR result
= WERR_OK
;
9195 info
= talloc_array(mem_ctx
, union spoolss_MonitorInfo
, 2);
9196 W_ERROR_HAVE_NO_MEMORY(info
);
9200 result
= fill_monitor_1(info
, &info
[0].info1
,
9202 if (!W_ERROR_IS_OK(result
)) {
9206 result
= fill_monitor_1(info
, &info
[1].info1
,
9208 if (!W_ERROR_IS_OK(result
)) {
9213 if (!W_ERROR_IS_OK(result
)) {
9224 /****************************************************************************
9225 enumprintmonitors level 2.
9226 ****************************************************************************/
9228 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
9229 union spoolss_MonitorInfo
**info_p
,
9232 union spoolss_MonitorInfo
*info
;
9233 WERROR result
= WERR_OK
;
9235 info
= talloc_array(mem_ctx
, union spoolss_MonitorInfo
, 2);
9236 W_ERROR_HAVE_NO_MEMORY(info
);
9240 result
= fill_monitor_2(info
, &info
[0].info2
,
9242 "Windows NT X86", /* FIXME */
9244 if (!W_ERROR_IS_OK(result
)) {
9248 result
= fill_monitor_2(info
, &info
[1].info2
,
9250 "Windows NT X86", /* FIXME */
9252 if (!W_ERROR_IS_OK(result
)) {
9257 if (!W_ERROR_IS_OK(result
)) {
9268 /****************************************************************
9269 _spoolss_EnumMonitors
9270 ****************************************************************/
9272 WERROR
_spoolss_EnumMonitors(struct pipes_struct
*p
,
9273 struct spoolss_EnumMonitors
*r
)
9277 /* that's an [in out] buffer */
9279 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9280 return WERR_INVALID_PARAM
;
9283 DEBUG(5,("_spoolss_EnumMonitors\n"));
9286 * Enumerate the print monitors ...
9288 * Just reply with "Local Port", to keep NT happy
9289 * and I can use my nice printer checker.
9294 *r
->out
.info
= NULL
;
9296 switch (r
->in
.level
) {
9298 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
9302 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
9306 return WERR_UNKNOWN_LEVEL
;
9309 if (!W_ERROR_IS_OK(result
)) {
9313 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
9314 spoolss_EnumMonitors
,
9315 *r
->out
.info
, r
->in
.level
,
9317 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9318 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
9320 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9323 /****************************************************************************
9324 ****************************************************************************/
9326 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
9327 const print_queue_struct
*queue
,
9328 int count
, int snum
,
9329 struct spoolss_PrinterInfo2
*pinfo2
,
9331 struct spoolss_JobInfo1
*r
)
9336 for (i
=0; i
<count
; i
++) {
9337 if (queue
[i
].sysjob
== (int)jobid
) {
9343 if (found
== false) {
9344 /* NT treats not found as bad param... yet another bad choice */
9345 return WERR_INVALID_PARAM
;
9348 return fill_job_info1(mem_ctx
,
9356 /****************************************************************************
9357 ****************************************************************************/
9359 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
9360 const print_queue_struct
*queue
,
9361 int count
, int snum
,
9362 struct spoolss_PrinterInfo2
*pinfo2
,
9364 struct spoolss_JobInfo2
*r
)
9368 struct spoolss_DeviceMode
*devmode
;
9371 for (i
=0; i
<count
; i
++) {
9372 if (queue
[i
].sysjob
== (int)jobid
) {
9378 if (found
== false) {
9379 /* NT treats not found as bad param... yet another bad
9381 return WERR_INVALID_PARAM
;
9385 * if the print job does not have a DEVMODE associated with it,
9386 * just use the one for the printer. A NULL devicemode is not
9387 * a failure condition
9390 devmode
= print_job_devmode(mem_ctx
, lp_const_servicename(snum
), jobid
);
9392 result
= spoolss_create_default_devmode(mem_ctx
,
9393 pinfo2
->printername
,
9395 if (!W_ERROR_IS_OK(result
)) {
9396 DEBUG(3, ("Can't proceed w/o a devmode!"));
9401 return fill_job_info2(mem_ctx
,
9410 /****************************************************************
9412 ****************************************************************/
9414 WERROR
_spoolss_GetJob(struct pipes_struct
*p
,
9415 struct spoolss_GetJob
*r
)
9417 WERROR result
= WERR_OK
;
9418 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
9421 print_queue_struct
*queue
= NULL
;
9422 print_status_struct prt_status
;
9424 /* that's an [in out] buffer */
9426 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9427 return WERR_INVALID_PARAM
;
9430 DEBUG(5,("_spoolss_GetJob\n"));
9434 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9438 result
= winreg_get_printer_internal(p
->mem_ctx
,
9439 get_session_info_system(),
9441 lp_const_servicename(snum
),
9443 if (!W_ERROR_IS_OK(result
)) {
9447 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
9449 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9450 count
, prt_status
.status
, prt_status
.message
));
9452 switch (r
->in
.level
) {
9454 result
= getjob_level_1(p
->mem_ctx
,
9455 queue
, count
, snum
, pinfo2
,
9456 r
->in
.job_id
, &r
->out
.info
->info1
);
9459 result
= getjob_level_2(p
->mem_ctx
,
9460 queue
, count
, snum
, pinfo2
,
9461 r
->in
.job_id
, &r
->out
.info
->info2
);
9464 result
= WERR_UNKNOWN_LEVEL
;
9469 TALLOC_FREE(pinfo2
);
9471 if (!W_ERROR_IS_OK(result
)) {
9472 TALLOC_FREE(r
->out
.info
);
9476 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, r
->out
.info
,
9478 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9480 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9483 /****************************************************************
9484 _spoolss_GetPrinterDataEx
9485 ****************************************************************/
9487 WERROR
_spoolss_GetPrinterDataEx(struct pipes_struct
*p
,
9488 struct spoolss_GetPrinterDataEx
*r
)
9491 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9492 const char *printer
;
9494 WERROR result
= WERR_OK
;
9496 enum winreg_Type val_type
= REG_NONE
;
9497 uint8_t *val_data
= NULL
;
9498 uint32_t val_size
= 0;
9499 struct dcerpc_binding_handle
*b
;
9500 TALLOC_CTX
*tmp_ctx
;
9502 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9504 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9505 r
->in
.key_name
, r
->in
.value_name
));
9507 /* in case of problem, return some default values */
9510 *r
->out
.type
= REG_NONE
;
9512 tmp_ctx
= talloc_new(p
->mem_ctx
);
9518 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9519 OUR_HANDLE(r
->in
.handle
)));
9520 result
= WERR_BADFID
;
9524 /* check to see if the keyname is valid */
9525 if (!strlen(r
->in
.key_name
)) {
9526 result
= WERR_INVALID_PARAM
;
9530 /* Is the handle to a printer or to the server? */
9532 if (Printer
->printer_type
== SPLHND_SERVER
) {
9534 union spoolss_PrinterData data
;
9536 result
= getprinterdata_printer_server(tmp_ctx
,
9540 if (!W_ERROR_IS_OK(result
)) {
9544 result
= push_spoolss_PrinterData(tmp_ctx
, &blob
,
9545 *r
->out
.type
, &data
);
9546 if (!W_ERROR_IS_OK(result
)) {
9550 *r
->out
.needed
= blob
.length
;
9552 if (r
->in
.offered
>= *r
->out
.needed
) {
9553 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
9560 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9561 result
= WERR_BADFID
;
9564 printer
= lp_const_servicename(snum
);
9566 result
= winreg_printer_binding_handle(tmp_ctx
,
9567 get_session_info_system(),
9570 if (!W_ERROR_IS_OK(result
)) {
9574 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9575 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
9576 strequal(r
->in
.value_name
, "ChangeId")) {
9577 *r
->out
.type
= REG_DWORD
;
9579 if (r
->in
.offered
>= *r
->out
.needed
) {
9580 uint32_t changeid
= 0;
9582 result
= winreg_printer_get_changeid(tmp_ctx
, b
,
9585 if (!W_ERROR_IS_OK(result
)) {
9589 SIVAL(r
->out
.data
, 0, changeid
);
9595 result
= winreg_get_printer_dataex(tmp_ctx
, b
,
9602 if (!W_ERROR_IS_OK(result
)) {
9606 *r
->out
.needed
= val_size
;
9607 *r
->out
.type
= val_type
;
9609 if (r
->in
.offered
>= *r
->out
.needed
) {
9610 memcpy(r
->out
.data
, val_data
, val_size
);
9614 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9616 if (W_ERROR_IS_OK(result
)) {
9617 result
= SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9620 talloc_free(tmp_ctx
);
9624 /****************************************************************
9625 _spoolss_SetPrinterDataEx
9626 ****************************************************************/
9628 WERROR
_spoolss_SetPrinterDataEx(struct pipes_struct
*p
,
9629 struct spoolss_SetPrinterDataEx
*r
)
9631 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
9633 WERROR result
= WERR_OK
;
9634 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9636 struct dcerpc_binding_handle
*b
;
9637 TALLOC_CTX
*tmp_ctx
;
9639 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9641 /* From MSDN documentation of SetPrinterDataEx: pass request to
9642 SetPrinterData if key is "PrinterDriverData" */
9645 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9646 OUR_HANDLE(r
->in
.handle
)));
9650 if (Printer
->printer_type
== SPLHND_SERVER
) {
9651 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9652 "Not implemented for server handles yet\n"));
9653 return WERR_INVALID_PARAM
;
9656 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9661 * Access check : NT returns "access denied" if you make a
9662 * SetPrinterData call without the necessary privildge.
9663 * we were originally returning OK if nothing changed
9664 * which made Win2k issue **a lot** of SetPrinterData
9665 * when connecting to a printer --jerry
9668 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9669 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9670 "change denied by handle access permissions\n"));
9671 return WERR_ACCESS_DENIED
;
9674 tmp_ctx
= talloc_new(p
->mem_ctx
);
9679 result
= winreg_printer_binding_handle(tmp_ctx
,
9680 get_session_info_system(),
9683 if (!W_ERROR_IS_OK(result
)) {
9687 result
= winreg_get_printer(tmp_ctx
, b
,
9688 lp_servicename(talloc_tos(), snum
),
9690 if (!W_ERROR_IS_OK(result
)) {
9694 /* check for OID in valuename */
9696 oid_string
= strchr(r
->in
.value_name
, ',');
9702 /* save the registry data */
9704 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
9712 if (W_ERROR_IS_OK(result
)) {
9713 /* save the OID if one was specified */
9715 char *str
= talloc_asprintf(tmp_ctx
, "%s\\%s",
9716 r
->in
.key_name
, SPOOL_OID_KEY
);
9718 result
= WERR_NOMEM
;
9723 * I'm not checking the status here on purpose. Don't know
9724 * if this is right, but I'm returning the status from the
9725 * previous set_printer_dataex() call. I have no idea if
9726 * this is right. --jerry
9728 winreg_set_printer_dataex(tmp_ctx
, b
,
9733 (uint8_t *) oid_string
,
9734 strlen(oid_string
) + 1);
9737 result
= winreg_printer_update_changeid(tmp_ctx
, b
,
9738 lp_const_servicename(snum
));
9743 talloc_free(tmp_ctx
);
9747 /****************************************************************
9748 _spoolss_DeletePrinterDataEx
9749 ****************************************************************/
9751 WERROR
_spoolss_DeletePrinterDataEx(struct pipes_struct
*p
,
9752 struct spoolss_DeletePrinterDataEx
*r
)
9754 const char *printer
;
9756 WERROR status
= WERR_OK
;
9757 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9759 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9762 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9763 "Invalid handle (%s:%u:%u).\n",
9764 OUR_HANDLE(r
->in
.handle
)));
9768 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9769 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9770 "printer properties change denied by handle\n"));
9771 return WERR_ACCESS_DENIED
;
9774 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
9778 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9781 printer
= lp_const_servicename(snum
);
9783 status
= winreg_delete_printer_dataex_internal(p
->mem_ctx
,
9784 get_session_info_system(),
9789 if (W_ERROR_IS_OK(status
)) {
9790 status
= winreg_printer_update_changeid_internal(p
->mem_ctx
,
9791 get_session_info_system(),
9799 /****************************************************************
9800 _spoolss_EnumPrinterKey
9801 ****************************************************************/
9803 WERROR
_spoolss_EnumPrinterKey(struct pipes_struct
*p
,
9804 struct spoolss_EnumPrinterKey
*r
)
9807 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9809 WERROR result
= WERR_BADFILE
;
9810 const char **array
= NULL
;
9813 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9816 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9817 OUR_HANDLE(r
->in
.handle
)));
9821 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9825 result
= winreg_enum_printer_key_internal(p
->mem_ctx
,
9826 get_session_info_system(),
9828 lp_const_servicename(snum
),
9832 if (!W_ERROR_IS_OK(result
)) {
9836 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
9837 result
= WERR_NOMEM
;
9841 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
9842 *r
->out
.needed
= blob
.length
;
9844 if (r
->in
.offered
< *r
->out
.needed
) {
9845 result
= WERR_MORE_DATA
;
9848 r
->out
.key_buffer
->string_array
= array
;
9852 if (!W_ERROR_IS_OK(result
)) {
9854 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
9862 /****************************************************************
9863 _spoolss_DeletePrinterKey
9864 ****************************************************************/
9866 WERROR
_spoolss_DeletePrinterKey(struct pipes_struct
*p
,
9867 struct spoolss_DeletePrinterKey
*r
)
9869 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9872 const char *printer
;
9873 struct dcerpc_binding_handle
*b
;
9874 TALLOC_CTX
*tmp_ctx
;
9876 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9879 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9880 OUR_HANDLE(r
->in
.handle
)));
9884 /* if keyname == NULL, return error */
9885 if ( !r
->in
.key_name
)
9886 return WERR_INVALID_PARAM
;
9888 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9892 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9893 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9894 "printer properties change denied by handle\n"));
9895 return WERR_ACCESS_DENIED
;
9898 printer
= lp_const_servicename(snum
);
9900 tmp_ctx
= talloc_new(p
->mem_ctx
);
9905 status
= winreg_printer_binding_handle(tmp_ctx
,
9906 get_session_info_system(),
9909 if (!W_ERROR_IS_OK(status
)) {
9913 /* delete the key and all subkeys */
9914 status
= winreg_delete_printer_key(tmp_ctx
, b
,
9917 if (W_ERROR_IS_OK(status
)) {
9918 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
9923 talloc_free(tmp_ctx
);
9927 /****************************************************************
9928 _spoolss_EnumPrinterDataEx
9929 ****************************************************************/
9931 WERROR
_spoolss_EnumPrinterDataEx(struct pipes_struct
*p
,
9932 struct spoolss_EnumPrinterDataEx
*r
)
9935 struct spoolss_PrinterEnumValues
*info
= NULL
;
9936 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9940 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9944 *r
->out
.info
= NULL
;
9947 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9948 OUR_HANDLE(r
->in
.handle
)));
9953 * first check for a keyname of NULL or "". Win2k seems to send
9954 * this a lot and we should send back WERR_INVALID_PARAM
9955 * no need to spend time looking up the printer in this case.
9959 if (!strlen(r
->in
.key_name
)) {
9960 result
= WERR_INVALID_PARAM
;
9964 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9968 /* now look for a match on the key name */
9969 result
= winreg_enum_printer_dataex_internal(p
->mem_ctx
,
9970 get_session_info_system(),
9972 lp_const_servicename(snum
),
9976 if (!W_ERROR_IS_OK(result
)) {
9980 #if 0 /* FIXME - gd */
9981 /* housekeeping information in the reply */
9983 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9984 * the hand marshalled container size is a multiple
9985 * of 4 bytes for RPC alignment.
9989 needed
+= 4-(needed
% 4);
9992 *r
->out
.count
= count
;
9993 *r
->out
.info
= info
;
9996 if (!W_ERROR_IS_OK(result
)) {
10000 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
10001 spoolss_EnumPrinterDataEx
,
10004 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
10005 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
10007 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
10010 /****************************************************************************
10011 ****************************************************************************/
10013 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
10014 const char *servername
,
10015 const char *environment
,
10016 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
10021 werr
= compose_spoolss_server_path(mem_ctx
,
10024 SPOOLSS_PRTPROCS_PATH
,
10026 if (!W_ERROR_IS_OK(werr
)) {
10030 DEBUG(4,("print processor directory: [%s]\n", path
));
10032 r
->directory_name
= path
;
10037 /****************************************************************
10038 _spoolss_GetPrintProcessorDirectory
10039 ****************************************************************/
10041 WERROR
_spoolss_GetPrintProcessorDirectory(struct pipes_struct
*p
,
10042 struct spoolss_GetPrintProcessorDirectory
*r
)
10045 char *prnproc_share
= NULL
;
10046 bool prnproc_share_exists
= false;
10049 /* that's an [in out] buffer */
10051 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
10052 return WERR_INVALID_PARAM
;
10055 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10058 *r
->out
.needed
= 0;
10060 /* r->in.level is ignored */
10062 /* We always should reply with a local print processor directory so that
10063 * users are not forced to have a [prnproc$] share on the Samba spoolss
10064 * server, if users decide to do so, lets announce it though - Guenther */
10066 snum
= find_service(talloc_tos(), "prnproc$", &prnproc_share
);
10067 if (!prnproc_share
) {
10071 prnproc_share_exists
= true;
10074 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
10075 prnproc_share_exists
? r
->in
.server
: NULL
,
10077 &r
->out
.info
->info1
);
10078 if (!W_ERROR_IS_OK(result
)) {
10079 TALLOC_FREE(r
->out
.info
);
10083 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
,
10084 r
->out
.info
, r
->in
.level
);
10085 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
10087 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
10090 /*******************************************************************
10091 ********************************************************************/
10093 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
10094 const char *dllname
)
10096 enum ndr_err_code ndr_err
;
10097 struct spoolss_MonitorUi ui
;
10099 ui
.dll_name
= dllname
;
10101 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, &ui
,
10102 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
10103 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
10104 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
10106 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
10109 /*******************************************************************
10110 Streams the monitor UI DLL name in UNICODE
10111 *******************************************************************/
10113 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
10114 struct security_token
*token
, DATA_BLOB
*in
,
10115 DATA_BLOB
*out
, uint32_t *needed
)
10117 const char *dllname
= "tcpmonui.dll";
10119 *needed
= (strlen(dllname
)+1) * 2;
10121 if (out
->length
< *needed
) {
10122 return WERR_INSUFFICIENT_BUFFER
;
10125 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
10132 /*******************************************************************
10133 ********************************************************************/
10135 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
10136 struct spoolss_PortData1
*port1
,
10137 const DATA_BLOB
*buf
)
10139 enum ndr_err_code ndr_err
;
10140 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port1
,
10141 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
10142 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
10143 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
10145 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
10148 /*******************************************************************
10149 ********************************************************************/
10151 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
10152 struct spoolss_PortData2
*port2
,
10153 const DATA_BLOB
*buf
)
10155 enum ndr_err_code ndr_err
;
10156 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port2
,
10157 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
10158 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
10159 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
10161 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
10164 /*******************************************************************
10165 Create a new TCP/IP port
10166 *******************************************************************/
10168 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
10169 struct security_token
*token
, DATA_BLOB
*in
,
10170 DATA_BLOB
*out
, uint32_t *needed
)
10172 struct spoolss_PortData1 port1
;
10173 struct spoolss_PortData2 port2
;
10174 char *device_uri
= NULL
;
10177 const char *portname
;
10178 const char *hostaddress
;
10180 uint32_t port_number
;
10183 /* peek for spoolss_PortData version */
10185 if (!in
|| (in
->length
< (128 + 4))) {
10186 return WERR_GENERAL_FAILURE
;
10189 version
= IVAL(in
->data
, 128);
10193 ZERO_STRUCT(port1
);
10195 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
10199 portname
= port1
.portname
;
10200 hostaddress
= port1
.hostaddress
;
10201 queue
= port1
.queue
;
10202 protocol
= port1
.protocol
;
10203 port_number
= port1
.port_number
;
10207 ZERO_STRUCT(port2
);
10209 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
10213 portname
= port2
.portname
;
10214 hostaddress
= port2
.hostaddress
;
10215 queue
= port2
.queue
;
10216 protocol
= port2
.protocol
;
10217 port_number
= port2
.port_number
;
10221 DEBUG(1,("xcvtcp_addport: "
10222 "unknown version of port_data: %d\n", version
));
10223 return WERR_UNKNOWN_PORT
;
10226 /* create the device URI and call the add_port_hook() */
10228 switch (protocol
) {
10229 case PROTOCOL_RAWTCP_TYPE
:
10230 device_uri
= talloc_asprintf(mem_ctx
,
10231 "socket://%s:%d/", hostaddress
,
10235 case PROTOCOL_LPR_TYPE
:
10236 device_uri
= talloc_asprintf(mem_ctx
,
10237 "lpr://%s/%s", hostaddress
, queue
);
10241 return WERR_UNKNOWN_PORT
;
10248 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
10251 /*******************************************************************
10252 *******************************************************************/
10254 struct xcv_api_table xcvtcp_cmds
[] = {
10255 { "MonitorUI", xcvtcp_monitorui
},
10256 { "AddPort", xcvtcp_addport
},
10260 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
10261 struct security_token
*token
, const char *command
,
10268 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
10270 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
10271 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
10272 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
10275 return WERR_BADFUNC
;
10278 /*******************************************************************
10279 *******************************************************************/
10280 #if 0 /* don't support management using the "Local Port" monitor */
10282 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
10283 struct security_token
*token
, DATA_BLOB
*in
,
10284 DATA_BLOB
*out
, uint32_t *needed
)
10286 const char *dllname
= "localui.dll";
10288 *needed
= (strlen(dllname
)+1) * 2;
10290 if (out
->length
< *needed
) {
10291 return WERR_INSUFFICIENT_BUFFER
;
10294 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
10301 /*******************************************************************
10302 *******************************************************************/
10304 struct xcv_api_table xcvlocal_cmds
[] = {
10305 { "MonitorUI", xcvlocal_monitorui
},
10309 struct xcv_api_table xcvlocal_cmds
[] = {
10316 /*******************************************************************
10317 *******************************************************************/
10319 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
10320 struct security_token
*token
, const char *command
,
10321 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
10326 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
10328 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
10329 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
10330 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
10332 return WERR_BADFUNC
;
10335 /****************************************************************
10337 ****************************************************************/
10339 WERROR
_spoolss_XcvData(struct pipes_struct
*p
,
10340 struct spoolss_XcvData
*r
)
10342 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
10343 DATA_BLOB out_data
= data_blob_null
;
10347 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10348 OUR_HANDLE(r
->in
.handle
)));
10349 return WERR_BADFID
;
10352 /* Has to be a handle to the TCP/IP port monitor */
10354 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
10355 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10356 return WERR_BADFID
;
10359 /* requires administrative access to the server */
10361 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
10362 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10363 return WERR_ACCESS_DENIED
;
10366 /* Allocate the outgoing buffer */
10368 if (r
->in
.out_data_size
) {
10369 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
10370 if (out_data
.data
== NULL
) {
10375 switch ( Printer
->printer_type
) {
10376 case SPLHND_PORTMON_TCP
:
10377 werror
= process_xcvtcp_command(p
->mem_ctx
,
10378 p
->session_info
->security_token
,
10379 r
->in
.function_name
,
10380 &r
->in
.in_data
, &out_data
,
10383 case SPLHND_PORTMON_LOCAL
:
10384 werror
= process_xcvlocal_command(p
->mem_ctx
,
10385 p
->session_info
->security_token
,
10386 r
->in
.function_name
,
10387 &r
->in
.in_data
, &out_data
,
10391 werror
= WERR_INVALID_PRINT_MONITOR
;
10394 if (!W_ERROR_IS_OK(werror
)) {
10398 *r
->out
.status_code
= 0;
10400 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
10401 memcpy(r
->out
.out_data
, out_data
.data
,
10402 MIN(r
->in
.out_data_size
, out_data
.length
));
10408 /****************************************************************
10409 _spoolss_AddPrintProcessor
10410 ****************************************************************/
10412 WERROR
_spoolss_AddPrintProcessor(struct pipes_struct
*p
,
10413 struct spoolss_AddPrintProcessor
*r
)
10415 /* for now, just indicate success and ignore the add. We'll
10416 automatically set the winprint processor for printer
10417 entries later. Used to debug the LexMark Optra S 1855 PCL
10423 /****************************************************************
10425 ****************************************************************/
10427 WERROR
_spoolss_AddPort(struct pipes_struct
*p
,
10428 struct spoolss_AddPort
*r
)
10430 /* do what w2k3 does */
10432 return WERR_NOT_SUPPORTED
;
10435 /****************************************************************
10436 _spoolss_GetPrinterDriver
10437 ****************************************************************/
10439 WERROR
_spoolss_GetPrinterDriver(struct pipes_struct
*p
,
10440 struct spoolss_GetPrinterDriver
*r
)
10442 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10443 return WERR_NOT_SUPPORTED
;
10446 /****************************************************************
10447 _spoolss_ReadPrinter
10448 ****************************************************************/
10450 WERROR
_spoolss_ReadPrinter(struct pipes_struct
*p
,
10451 struct spoolss_ReadPrinter
*r
)
10453 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10454 return WERR_NOT_SUPPORTED
;
10457 /****************************************************************
10458 _spoolss_WaitForPrinterChange
10459 ****************************************************************/
10461 WERROR
_spoolss_WaitForPrinterChange(struct pipes_struct
*p
,
10462 struct spoolss_WaitForPrinterChange
*r
)
10464 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10465 return WERR_NOT_SUPPORTED
;
10468 /****************************************************************
10469 _spoolss_ConfigurePort
10470 ****************************************************************/
10472 WERROR
_spoolss_ConfigurePort(struct pipes_struct
*p
,
10473 struct spoolss_ConfigurePort
*r
)
10475 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10476 return WERR_NOT_SUPPORTED
;
10479 /****************************************************************
10480 _spoolss_DeletePort
10481 ****************************************************************/
10483 WERROR
_spoolss_DeletePort(struct pipes_struct
*p
,
10484 struct spoolss_DeletePort
*r
)
10486 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10487 return WERR_NOT_SUPPORTED
;
10490 /****************************************************************
10491 _spoolss_CreatePrinterIC
10492 ****************************************************************/
10494 WERROR
_spoolss_CreatePrinterIC(struct pipes_struct
*p
,
10495 struct spoolss_CreatePrinterIC
*r
)
10497 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10498 return WERR_NOT_SUPPORTED
;
10501 /****************************************************************
10502 _spoolss_PlayGDIScriptOnPrinterIC
10503 ****************************************************************/
10505 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct
*p
,
10506 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
10508 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10509 return WERR_NOT_SUPPORTED
;
10512 /****************************************************************
10513 _spoolss_DeletePrinterIC
10514 ****************************************************************/
10516 WERROR
_spoolss_DeletePrinterIC(struct pipes_struct
*p
,
10517 struct spoolss_DeletePrinterIC
*r
)
10519 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10520 return WERR_NOT_SUPPORTED
;
10523 /****************************************************************
10524 _spoolss_AddPrinterConnection
10525 ****************************************************************/
10527 WERROR
_spoolss_AddPrinterConnection(struct pipes_struct
*p
,
10528 struct spoolss_AddPrinterConnection
*r
)
10530 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10531 return WERR_NOT_SUPPORTED
;
10534 /****************************************************************
10535 _spoolss_DeletePrinterConnection
10536 ****************************************************************/
10538 WERROR
_spoolss_DeletePrinterConnection(struct pipes_struct
*p
,
10539 struct spoolss_DeletePrinterConnection
*r
)
10541 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10542 return WERR_NOT_SUPPORTED
;
10545 /****************************************************************
10546 _spoolss_PrinterMessageBox
10547 ****************************************************************/
10549 WERROR
_spoolss_PrinterMessageBox(struct pipes_struct
*p
,
10550 struct spoolss_PrinterMessageBox
*r
)
10552 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10553 return WERR_NOT_SUPPORTED
;
10556 /****************************************************************
10557 _spoolss_AddMonitor
10558 ****************************************************************/
10560 WERROR
_spoolss_AddMonitor(struct pipes_struct
*p
,
10561 struct spoolss_AddMonitor
*r
)
10563 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10564 return WERR_NOT_SUPPORTED
;
10567 /****************************************************************
10568 _spoolss_DeleteMonitor
10569 ****************************************************************/
10571 WERROR
_spoolss_DeleteMonitor(struct pipes_struct
*p
,
10572 struct spoolss_DeleteMonitor
*r
)
10574 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10575 return WERR_NOT_SUPPORTED
;
10578 /****************************************************************
10579 _spoolss_DeletePrintProcessor
10580 ****************************************************************/
10582 WERROR
_spoolss_DeletePrintProcessor(struct pipes_struct
*p
,
10583 struct spoolss_DeletePrintProcessor
*r
)
10585 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10586 return WERR_NOT_SUPPORTED
;
10589 /****************************************************************
10590 _spoolss_AddPrintProvidor
10591 ****************************************************************/
10593 WERROR
_spoolss_AddPrintProvidor(struct pipes_struct
*p
,
10594 struct spoolss_AddPrintProvidor
*r
)
10596 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10597 return WERR_NOT_SUPPORTED
;
10600 /****************************************************************
10601 _spoolss_DeletePrintProvidor
10602 ****************************************************************/
10604 WERROR
_spoolss_DeletePrintProvidor(struct pipes_struct
*p
,
10605 struct spoolss_DeletePrintProvidor
*r
)
10607 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10608 return WERR_NOT_SUPPORTED
;
10611 /****************************************************************
10612 _spoolss_FindFirstPrinterChangeNotification
10613 ****************************************************************/
10615 WERROR
_spoolss_FindFirstPrinterChangeNotification(struct pipes_struct
*p
,
10616 struct spoolss_FindFirstPrinterChangeNotification
*r
)
10618 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10619 return WERR_NOT_SUPPORTED
;
10622 /****************************************************************
10623 _spoolss_FindNextPrinterChangeNotification
10624 ****************************************************************/
10626 WERROR
_spoolss_FindNextPrinterChangeNotification(struct pipes_struct
*p
,
10627 struct spoolss_FindNextPrinterChangeNotification
*r
)
10629 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10630 return WERR_NOT_SUPPORTED
;
10633 /****************************************************************
10634 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10635 ****************************************************************/
10637 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct
*p
,
10638 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
10640 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10641 return WERR_NOT_SUPPORTED
;
10644 /****************************************************************
10645 _spoolss_ReplyOpenPrinter
10646 ****************************************************************/
10648 WERROR
_spoolss_ReplyOpenPrinter(struct pipes_struct
*p
,
10649 struct spoolss_ReplyOpenPrinter
*r
)
10651 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10652 return WERR_NOT_SUPPORTED
;
10655 /****************************************************************
10656 _spoolss_RouterReplyPrinter
10657 ****************************************************************/
10659 WERROR
_spoolss_RouterReplyPrinter(struct pipes_struct
*p
,
10660 struct spoolss_RouterReplyPrinter
*r
)
10662 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10663 return WERR_NOT_SUPPORTED
;
10666 /****************************************************************
10667 _spoolss_ReplyClosePrinter
10668 ****************************************************************/
10670 WERROR
_spoolss_ReplyClosePrinter(struct pipes_struct
*p
,
10671 struct spoolss_ReplyClosePrinter
*r
)
10673 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10674 return WERR_NOT_SUPPORTED
;
10677 /****************************************************************
10679 ****************************************************************/
10681 WERROR
_spoolss_AddPortEx(struct pipes_struct
*p
,
10682 struct spoolss_AddPortEx
*r
)
10684 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10685 return WERR_NOT_SUPPORTED
;
10688 /****************************************************************
10689 _spoolss_RouterFindFirstPrinterChangeNotification
10690 ****************************************************************/
10692 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct
*p
,
10693 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
10695 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10696 return WERR_NOT_SUPPORTED
;
10699 /****************************************************************
10700 _spoolss_SpoolerInit
10701 ****************************************************************/
10703 WERROR
_spoolss_SpoolerInit(struct pipes_struct
*p
,
10704 struct spoolss_SpoolerInit
*r
)
10706 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10707 return WERR_NOT_SUPPORTED
;
10710 /****************************************************************
10711 _spoolss_ResetPrinterEx
10712 ****************************************************************/
10714 WERROR
_spoolss_ResetPrinterEx(struct pipes_struct
*p
,
10715 struct spoolss_ResetPrinterEx
*r
)
10717 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10718 return WERR_NOT_SUPPORTED
;
10721 /****************************************************************
10722 _spoolss_RouterReplyPrinterEx
10723 ****************************************************************/
10725 WERROR
_spoolss_RouterReplyPrinterEx(struct pipes_struct
*p
,
10726 struct spoolss_RouterReplyPrinterEx
*r
)
10728 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10729 return WERR_NOT_SUPPORTED
;
10732 /****************************************************************
10734 ****************************************************************/
10736 WERROR
_spoolss_44(struct pipes_struct
*p
,
10737 struct spoolss_44
*r
)
10739 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10740 return WERR_NOT_SUPPORTED
;
10743 /****************************************************************
10745 ****************************************************************/
10747 WERROR
_spoolss_SetPort(struct pipes_struct
*p
,
10748 struct spoolss_SetPort
*r
)
10750 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10751 return WERR_NOT_SUPPORTED
;
10754 /****************************************************************
10756 ****************************************************************/
10758 WERROR
_spoolss_4a(struct pipes_struct
*p
,
10759 struct spoolss_4a
*r
)
10761 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10762 return WERR_NOT_SUPPORTED
;
10765 /****************************************************************
10767 ****************************************************************/
10769 WERROR
_spoolss_4b(struct pipes_struct
*p
,
10770 struct spoolss_4b
*r
)
10772 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10773 return WERR_NOT_SUPPORTED
;
10776 /****************************************************************
10778 ****************************************************************/
10780 WERROR
_spoolss_4c(struct pipes_struct
*p
,
10781 struct spoolss_4c
*r
)
10783 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10784 return WERR_NOT_SUPPORTED
;
10787 /****************************************************************
10789 ****************************************************************/
10791 WERROR
_spoolss_53(struct pipes_struct
*p
,
10792 struct spoolss_53
*r
)
10794 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10795 return WERR_NOT_SUPPORTED
;
10798 /****************************************************************
10799 _spoolss_AddPerMachineConnection
10800 ****************************************************************/
10802 WERROR
_spoolss_AddPerMachineConnection(struct pipes_struct
*p
,
10803 struct spoolss_AddPerMachineConnection
*r
)
10805 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10806 return WERR_NOT_SUPPORTED
;
10809 /****************************************************************
10810 _spoolss_DeletePerMachineConnection
10811 ****************************************************************/
10813 WERROR
_spoolss_DeletePerMachineConnection(struct pipes_struct
*p
,
10814 struct spoolss_DeletePerMachineConnection
*r
)
10816 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10817 return WERR_NOT_SUPPORTED
;
10820 /****************************************************************
10821 _spoolss_EnumPerMachineConnections
10822 ****************************************************************/
10824 WERROR
_spoolss_EnumPerMachineConnections(struct pipes_struct
*p
,
10825 struct spoolss_EnumPerMachineConnections
*r
)
10827 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10828 return WERR_NOT_SUPPORTED
;
10831 /****************************************************************
10833 ****************************************************************/
10835 WERROR
_spoolss_5a(struct pipes_struct
*p
,
10836 struct spoolss_5a
*r
)
10838 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10839 return WERR_NOT_SUPPORTED
;
10842 /****************************************************************
10844 ****************************************************************/
10846 WERROR
_spoolss_5b(struct pipes_struct
*p
,
10847 struct spoolss_5b
*r
)
10849 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10850 return WERR_NOT_SUPPORTED
;
10853 /****************************************************************
10855 ****************************************************************/
10857 WERROR
_spoolss_5c(struct pipes_struct
*p
,
10858 struct spoolss_5c
*r
)
10860 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10861 return WERR_NOT_SUPPORTED
;
10864 /****************************************************************
10866 ****************************************************************/
10868 WERROR
_spoolss_5d(struct pipes_struct
*p
,
10869 struct spoolss_5d
*r
)
10871 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10872 return WERR_NOT_SUPPORTED
;
10875 /****************************************************************
10877 ****************************************************************/
10879 WERROR
_spoolss_5e(struct pipes_struct
*p
,
10880 struct spoolss_5e
*r
)
10882 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10883 return WERR_NOT_SUPPORTED
;
10886 /****************************************************************
10888 ****************************************************************/
10890 WERROR
_spoolss_5f(struct pipes_struct
*p
,
10891 struct spoolss_5f
*r
)
10893 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10894 return WERR_NOT_SUPPORTED
;
10897 /****************************************************************
10899 ****************************************************************/
10901 WERROR
_spoolss_60(struct pipes_struct
*p
,
10902 struct spoolss_60
*r
)
10904 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10905 return WERR_NOT_SUPPORTED
;
10908 /****************************************************************
10909 _spoolss_RpcSendRecvBidiData
10910 ****************************************************************/
10912 WERROR
_spoolss_RpcSendRecvBidiData(struct pipes_struct
*p
,
10913 struct spoolss_RpcSendRecvBidiData
*r
)
10915 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10916 return WERR_NOT_SUPPORTED
;
10919 /****************************************************************
10921 ****************************************************************/
10923 WERROR
_spoolss_62(struct pipes_struct
*p
,
10924 struct spoolss_62
*r
)
10926 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10927 return WERR_NOT_SUPPORTED
;
10930 /****************************************************************
10932 ****************************************************************/
10934 WERROR
_spoolss_63(struct pipes_struct
*p
,
10935 struct spoolss_63
*r
)
10937 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10938 return WERR_NOT_SUPPORTED
;
10941 /****************************************************************
10943 ****************************************************************/
10945 WERROR
_spoolss_64(struct pipes_struct
*p
,
10946 struct spoolss_64
*r
)
10948 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10949 return WERR_NOT_SUPPORTED
;
10952 /****************************************************************
10954 ****************************************************************/
10956 WERROR
_spoolss_65(struct pipes_struct
*p
,
10957 struct spoolss_65
*r
)
10959 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10960 return WERR_NOT_SUPPORTED
;
10963 /****************************************************************
10964 _spoolss_GetCorePrinterDrivers
10965 ****************************************************************/
10967 WERROR
_spoolss_GetCorePrinterDrivers(struct pipes_struct
*p
,
10968 struct spoolss_GetCorePrinterDrivers
*r
)
10970 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10971 return WERR_NOT_SUPPORTED
;
10974 /****************************************************************
10976 ****************************************************************/
10978 WERROR
_spoolss_67(struct pipes_struct
*p
,
10979 struct spoolss_67
*r
)
10981 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10982 return WERR_NOT_SUPPORTED
;
10985 /****************************************************************
10986 _spoolss_GetPrinterDriverPackagePath
10987 ****************************************************************/
10989 WERROR
_spoolss_GetPrinterDriverPackagePath(struct pipes_struct
*p
,
10990 struct spoolss_GetPrinterDriverPackagePath
*r
)
10992 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
10993 return WERR_NOT_SUPPORTED
;
10996 /****************************************************************
10998 ****************************************************************/
11000 WERROR
_spoolss_69(struct pipes_struct
*p
,
11001 struct spoolss_69
*r
)
11003 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11004 return WERR_NOT_SUPPORTED
;
11007 /****************************************************************
11009 ****************************************************************/
11011 WERROR
_spoolss_6a(struct pipes_struct
*p
,
11012 struct spoolss_6a
*r
)
11014 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11015 return WERR_NOT_SUPPORTED
;
11018 /****************************************************************
11020 ****************************************************************/
11022 WERROR
_spoolss_6b(struct pipes_struct
*p
,
11023 struct spoolss_6b
*r
)
11025 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11026 return WERR_NOT_SUPPORTED
;
11029 /****************************************************************
11031 ****************************************************************/
11033 WERROR
_spoolss_6c(struct pipes_struct
*p
,
11034 struct spoolss_6c
*r
)
11036 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11037 return WERR_NOT_SUPPORTED
;
11040 /****************************************************************
11042 ****************************************************************/
11044 WERROR
_spoolss_6d(struct pipes_struct
*p
,
11045 struct spoolss_6d
*r
)
11047 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11048 return WERR_NOT_SUPPORTED
;
11051 /****************************************************************
11052 _spoolss_RpcGetJobNamedPropertyValue
11053 ****************************************************************/
11055 WERROR
_spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct
*p
,
11056 struct spoolss_RpcGetJobNamedPropertyValue
*r
)
11058 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11059 return WERR_NOT_SUPPORTED
;
11062 /****************************************************************
11063 _spoolss_RpcSetJobNamedProperty
11064 ****************************************************************/
11066 WERROR
_spoolss_RpcSetJobNamedProperty(struct pipes_struct
*p
,
11067 struct spoolss_RpcSetJobNamedProperty
*r
)
11069 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11070 return WERR_NOT_SUPPORTED
;
11073 /****************************************************************
11074 _spoolss_RpcDeleteJobNamedProperty
11075 ****************************************************************/
11077 WERROR
_spoolss_RpcDeleteJobNamedProperty(struct pipes_struct
*p
,
11078 struct spoolss_RpcDeleteJobNamedProperty
*r
)
11080 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11081 return WERR_NOT_SUPPORTED
;
11084 /****************************************************************
11085 _spoolss_RpcEnumJobNamedProperties
11086 ****************************************************************/
11088 WERROR
_spoolss_RpcEnumJobNamedProperties(struct pipes_struct
*p
,
11089 struct spoolss_RpcEnumJobNamedProperties
*r
)
11091 p
->fault_state
= DCERPC_FAULT_OP_RNG_ERROR
;
11092 return WERR_NOT_SUPPORTED
;