2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
41 #include "registry/reg_objects.h"
42 #include "include/printing.h"
44 #include "../librpc/gen_ndr/netlogon.h"
46 #include "printing/notify.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
50 #include "smbd/globals.h"
53 #include "rpc_server/spoolss/srv_spoolss_nt.h"
55 #include "libsmb/libsmb.h"
56 #include "printing/printer_list.h"
57 #include "../lib/tsocket/tsocket.h"
58 #include "rpc_client/cli_winreg_spoolss.h"
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62 ((info)?ndr_size_##fn(info, level, 0):0)
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
73 #define DBGC_CLASS DBGC_RPC_SRV
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
79 struct notify_back_channel
;
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle
{
86 struct printer_handle
*prev
, *next
;
87 bool document_started
;
89 uint32 jobid
; /* jobid in printing backend */
91 const char *servername
;
94 uint32 access_granted
;
100 struct spoolss_NotifyOption
*option
;
101 struct policy_handle cli_hnd
;
102 struct notify_back_channel
*cli_chan
;
104 /* are we in a FindNextPrinterChangeNotify() call? */
106 struct messaging_context
*msg_ctx
;
113 /* devmode sent in the OpenPrinter() call */
114 struct spoolss_DeviceMode
*devmode
;
116 /* TODO cache the printer info2 structure */
117 struct spoolss_PrinterInfo2
*info2
;
121 static struct printer_handle
*printers_list
;
123 struct printer_session_counter
{
124 struct printer_session_counter
*next
;
125 struct printer_session_counter
*prev
;
131 static struct printer_session_counter
*counter_list
;
133 struct notify_back_channel
{
134 struct notify_back_channel
*prev
, *next
;
136 /* associated client */
137 struct sockaddr_storage client_address
;
139 /* print notify back-channel pipe handle*/
140 struct rpc_pipe_client
*cli_pipe
;
141 uint32_t active_connections
;
144 static struct notify_back_channel
*back_channels
;
146 /* Map generic permissions to printer object specific permissions */
148 const struct standard_mapping printer_std_mapping
= {
155 /* Map generic permissions to print server object specific permissions */
157 const struct standard_mapping printserver_std_mapping
= {
164 /* API table for Xcv Monitor functions */
166 struct xcv_api_table
{
168 WERROR(*fn
) (TALLOC_CTX
*mem_ctx
, struct security_token
*token
, DATA_BLOB
*in
, DATA_BLOB
*out
, uint32_t *needed
);
171 static void prune_printername_cache(void);
173 /********************************************************************
174 * Canonicalize servername.
175 ********************************************************************/
177 static const char *canon_servername(const char *servername
)
179 const char *pservername
= servername
;
180 while (*pservername
== '\\') {
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v
)
193 return JOB_STATUS_PAUSED
;
195 return JOB_STATUS_SPOOLING
;
197 return JOB_STATUS_PRINTING
;
199 return JOB_STATUS_ERROR
;
201 return JOB_STATUS_DELETING
;
203 return JOB_STATUS_OFFLINE
;
205 return JOB_STATUS_PAPEROUT
;
207 return JOB_STATUS_PRINTED
;
209 return JOB_STATUS_DELETED
;
211 return JOB_STATUS_BLOCKED_DEVQ
;
212 case LPQ_USER_INTERVENTION
:
213 return JOB_STATUS_USER_INTERVENTION
;
218 static int nt_printq_status(int v
)
222 return PRINTER_STATUS_PAUSED
;
231 /***************************************************************************
232 Disconnect from the client
233 ****************************************************************************/
235 static void srv_spoolss_replycloseprinter(int snum
,
236 struct printer_handle
*prn_hnd
)
242 * Tell the specific printing tdb we no longer want messages for this printer
243 * by deregistering our PID.
246 if (!print_notify_deregister_pid(snum
)) {
247 DEBUG(0, ("Failed to register our pid for printer %s\n",
248 lp_const_servicename(snum
)));
251 /* weird if the test succeeds !!! */
252 if (prn_hnd
->notify
.cli_chan
== NULL
||
253 prn_hnd
->notify
.cli_chan
->cli_pipe
== NULL
||
254 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
== NULL
||
255 prn_hnd
->notify
.cli_chan
->active_connections
== 0) {
256 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257 DLIST_REMOVE(back_channels
, prn_hnd
->notify
.cli_chan
);
258 TALLOC_FREE(prn_hnd
->notify
.cli_chan
);
262 status
= dcerpc_spoolss_ReplyClosePrinter(
263 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
,
265 &prn_hnd
->notify
.cli_hnd
,
267 if (!NT_STATUS_IS_OK(status
)) {
268 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
270 result
= ntstatus_to_werror(status
);
271 } else if (!W_ERROR_IS_OK(result
)) {
272 DEBUG(0, ("reply_close_printer failed [%s].\n",
273 win_errstr(result
)));
276 /* if it's the last connection, deconnect the IPC$ share */
277 if (prn_hnd
->notify
.cli_chan
->active_connections
== 1) {
279 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd
->notify
.cli_chan
->cli_pipe
));
280 DLIST_REMOVE(back_channels
, prn_hnd
->notify
.cli_chan
);
281 TALLOC_FREE(prn_hnd
->notify
.cli_chan
);
283 if (prn_hnd
->notify
.msg_ctx
!= NULL
) {
284 messaging_deregister(prn_hnd
->notify
.msg_ctx
,
285 MSG_PRINTER_NOTIFY2
, NULL
);
289 if (prn_hnd
->notify
.cli_chan
) {
290 prn_hnd
->notify
.cli_chan
->active_connections
--;
291 prn_hnd
->notify
.cli_chan
= NULL
;
295 /****************************************************************************
296 Functions to free a printer entry datastruct.
297 ****************************************************************************/
299 static int printer_entry_destructor(struct printer_handle
*Printer
)
301 if (Printer
->notify
.cli_chan
!= NULL
&&
302 Printer
->notify
.cli_chan
->active_connections
> 0) {
305 switch(Printer
->printer_type
) {
307 srv_spoolss_replycloseprinter(snum
, Printer
);
311 snum
= print_queue_snum(Printer
->sharename
);
313 srv_spoolss_replycloseprinter(snum
, Printer
);
321 Printer
->notify
.flags
=0;
322 Printer
->notify
.options
=0;
323 Printer
->notify
.localmachine
[0]='\0';
324 Printer
->notify
.printerlocal
=0;
325 TALLOC_FREE(Printer
->notify
.option
);
326 TALLOC_FREE(Printer
->devmode
);
328 /* Remove from the internal list. */
329 DLIST_REMOVE(printers_list
, Printer
);
333 /****************************************************************************
334 find printer index by handle
335 ****************************************************************************/
337 static struct printer_handle
*find_printer_index_by_hnd(struct pipes_struct
*p
,
338 struct policy_handle
*hnd
)
340 struct printer_handle
*find_printer
= NULL
;
342 if(!find_policy_by_hnd(p
,hnd
,(void **)(void *)&find_printer
)) {
343 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
350 /****************************************************************************
351 Close printer index by handle.
352 ****************************************************************************/
354 static bool close_printer_handle(struct pipes_struct
*p
, struct policy_handle
*hnd
)
356 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
359 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
364 close_policy_hnd(p
, hnd
);
369 /****************************************************************************
370 Delete a printer given a handle.
371 ****************************************************************************/
373 static WERROR
delete_printer_hook(TALLOC_CTX
*ctx
, struct security_token
*token
,
374 const char *sharename
,
375 struct messaging_context
*msg_ctx
)
377 char *cmd
= lp_deleteprinter_cmd();
378 char *command
= NULL
;
380 bool is_print_op
= false;
382 /* can't fail if we don't try */
387 command
= talloc_asprintf(ctx
,
394 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
396 DEBUG(10,("Running [%s]\n", command
));
398 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
403 if ( (ret
= smbrun(command
, NULL
)) == 0 ) {
404 /* Tell everyone we updated smb.conf. */
405 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
411 /********** END SePrintOperatorPrivlege BLOCK **********/
413 DEBUGADD(10,("returned [%d]\n", ret
));
415 TALLOC_FREE(command
);
418 return WERR_BADFID
; /* What to return here? */
423 /****************************************************************************
424 Delete a printer given a handle.
425 ****************************************************************************/
427 static WERROR
delete_printer_handle(struct pipes_struct
*p
, struct policy_handle
*hnd
)
429 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
433 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
439 * It turns out that Windows allows delete printer on a handle
440 * opened by an admin user, then used on a pipe handle created
441 * by an anonymous user..... but they're working on security.... riiight !
445 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
446 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447 return WERR_ACCESS_DENIED
;
450 /* this does not need a become root since the access check has been
451 done on the handle already */
453 result
= winreg_delete_printer_key_internal(p
->mem_ctx
,
454 get_session_info_system(),
458 if (!W_ERROR_IS_OK(result
)) {
459 DEBUG(3,("Error deleting printer %s\n", Printer
->sharename
));
463 result
= delete_printer_hook(p
->mem_ctx
, p
->session_info
->security_token
,
464 Printer
->sharename
, p
->msg_ctx
);
465 if (!W_ERROR_IS_OK(result
)) {
468 prune_printername_cache();
472 /****************************************************************************
473 Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
476 static bool get_printer_snum(struct pipes_struct
*p
, struct policy_handle
*hnd
,
477 int *number
, struct share_params
**params
)
479 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
482 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
487 switch (Printer
->printer_type
) {
489 DEBUG(4,("short name:%s\n", Printer
->sharename
));
490 *number
= print_queue_snum(Printer
->sharename
);
491 return (*number
!= -1);
499 /****************************************************************************
500 Set printer handle type.
501 Check if it's \\server or \\server\printer
502 ****************************************************************************/
504 static bool set_printer_hnd_printertype(struct printer_handle
*Printer
, const char *handlename
)
506 DEBUG(3,("Setting printer type=%s\n", handlename
));
508 /* it's a print server */
509 if (handlename
&& *handlename
=='\\' && *(handlename
+1)=='\\' && !strchr_m(handlename
+2, '\\')) {
510 DEBUGADD(4,("Printer is a print server\n"));
511 Printer
->printer_type
= SPLHND_SERVER
;
513 /* it's a printer (set_printer_hnd_name() will handle port monitors */
515 DEBUGADD(4,("Printer is a printer\n"));
516 Printer
->printer_type
= SPLHND_PRINTER
;
522 static void prune_printername_cache_fn(const char *key
, const char *value
,
523 time_t timeout
, void *private_data
)
528 static void prune_printername_cache(void)
530 gencache_iterate(prune_printername_cache_fn
, NULL
, "PRINTERNAME/*");
533 /****************************************************************************
534 Set printer handle name.. Accept names like \\server, \\server\printer,
535 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
536 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537 XcvDataPort() interface.
538 ****************************************************************************/
540 static WERROR
set_printer_hnd_name(TALLOC_CTX
*mem_ctx
,
541 const struct auth_session_info
*session_info
,
542 struct messaging_context
*msg_ctx
,
543 struct printer_handle
*Printer
,
544 const char *handlename
)
547 int n_services
=lp_numservices();
549 const char *printername
;
550 const char *servername
= NULL
;
553 struct spoolss_PrinterInfo2
*info2
= NULL
;
558 * Hopefully nobody names his printers like this. Maybe \ or ,
559 * are illegal in printer names even?
561 const char printer_not_found
[] = "Printer \\, !@#$%^&*( not found";
565 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename
,
566 (unsigned long)strlen(handlename
)));
568 aprinter
= discard_const_p(char, handlename
);
569 if ( *handlename
== '\\' ) {
570 servername
= canon_servername(handlename
);
571 if ( (aprinter
= strchr_m( servername
, '\\' )) != NULL
) {
575 if (!is_myname_or_ipaddr(servername
)) {
576 return WERR_INVALID_PRINTER_NAME
;
578 Printer
->servername
= talloc_asprintf(Printer
, "\\\\%s", servername
);
579 if (Printer
->servername
== NULL
) {
584 if (Printer
->printer_type
== SPLHND_SERVER
) {
588 if (Printer
->printer_type
!= SPLHND_PRINTER
) {
589 return WERR_INVALID_HANDLE
;
592 DEBUGADD(5, ("searching for [%s]\n", aprinter
));
594 p
= strchr(aprinter
, ',');
601 if (strncmp(p
, "DrvConvert", strlen("DrvConvert")) == 0) {
603 } else if (strncmp(p
, "LocalOnly", strlen("LocalOnly")) == 0) {
609 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter
));
612 /* check for the Port Monitor Interface */
613 if ( strequal( aprinter
, SPL_XCV_MONITOR_TCPMON
) ) {
614 Printer
->printer_type
= SPLHND_PORTMON_TCP
;
615 fstrcpy(sname
, SPL_XCV_MONITOR_TCPMON
);
618 else if ( strequal( aprinter
, SPL_XCV_MONITOR_LOCALMON
) ) {
619 Printer
->printer_type
= SPLHND_PORTMON_LOCAL
;
620 fstrcpy(sname
, SPL_XCV_MONITOR_LOCALMON
);
625 * With hundreds of printers, the "for" loop iterating all
626 * shares can be quite expensive, as it is done on every
627 * OpenPrinter. The loop maps "aprinter" to "sname", the
628 * result of which we cache in gencache.
631 cache_key
= talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
633 if ((cache_key
!= NULL
) && gencache_get(cache_key
, &tmp
, NULL
)) {
635 found
= (strcmp(tmp
, printer_not_found
) != 0);
637 DEBUG(4, ("Printer %s not found\n", aprinter
));
639 return WERR_INVALID_PRINTER_NAME
;
645 /* Search all sharenames first as this is easier than pulling
646 the printer_info_2 off of disk. Don't use find_service() since
647 that calls out to map_username() */
649 /* do another loop to look for printernames */
650 for (snum
= 0; !found
&& snum
< n_services
; snum
++) {
651 const char *printer
= lp_const_servicename(snum
);
653 /* no point going on if this is not a printer */
654 if (!(lp_snum_ok(snum
) && lp_print_ok(snum
))) {
658 /* ignore [printers] share */
659 if (strequal(printer
, "printers")) {
663 fstrcpy(sname
, printer
);
664 if (strequal(aprinter
, printer
)) {
669 /* no point looking up the printer object if
670 we aren't allowing printername != sharename */
671 if (lp_force_printername(snum
)) {
675 result
= winreg_get_printer_internal(mem_ctx
,
680 if ( !W_ERROR_IS_OK(result
) ) {
681 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682 sname
, win_errstr(result
)));
686 printername
= strrchr(info2
->printername
, '\\');
687 if (printername
== NULL
) {
688 printername
= info2
->printername
;
693 if (strequal(printername
, aprinter
)) {
698 DEBUGADD(10, ("printername: %s\n", printername
));
704 if (cache_key
!= NULL
) {
705 gencache_set(cache_key
, printer_not_found
,
707 TALLOC_FREE(cache_key
);
709 DEBUGADD(4,("Printer not found\n"));
710 return WERR_INVALID_PRINTER_NAME
;
713 if (cache_key
!= NULL
) {
714 gencache_set(cache_key
, sname
, time(NULL
)+300);
715 TALLOC_FREE(cache_key
);
718 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter
, sname
));
720 strlcpy(Printer
->sharename
, sname
, sizeof(Printer
->sharename
));
725 /****************************************************************************
726 Find first available printer slot. creates a printer handle for you.
727 ****************************************************************************/
729 static WERROR
open_printer_hnd(struct pipes_struct
*p
,
730 struct policy_handle
*hnd
,
732 uint32_t access_granted
)
734 struct printer_handle
*new_printer
;
737 DEBUG(10,("open_printer_hnd: name [%s]\n", name
));
739 new_printer
= talloc_zero(p
->mem_ctx
, struct printer_handle
);
740 if (new_printer
== NULL
) {
743 talloc_set_destructor(new_printer
, printer_entry_destructor
);
745 /* This also steals the printer_handle on the policy_handle */
746 if (!create_policy_hnd(p
, hnd
, new_printer
)) {
747 TALLOC_FREE(new_printer
);
748 return WERR_INVALID_HANDLE
;
751 /* Add to the internal list. */
752 DLIST_ADD(printers_list
, new_printer
);
754 new_printer
->notify
.option
=NULL
;
756 if (!set_printer_hnd_printertype(new_printer
, name
)) {
757 close_printer_handle(p
, hnd
);
758 return WERR_INVALID_HANDLE
;
761 result
= set_printer_hnd_name(p
->mem_ctx
,
762 get_session_info_system(),
765 if (!W_ERROR_IS_OK(result
)) {
766 close_printer_handle(p
, hnd
);
770 new_printer
->access_granted
= access_granted
;
772 DEBUG(5, ("%d printer handles active\n",
773 (int)num_pipe_handles(p
)));
778 /***************************************************************************
779 check to see if the client motify handle is monitoring the notification
780 given by (notify_type, notify_field).
781 **************************************************************************/
783 static bool is_monitoring_event_flags(uint32_t flags
, uint16_t notify_type
,
784 uint16_t notify_field
)
789 static bool is_monitoring_event(struct printer_handle
*p
, uint16_t notify_type
,
790 uint16_t notify_field
)
792 struct spoolss_NotifyOption
*option
= p
->notify
.option
;
796 * Flags should always be zero when the change notify
797 * is registered by the client's spooler. A user Win32 app
798 * might use the flags though instead of the NOTIFY_OPTION_INFO
807 return is_monitoring_event_flags(
808 p
->notify
.flags
, notify_type
, notify_field
);
810 for (i
= 0; i
< option
->count
; i
++) {
812 /* Check match for notify_type */
814 if (option
->types
[i
].type
!= notify_type
)
817 /* Check match for field */
819 for (j
= 0; j
< option
->types
[i
].count
; j
++) {
820 if (option
->types
[i
].fields
[j
].field
== notify_field
) {
826 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827 p
->servername
, p
->sharename
, notify_type
, notify_field
));
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833 _data->data.integer[0] = _integer; \
834 _data->data.integer[1] = 0;
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839 if (!_data->data.string.string) {\
840 _data->data.string.size = 0; \
842 _data->data.string.size = strlen_m_term(_p) * 2;
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845 _data->data.devmode.devmode = _devmode;
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849 if (!_data->data.sd.sd) { \
850 _data->data.sd.sd_size = 0; \
852 _data->data.sd.sd_size = \
853 ndr_size_security_descriptor(_data->data.sd.sd, 0);
855 static void init_systemtime_buffer(TALLOC_CTX
*mem_ctx
,
860 struct spoolss_Time st
;
864 if (!init_systemtime(&st
, t
)) {
868 p
= talloc_array(mem_ctx
, char, len
);
874 * Systemtime must be linearized as a set of UINT16's.
875 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
878 SSVAL(p
, 0, st
.year
);
879 SSVAL(p
, 2, st
.month
);
880 SSVAL(p
, 4, st
.day_of_week
);
882 SSVAL(p
, 8, st
.hour
);
883 SSVAL(p
, 10, st
.minute
);
884 SSVAL(p
, 12, st
.second
);
885 SSVAL(p
, 14, st
.millisecond
);
891 /* Convert a notification message to a struct spoolss_Notify */
893 static void notify_one_value(struct spoolss_notify_msg
*msg
,
894 struct spoolss_Notify
*data
,
897 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, msg
->notify
.value
[0]);
900 static void notify_string(struct spoolss_notify_msg
*msg
,
901 struct spoolss_Notify
*data
,
904 /* The length of the message includes the trailing \0 */
906 data
->data
.string
.size
= msg
->len
* 2;
907 data
->data
.string
.string
= talloc_strdup(mem_ctx
, msg
->notify
.data
);
908 if (!data
->data
.string
.string
) {
909 data
->data
.string
.size
= 0;
914 static void notify_system_time(struct spoolss_notify_msg
*msg
,
915 struct spoolss_Notify
*data
,
918 data
->data
.string
.string
= NULL
;
919 data
->data
.string
.size
= 0;
921 if (msg
->len
!= sizeof(time_t)) {
922 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
927 init_systemtime_buffer(mem_ctx
, gmtime((time_t *)msg
->notify
.data
),
928 &data
->data
.string
.string
,
929 &data
->data
.string
.size
);
932 struct notify2_message_table
{
934 void (*fn
)(struct spoolss_notify_msg
*msg
,
935 struct spoolss_Notify
*data
, TALLOC_CTX
*mem_ctx
);
938 static struct notify2_message_table printer_notify_table
[] = {
939 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string
},
940 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string
},
941 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string
},
942 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string
},
943 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string
},
944 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string
},
945 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string
},
946 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL
},
947 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string
},
948 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string
},
949 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL
},
950 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string
},
951 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
952 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value
},
953 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value
},
954 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL
},
955 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL
},
956 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL
},
957 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value
},
960 static struct notify2_message_table job_notify_table
[] = {
961 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL
},
962 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL
},
963 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL
},
964 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string
},
965 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL
},
966 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL
},
967 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL
},
968 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL
},
969 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL
},
970 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL
},
971 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value
},
972 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL
},
973 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL
},
974 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string
},
975 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL
},
976 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL
},
977 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time
},
978 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL
},
979 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL
},
980 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL
},
981 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value
},
982 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL
},
983 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value
},
984 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL
},
988 /***********************************************************************
989 Allocate talloc context for container object
990 **********************************************************************/
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
997 ctr
->ctx
= talloc_init("notify_msg_ctr_init %p", ctr
);
1002 /***********************************************************************
1003 release all allocated memory and zero out structure
1004 **********************************************************************/
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1012 talloc_destroy(ctr
->ctx
);
1019 /***********************************************************************
1020 **********************************************************************/
1022 static TALLOC_CTX
* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1030 /***********************************************************************
1031 **********************************************************************/
1033 static SPOOLSS_NOTIFY_MSG_GROUP
* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
1035 if ( !ctr
|| !ctr
->msg_groups
)
1038 if ( idx
>= ctr
->num_groups
)
1041 return &ctr
->msg_groups
[idx
];
1045 /***********************************************************************
1046 How many groups of change messages do we have ?
1047 **********************************************************************/
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR
*ctr
)
1054 return ctr
->num_groups
;
1057 /***********************************************************************
1058 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059 **********************************************************************/
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, SPOOLSS_NOTIFY_MSG
*msg
)
1063 SPOOLSS_NOTIFY_MSG_GROUP
*groups
= NULL
;
1064 SPOOLSS_NOTIFY_MSG_GROUP
*msg_grp
= NULL
;
1065 SPOOLSS_NOTIFY_MSG
*msg_list
= NULL
;
1071 /* loop over all groups looking for a matching printer name */
1073 for ( i
=0; i
<ctr
->num_groups
; i
++ ) {
1074 if ( strcmp(ctr
->msg_groups
[i
].printername
, msg
->printer
) == 0 )
1078 /* add a new group? */
1080 if ( i
== ctr
->num_groups
) {
1083 if ( !(groups
= talloc_realloc( ctr
->ctx
, ctr
->msg_groups
, SPOOLSS_NOTIFY_MSG_GROUP
, ctr
->num_groups
)) ) {
1084 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1087 ctr
->msg_groups
= groups
;
1089 /* clear the new entry and set the printer name */
1091 ZERO_STRUCT( ctr
->msg_groups
[ctr
->num_groups
-1] );
1092 fstrcpy( ctr
->msg_groups
[ctr
->num_groups
-1].printername
, msg
->printer
);
1095 /* add the change messages; 'i' is the correct index now regardless */
1097 msg_grp
= &ctr
->msg_groups
[i
];
1099 msg_grp
->num_msgs
++;
1101 if ( !(msg_list
= talloc_realloc( ctr
->ctx
, msg_grp
->msgs
, SPOOLSS_NOTIFY_MSG
, msg_grp
->num_msgs
)) ) {
1102 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp
->num_msgs
));
1105 msg_grp
->msgs
= msg_list
;
1107 new_slot
= msg_grp
->num_msgs
-1;
1108 memcpy( &msg_grp
->msgs
[new_slot
], msg
, sizeof(SPOOLSS_NOTIFY_MSG
) );
1110 /* need to allocate own copy of data */
1112 if ( msg
->len
!= 0 )
1113 msg_grp
->msgs
[new_slot
].notify
.data
= (char *)
1114 talloc_memdup( ctr
->ctx
, msg
->notify
.data
, msg
->len
);
1116 return ctr
->num_groups
;
1119 static void construct_info_data(struct spoolss_Notify
*info_data
,
1120 enum spoolss_NotifyType type
,
1121 uint16_t field
, int id
);
1123 /***********************************************************************
1124 Send a change notication message on all handles which have a call
1126 **********************************************************************/
1128 static int build_notify2_messages(TALLOC_CTX
*mem_ctx
,
1129 struct printer_handle
*prn_hnd
,
1130 SPOOLSS_NOTIFY_MSG
*messages
,
1132 struct spoolss_Notify
**_notifies
,
1135 struct spoolss_Notify
*notifies
;
1136 SPOOLSS_NOTIFY_MSG
*msg
;
1141 notifies
= talloc_zero_array(mem_ctx
,
1142 struct spoolss_Notify
, num_msgs
);
1147 for (i
= 0; i
< num_msgs
; i
++) {
1151 /* Are we monitoring this event? */
1153 if (!is_monitoring_event(prn_hnd
, msg
->type
, msg
->field
)) {
1157 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158 "for printer [%s]\n",
1159 msg
->type
, msg
->field
, prn_hnd
->sharename
));
1162 * if the is a printer notification handle and not a job
1163 * notification type, then set the id to 0.
1164 * Otherwise just use what was specified in the message.
1166 * When registering change notification on a print server
1167 * handle we always need to send back the id (snum) matching
1168 * the printer for which the change took place.
1169 * For change notify registered on a printer handle,
1170 * this does not matter and the id should be 0.
1175 if ((msg
->type
== PRINTER_NOTIFY_TYPE
) &&
1176 (prn_hnd
->printer_type
== SPLHND_PRINTER
)) {
1182 /* Convert unix jobid to smb jobid */
1184 if (msg
->flags
& SPOOLSS_NOTIFY_MSG_UNIX_JOBID
) {
1185 id
= sysjob_to_jobid(msg
->id
);
1188 DEBUG(3, ("no such unix jobid %d\n",
1194 construct_info_data(¬ifies
[count
],
1195 msg
->type
, msg
->field
, id
);
1198 case PRINTER_NOTIFY_TYPE
:
1199 if (printer_notify_table
[msg
->field
].fn
) {
1200 printer_notify_table
[msg
->field
].fn(msg
,
1201 ¬ifies
[count
], mem_ctx
);
1205 case JOB_NOTIFY_TYPE
:
1206 if (job_notify_table
[msg
->field
].fn
) {
1207 job_notify_table
[msg
->field
].fn(msg
,
1208 ¬ifies
[count
], mem_ctx
);
1213 DEBUG(5, ("Unknown notification type %d\n",
1221 *_notifies
= notifies
;
1227 static int send_notify2_printer(TALLOC_CTX
*mem_ctx
,
1228 struct printer_handle
*prn_hnd
,
1229 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
)
1231 struct spoolss_Notify
*notifies
;
1233 union spoolss_ReplyPrinterInfo info
;
1234 struct spoolss_NotifyInfo info0
;
1235 uint32_t reply_result
;
1240 /* Is there notification on this handle? */
1241 if (prn_hnd
->notify
.cli_chan
== NULL
||
1242 prn_hnd
->notify
.cli_chan
->cli_pipe
== NULL
||
1243 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
== NULL
||
1244 prn_hnd
->notify
.cli_chan
->active_connections
== 0) {
1248 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249 prn_hnd
->servername
, prn_hnd
->sharename
));
1251 /* For this printer? Print servers always receive notifications. */
1252 if ((prn_hnd
->printer_type
== SPLHND_PRINTER
) &&
1253 (!strequal(msg_group
->printername
, prn_hnd
->sharename
))) {
1257 DEBUG(10,("Our printer\n"));
1259 /* build the array of change notifications */
1260 ret
= build_notify2_messages(mem_ctx
, prn_hnd
,
1262 msg_group
->num_msgs
,
1268 info0
.version
= 0x2;
1269 info0
.flags
= count
? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED
;
1270 info0
.count
= count
;
1271 info0
.notifies
= notifies
;
1273 info
.info0
= &info0
;
1275 status
= dcerpc_spoolss_RouterReplyPrinterEx(
1276 prn_hnd
->notify
.cli_chan
->cli_pipe
->binding_handle
,
1278 &prn_hnd
->notify
.cli_hnd
,
1279 prn_hnd
->notify
.change
, /* color */
1280 prn_hnd
->notify
.flags
,
1282 0, /* reply_type, must be 0 */
1284 if (!NT_STATUS_IS_OK(status
)) {
1285 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1287 prn_hnd
->notify
.cli_chan
->cli_pipe
->srv_name_slash
,
1288 nt_errstr(status
)));
1289 werr
= ntstatus_to_werror(status
);
1290 } else if (!W_ERROR_IS_OK(werr
)) {
1291 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1293 prn_hnd
->notify
.cli_chan
->cli_pipe
->srv_name_slash
,
1296 switch (reply_result
) {
1299 case PRINTER_NOTIFY_INFO_DISCARDED
:
1300 case PRINTER_NOTIFY_INFO_DISCARDNOTED
:
1301 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH
:
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR
*ctr
, uint32_t idx
)
1312 struct printer_handle
*p
;
1313 TALLOC_CTX
*mem_ctx
= notify_ctr_getctx( ctr
);
1314 SPOOLSS_NOTIFY_MSG_GROUP
*msg_group
= notify_ctr_getgroup( ctr
, idx
);
1318 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1322 if (!msg_group
->msgs
) {
1323 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1327 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group
->printername
));
1329 /* loop over all printers */
1331 for (p
= printers_list
; p
; p
= p
->next
) {
1332 ret
= send_notify2_printer(mem_ctx
, p
, msg_group
);
1339 DEBUG(8,("send_notify2_changes: Exit...\n"));
1343 /***********************************************************************
1344 **********************************************************************/
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG
*msg
, struct timeval
*tv
, void *buf
, size_t len
)
1349 uint32_t tv_sec
, tv_usec
;
1352 /* Unpack message */
1354 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "f",
1357 offset
+= tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "ddddddd",
1359 &msg
->type
, &msg
->field
, &msg
->id
, &msg
->len
, &msg
->flags
);
1362 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "dd",
1363 &msg
->notify
.value
[0], &msg
->notify
.value
[1]);
1365 tdb_unpack((uint8_t *)buf
+ offset
, len
- offset
, "B",
1366 &msg
->len
, &msg
->notify
.data
);
1368 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369 msg
->printer
, (unsigned int)msg
->id
, msg
->type
, msg
->field
, msg
->flags
));
1371 tv
->tv_sec
= tv_sec
;
1372 tv
->tv_usec
= tv_usec
;
1375 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg
->notify
.value
[0],
1376 msg
->notify
.value
[1]));
1378 dump_data(3, (uint8_t *)msg
->notify
.data
, msg
->len
);
1383 /********************************************************************
1384 Receive a notify2 message list
1385 ********************************************************************/
1387 static void receive_notify2_message_list(struct messaging_context
*msg
,
1390 struct server_id server_id
,
1393 size_t msg_count
, i
;
1394 char *buf
= (char *)data
->data
;
1397 SPOOLSS_NOTIFY_MSG notify
;
1398 SPOOLSS_NOTIFY_MSG_CTR messages
;
1401 if (data
->length
< 4) {
1402 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1406 msg_count
= IVAL(buf
, 0);
1409 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count
));
1411 if (msg_count
== 0) {
1412 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1416 /* initialize the container */
1418 ZERO_STRUCT( messages
);
1419 notify_msg_ctr_init( &messages
);
1422 * build message groups for each printer identified
1423 * in a change_notify msg. Remember that a PCN message
1424 * includes the handle returned for the srv_spoolss_replyopenprinter()
1425 * call. Therefore messages are grouped according to printer handle.
1428 for ( i
=0; i
<msg_count
; i
++ ) {
1429 struct timeval msg_tv
;
1431 if (msg_ptr
+ 4 - buf
> data
->length
) {
1432 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1436 msg_len
= IVAL(msg_ptr
,0);
1439 if (msg_ptr
+ msg_len
- buf
> data
->length
) {
1440 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1444 /* unpack messages */
1446 ZERO_STRUCT( notify
);
1447 notify2_unpack_msg( ¬ify
, &msg_tv
, msg_ptr
, msg_len
);
1450 /* add to correct list in container */
1452 notify_msg_ctr_addmsg( &messages
, ¬ify
);
1454 /* free memory that might have been allocated by notify2_unpack_msg() */
1456 if ( notify
.len
!= 0 )
1457 SAFE_FREE( notify
.notify
.data
);
1460 /* process each group of messages */
1462 num_groups
= notify_msg_ctr_numgroups( &messages
);
1463 for ( i
=0; i
<num_groups
; i
++ )
1464 send_notify2_changes( &messages
, i
);
1469 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470 (uint32_t)msg_count
));
1472 notify_msg_ctr_destroy( &messages
);
1477 /********************************************************************
1478 Send a message to ourself about new driver being installed
1479 so we can upgrade the information for each printer bound to this
1481 ********************************************************************/
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername
,
1484 struct messaging_context
*msg_ctx
)
1486 int len
= strlen(drivername
);
1491 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1494 messaging_send_buf(msg_ctx
, messaging_server_id(msg_ctx
),
1495 MSG_PRINTER_DRVUPGRADE
,
1496 (const uint8_t *)drivername
, len
+1);
1501 void srv_spoolss_cleanup(void)
1503 struct printer_session_counter
*session_counter
;
1505 for (session_counter
= counter_list
;
1506 session_counter
!= NULL
;
1507 session_counter
= counter_list
) {
1508 DLIST_REMOVE(counter_list
, session_counter
);
1509 TALLOC_FREE(session_counter
);
1513 /**********************************************************************
1514 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515 over all printers, upgrading ones as necessary
1516 **********************************************************************/
1518 void do_drv_upgrade_printer(struct messaging_context
*msg
,
1521 struct server_id server_id
,
1524 TALLOC_CTX
*tmp_ctx
;
1525 const struct auth_session_info
*session_info
= get_session_info_system();
1526 struct spoolss_PrinterInfo2
*pinfo2
;
1528 const char *drivername
;
1530 int n_services
= lp_numservices();
1531 struct dcerpc_binding_handle
*b
= NULL
;
1533 tmp_ctx
= talloc_new(NULL
);
1534 if (!tmp_ctx
) return;
1536 drivername
= talloc_strndup(tmp_ctx
, (const char *)data
->data
, data
->length
);
1538 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1542 DEBUG(10, ("do_drv_upgrade_printer: "
1543 "Got message for new driver [%s]\n", drivername
));
1545 /* Iterate the printer list */
1547 for (snum
= 0; snum
< n_services
; snum
++) {
1548 if (!lp_snum_ok(snum
) || !lp_print_ok(snum
)) {
1552 /* ignore [printers] share */
1553 if (strequal(lp_const_servicename(snum
), "printers")) {
1558 result
= winreg_printer_binding_handle(tmp_ctx
,
1562 if (!W_ERROR_IS_OK(result
)) {
1567 result
= winreg_get_printer(tmp_ctx
, b
,
1568 lp_const_servicename(snum
),
1571 if (!W_ERROR_IS_OK(result
)) {
1575 if (!pinfo2
->drivername
) {
1579 if (strcmp(drivername
, pinfo2
->drivername
) != 0) {
1583 DEBUG(6,("Updating printer [%s]\n", pinfo2
->printername
));
1585 /* all we care about currently is the change_id */
1586 result
= winreg_printer_update_changeid(tmp_ctx
, b
,
1587 pinfo2
->printername
);
1589 if (!W_ERROR_IS_OK(result
)) {
1590 DEBUG(3, ("do_drv_upgrade_printer: "
1591 "Failed to update changeid [%s]\n",
1592 win_errstr(result
)));
1598 talloc_free(tmp_ctx
);
1601 /********************************************************************
1602 Update the cache for all printq's with a registered client
1604 ********************************************************************/
1606 void update_monitored_printq_cache(struct messaging_context
*msg_ctx
)
1608 struct printer_handle
*printer
= printers_list
;
1611 /* loop through all printers and update the cache where
1612 a client is connected */
1614 if ((printer
->printer_type
== SPLHND_PRINTER
) &&
1615 ((printer
->notify
.cli_chan
!= NULL
) &&
1616 (printer
->notify
.cli_chan
->active_connections
> 0))) {
1617 snum
= print_queue_snum(printer
->sharename
);
1618 print_queue_status(msg_ctx
, snum
, NULL
, NULL
);
1621 printer
= printer
->next
;
1627 /****************************************************************
1628 _spoolss_OpenPrinter
1629 ****************************************************************/
1631 WERROR
_spoolss_OpenPrinter(struct pipes_struct
*p
,
1632 struct spoolss_OpenPrinter
*r
)
1634 struct spoolss_OpenPrinterEx e
;
1637 ZERO_STRUCT(e
.in
.userlevel
);
1639 e
.in
.printername
= r
->in
.printername
;
1640 e
.in
.datatype
= r
->in
.datatype
;
1641 e
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
1642 e
.in
.access_mask
= r
->in
.access_mask
;
1645 e
.out
.handle
= r
->out
.handle
;
1647 werr
= _spoolss_OpenPrinterEx(p
, &e
);
1649 if (W_ERROR_EQUAL(werr
, WERR_INVALID_PARAM
)) {
1650 /* OpenPrinterEx returns this for a bad
1651 * printer name. We must return WERR_INVALID_PRINTER_NAME
1654 werr
= WERR_INVALID_PRINTER_NAME
;
1660 static WERROR
copy_devicemode(TALLOC_CTX
*mem_ctx
,
1661 struct spoolss_DeviceMode
*orig
,
1662 struct spoolss_DeviceMode
**dest
)
1664 struct spoolss_DeviceMode
*dm
;
1666 dm
= talloc(mem_ctx
, struct spoolss_DeviceMode
);
1671 /* copy all values, then duplicate strings and structs */
1674 dm
->devicename
= talloc_strdup(dm
, orig
->devicename
);
1675 if (!dm
->devicename
) {
1678 dm
->formname
= talloc_strdup(dm
, orig
->formname
);
1679 if (!dm
->formname
) {
1682 if (orig
->driverextra_data
.data
) {
1683 dm
->driverextra_data
.data
=
1684 (uint8_t *) talloc_memdup(dm
, orig
->driverextra_data
.data
,
1685 orig
->driverextra_data
.length
);
1686 if (!dm
->driverextra_data
.data
) {
1695 /****************************************************************
1696 _spoolss_OpenPrinterEx
1697 ****************************************************************/
1699 WERROR
_spoolss_OpenPrinterEx(struct pipes_struct
*p
,
1700 struct spoolss_OpenPrinterEx
*r
)
1705 struct printer_handle
*Printer
=NULL
;
1709 if (!r
->in
.printername
) {
1710 return WERR_INVALID_PARAM
;
1713 if (r
->in
.level
> 3) {
1714 return WERR_INVALID_PARAM
;
1716 if ((r
->in
.level
== 1 && !r
->in
.userlevel
.level1
) ||
1717 (r
->in
.level
== 2 && !r
->in
.userlevel
.level2
) ||
1718 (r
->in
.level
== 3 && !r
->in
.userlevel
.level3
)) {
1719 return WERR_INVALID_PARAM
;
1722 /* some sanity check because you can open a printer or a print server */
1723 /* aka: \\server\printer or \\server */
1725 DEBUGADD(3,("checking name: %s\n", r
->in
.printername
));
1727 result
= open_printer_hnd(p
, r
->out
.handle
, r
->in
.printername
, 0);
1728 if (!W_ERROR_IS_OK(result
)) {
1729 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1730 "for printer %s\n", r
->in
.printername
));
1731 ZERO_STRUCTP(r
->out
.handle
);
1735 Printer
= find_printer_index_by_hnd(p
, r
->out
.handle
);
1737 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1738 "handle we created for printer %s\n", r
->in
.printername
));
1739 close_printer_handle(p
, r
->out
.handle
);
1740 ZERO_STRUCTP(r
->out
.handle
);
1741 return WERR_INVALID_PARAM
;
1745 * First case: the user is opening the print server:
1747 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1748 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1750 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1751 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1752 * or if the user is listed in the smb.conf printer admin parameter.
1754 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1755 * client view printer folder, but does not show the MSAPW.
1757 * Note: this test needs code to check access rights here too. Jeremy
1758 * could you look at this?
1760 * Second case: the user is opening a printer:
1761 * NT doesn't let us connect to a printer if the connecting user
1762 * doesn't have print permission.
1764 * Third case: user is opening a Port Monitor
1765 * access checks same as opening a handle to the print server.
1768 switch (Printer
->printer_type
)
1771 case SPLHND_PORTMON_TCP
:
1772 case SPLHND_PORTMON_LOCAL
:
1773 /* Printserver handles use global struct... */
1777 /* Map standard access rights to object specific access rights */
1779 se_map_standard(&r
->in
.access_mask
,
1780 &printserver_std_mapping
);
1782 /* Deny any object specific bits that don't apply to print
1783 servers (i.e printer and job specific bits) */
1785 r
->in
.access_mask
&= SEC_MASK_SPECIFIC
;
1787 if (r
->in
.access_mask
&
1788 ~(SERVER_ACCESS_ADMINISTER
| SERVER_ACCESS_ENUMERATE
)) {
1789 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1790 close_printer_handle(p
, r
->out
.handle
);
1791 ZERO_STRUCTP(r
->out
.handle
);
1792 return WERR_ACCESS_DENIED
;
1795 /* Allow admin access */
1797 if ( r
->in
.access_mask
& SERVER_ACCESS_ADMINISTER
)
1799 if (!lp_ms_add_printer_wizard()) {
1800 close_printer_handle(p
, r
->out
.handle
);
1801 ZERO_STRUCTP(r
->out
.handle
);
1802 return WERR_ACCESS_DENIED
;
1805 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1806 and not a printer admin, then fail */
1808 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
1809 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
1810 !nt_token_check_sid(&global_sid_Builtin_Print_Operators
, p
->session_info
->security_token
) &&
1811 !token_contains_name_in_list(
1812 uidtoname(p
->session_info
->unix_token
->uid
),
1813 p
->session_info
->info
->domain_name
,
1815 p
->session_info
->security_token
,
1816 lp_printer_admin(snum
))) {
1817 close_printer_handle(p
, r
->out
.handle
);
1818 ZERO_STRUCTP(r
->out
.handle
);
1819 DEBUG(3,("access DENIED as user is not root, "
1820 "has no printoperator privilege, "
1821 "not a member of the printoperator builtin group and "
1822 "is not in printer admin list"));
1823 return WERR_ACCESS_DENIED
;
1826 r
->in
.access_mask
= SERVER_ACCESS_ADMINISTER
;
1830 r
->in
.access_mask
= SERVER_ACCESS_ENUMERATE
;
1833 DEBUG(4,("Setting print server access = %s\n", (r
->in
.access_mask
== SERVER_ACCESS_ADMINISTER
)
1834 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1836 /* We fall through to return WERR_OK */
1839 case SPLHND_PRINTER
:
1840 /* NT doesn't let us connect to a printer if the connecting user
1841 doesn't have print permission. */
1843 if (!get_printer_snum(p
, r
->out
.handle
, &snum
, NULL
)) {
1844 close_printer_handle(p
, r
->out
.handle
);
1845 ZERO_STRUCTP(r
->out
.handle
);
1849 if (r
->in
.access_mask
== SEC_FLAG_MAXIMUM_ALLOWED
) {
1850 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1853 se_map_standard(&r
->in
.access_mask
, &printer_std_mapping
);
1855 /* map an empty access mask to the minimum access mask */
1856 if (r
->in
.access_mask
== 0x0)
1857 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1860 * If we are not serving the printer driver for this printer,
1861 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1862 * will keep NT clients happy --jerry
1865 if (lp_use_client_driver(snum
)
1866 && (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
))
1868 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1871 /* check smb.conf parameters and the the sec_desc */
1872 raddr
= tsocket_address_inet_addr_string(p
->remote_address
,
1874 if (raddr
== NULL
) {
1878 rc
= get_remote_hostname(p
->remote_address
,
1884 if (strequal(rhost
, "UNKNOWN")) {
1888 if (!allow_access(lp_hostsdeny(snum
), lp_hostsallow(snum
),
1890 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1891 ZERO_STRUCTP(r
->out
.handle
);
1892 return WERR_ACCESS_DENIED
;
1895 if (!user_ok_token(uidtoname(p
->session_info
->unix_token
->uid
), NULL
,
1896 p
->session_info
->security_token
, snum
) ||
1897 !print_access_check(p
->session_info
,
1900 r
->in
.access_mask
)) {
1901 DEBUG(3, ("access DENIED for printer open\n"));
1902 close_printer_handle(p
, r
->out
.handle
);
1903 ZERO_STRUCTP(r
->out
.handle
);
1904 return WERR_ACCESS_DENIED
;
1907 if ((r
->in
.access_mask
& SEC_MASK_SPECIFIC
)& ~(PRINTER_ACCESS_ADMINISTER
|PRINTER_ACCESS_USE
)) {
1908 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1909 close_printer_handle(p
, r
->out
.handle
);
1910 ZERO_STRUCTP(r
->out
.handle
);
1911 return WERR_ACCESS_DENIED
;
1914 if (r
->in
.access_mask
& PRINTER_ACCESS_ADMINISTER
)
1915 r
->in
.access_mask
= PRINTER_ACCESS_ADMINISTER
;
1917 r
->in
.access_mask
= PRINTER_ACCESS_USE
;
1919 DEBUG(4,("Setting printer access = %s\n", (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1920 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1922 winreg_create_printer_internal(p
->mem_ctx
,
1923 get_session_info_system(),
1925 lp_const_servicename(snum
));
1930 /* sanity check to prevent programmer error */
1931 ZERO_STRUCTP(r
->out
.handle
);
1935 Printer
->access_granted
= r
->in
.access_mask
;
1938 * If the client sent a devmode in the OpenPrinter() call, then
1939 * save it here in case we get a job submission on this handle
1942 if ((Printer
->printer_type
!= SPLHND_SERVER
) &&
1943 r
->in
.devmode_ctr
.devmode
) {
1944 copy_devicemode(NULL
, r
->in
.devmode_ctr
.devmode
,
1948 #if 0 /* JERRY -- I'm doubtful this is really effective */
1949 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1950 optimization in Windows 2000 clients --jerry */
1952 if ( (r
->in
.access_mask
== PRINTER_ACCESS_ADMINISTER
)
1953 && (RA_WIN2K
== get_remote_arch()) )
1955 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1956 sys_usleep( 500000 );
1963 /****************************************************************
1964 _spoolss_ClosePrinter
1965 ****************************************************************/
1967 WERROR
_spoolss_ClosePrinter(struct pipes_struct
*p
,
1968 struct spoolss_ClosePrinter
*r
)
1970 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
1972 if (Printer
&& Printer
->document_started
) {
1973 struct spoolss_EndDocPrinter e
;
1975 e
.in
.handle
= r
->in
.handle
;
1977 _spoolss_EndDocPrinter(p
, &e
);
1980 if (!close_printer_handle(p
, r
->in
.handle
))
1983 /* clear the returned printer handle. Observed behavior
1984 from Win2k server. Don't think this really matters.
1985 Previous code just copied the value of the closed
1988 ZERO_STRUCTP(r
->out
.handle
);
1993 /****************************************************************
1994 _spoolss_DeletePrinter
1995 ****************************************************************/
1997 WERROR
_spoolss_DeletePrinter(struct pipes_struct
*p
,
1998 struct spoolss_DeletePrinter
*r
)
2000 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2004 if (Printer
&& Printer
->document_started
) {
2005 struct spoolss_EndDocPrinter e
;
2007 e
.in
.handle
= r
->in
.handle
;
2009 _spoolss_EndDocPrinter(p
, &e
);
2012 if (get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
2013 winreg_delete_printer_key_internal(p
->mem_ctx
,
2014 get_session_info_system(),
2016 lp_const_servicename(snum
),
2020 result
= delete_printer_handle(p
, r
->in
.handle
);
2025 /*******************************************************************
2026 * static function to lookup the version id corresponding to an
2027 * long architecture string
2028 ******************************************************************/
2030 static const struct print_architecture_table_node archi_table
[]= {
2032 {"Windows 4.0", SPL_ARCH_WIN40
, 0 },
2033 {"Windows NT x86", SPL_ARCH_W32X86
, 2 },
2034 {"Windows NT R4000", SPL_ARCH_W32MIPS
, 2 },
2035 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA
, 2 },
2036 {"Windows NT PowerPC", SPL_ARCH_W32PPC
, 2 },
2037 {"Windows IA64", SPL_ARCH_IA64
, 3 },
2038 {"Windows x64", SPL_ARCH_X64
, 3 },
2042 static const int drv_cversion
[] = {SPOOLSS_DRIVER_VERSION_9X
,
2043 SPOOLSS_DRIVER_VERSION_NT35
,
2044 SPOOLSS_DRIVER_VERSION_NT4
,
2045 SPOOLSS_DRIVER_VERSION_200X
,
2048 static int get_version_id(const char *arch
)
2052 for (i
=0; archi_table
[i
].long_archi
!= NULL
; i
++)
2054 if (strcmp(arch
, archi_table
[i
].long_archi
) == 0)
2055 return (archi_table
[i
].version
);
2061 /****************************************************************
2062 _spoolss_DeletePrinterDriver
2063 ****************************************************************/
2065 WERROR
_spoolss_DeletePrinterDriver(struct pipes_struct
*p
,
2066 struct spoolss_DeletePrinterDriver
*r
)
2069 struct spoolss_DriverInfo8
*info
= NULL
;
2072 struct dcerpc_binding_handle
*b
;
2073 TALLOC_CTX
*tmp_ctx
= NULL
;
2077 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2078 and not a printer admin, then fail */
2080 if ( (p
->session_info
->unix_token
->uid
!= sec_initial_uid())
2081 && !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
)
2082 && !token_contains_name_in_list(
2083 uidtoname(p
->session_info
->unix_token
->uid
),
2084 p
->session_info
->info
->domain_name
,
2086 p
->session_info
->security_token
,
2087 lp_printer_admin(-1)) )
2089 return WERR_ACCESS_DENIED
;
2092 /* check that we have a valid driver name first */
2094 if ((version
= get_version_id(r
->in
.architecture
)) == -1) {
2095 return WERR_INVALID_ENVIRONMENT
;
2098 tmp_ctx
= talloc_new(p
->mem_ctx
);
2103 status
= winreg_printer_binding_handle(tmp_ctx
,
2104 get_session_info_system(),
2107 if (!W_ERROR_IS_OK(status
)) {
2111 for (found
= false, i
= 0; drv_cversion
[i
] >= 0; i
++) {
2112 status
= winreg_get_driver(tmp_ctx
, b
,
2113 r
->in
.architecture
, r
->in
.driver
,
2114 drv_cversion
[i
], &info
);
2115 if (!W_ERROR_IS_OK(status
)) {
2116 DEBUG(5, ("skipping del of driver with version %d\n",
2122 if (printer_driver_in_use(tmp_ctx
, b
, info
)) {
2123 status
= WERR_PRINTER_DRIVER_IN_USE
;
2127 status
= winreg_del_driver(tmp_ctx
, b
, info
, drv_cversion
[i
]);
2128 if (!W_ERROR_IS_OK(status
)) {
2129 DEBUG(0, ("failed del of driver with version %d\n",
2134 if (found
== false) {
2135 DEBUG(0, ("driver %s not found for deletion\n", r
->in
.driver
));
2136 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2142 talloc_free(tmp_ctx
);
2147 static WERROR
spoolss_dpd_version(TALLOC_CTX
*mem_ctx
,
2148 struct pipes_struct
*p
,
2149 struct spoolss_DeletePrinterDriverEx
*r
,
2150 struct dcerpc_binding_handle
*b
,
2151 struct spoolss_DriverInfo8
*info
)
2156 if (printer_driver_in_use(mem_ctx
, b
, info
)) {
2157 status
= WERR_PRINTER_DRIVER_IN_USE
;
2162 * we have a couple of cases to consider.
2163 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2164 * then the delete should fail if **any** files overlap with
2166 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2167 * non-overlapping files
2168 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2169 * are set, then do not delete any files
2170 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2173 delete_files
= r
->in
.delete_flags
2174 & (DPD_DELETE_ALL_FILES
| DPD_DELETE_UNUSED_FILES
);
2178 bool in_use
= printer_driver_files_in_use(mem_ctx
, b
, info
);
2179 if (in_use
&& (r
->in
.delete_flags
& DPD_DELETE_ALL_FILES
)) {
2180 status
= WERR_PRINTER_DRIVER_IN_USE
;
2184 * printer_driver_files_in_use() has trimmed overlapping files
2185 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2190 status
= winreg_del_driver(mem_ctx
, b
, info
, info
->version
);
2191 if (!W_ERROR_IS_OK(status
)) {
2196 * now delete any associated files if delete_files is
2197 * true. Even if this part failes, we return succes
2198 * because the driver doesn not exist any more
2201 delete_driver_files(get_session_info_system(), info
);
2208 /****************************************************************
2209 _spoolss_DeletePrinterDriverEx
2210 ****************************************************************/
2212 WERROR
_spoolss_DeletePrinterDriverEx(struct pipes_struct
*p
,
2213 struct spoolss_DeletePrinterDriverEx
*r
)
2215 struct spoolss_DriverInfo8
*info
= NULL
;
2217 struct dcerpc_binding_handle
*b
;
2218 TALLOC_CTX
*tmp_ctx
= NULL
;
2222 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2223 and not a printer admin, then fail */
2225 if ( (p
->session_info
->unix_token
->uid
!= sec_initial_uid())
2226 && !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
)
2227 && !token_contains_name_in_list(
2228 uidtoname(p
->session_info
->unix_token
->uid
),
2229 p
->session_info
->info
->domain_name
,
2231 p
->session_info
->security_token
, lp_printer_admin(-1)) )
2233 return WERR_ACCESS_DENIED
;
2236 /* check that we have a valid driver name first */
2237 if (get_version_id(r
->in
.architecture
) == -1) {
2238 /* this is what NT returns */
2239 return WERR_INVALID_ENVIRONMENT
;
2242 tmp_ctx
= talloc_new(p
->mem_ctx
);
2247 status
= winreg_printer_binding_handle(tmp_ctx
,
2248 get_session_info_system(),
2251 if (!W_ERROR_IS_OK(status
)) {
2255 for (found
= false, i
= 0; drv_cversion
[i
] >= 0; i
++) {
2256 if ((r
->in
.delete_flags
& DPD_DELETE_SPECIFIC_VERSION
)
2257 && (drv_cversion
[i
] != r
->in
.version
)) {
2261 /* check if a driver with this version exists before delete */
2262 status
= winreg_get_driver(tmp_ctx
, b
,
2263 r
->in
.architecture
, r
->in
.driver
,
2264 drv_cversion
[i
], &info
);
2265 if (!W_ERROR_IS_OK(status
)) {
2266 DEBUG(5, ("skipping del of driver with version %d\n",
2272 status
= spoolss_dpd_version(tmp_ctx
, p
, r
, b
, info
);
2273 if (!NT_STATUS_IS_OK(status
)) {
2274 DEBUG(0, ("failed to delete driver with version %d\n",
2279 if (found
== false) {
2280 DEBUG(0, ("driver %s not found for deletion\n", r
->in
.driver
));
2281 status
= WERR_UNKNOWN_PRINTER_DRIVER
;
2287 talloc_free(tmp_ctx
);
2292 /********************************************************************
2293 GetPrinterData on a printer server Handle.
2294 ********************************************************************/
2296 static WERROR
getprinterdata_printer_server(TALLOC_CTX
*mem_ctx
,
2298 enum winreg_Type
*type
,
2299 union spoolss_PrinterData
*data
)
2301 DEBUG(8,("getprinterdata_printer_server:%s\n", value
));
2303 if (!strcasecmp_m(value
, "W3SvcInstalled")) {
2309 if (!strcasecmp_m(value
, "BeepEnabled")) {
2315 if (!strcasecmp_m(value
, "EventLog")) {
2317 /* formally was 0x1b */
2322 if (!strcasecmp_m(value
, "NetPopup")) {
2328 if (!strcasecmp_m(value
, "MajorVersion")) {
2331 /* Windows NT 4.0 seems to not allow uploading of drivers
2332 to a server that reports 0x3 as the MajorVersion.
2333 need to investigate more how Win2k gets around this .
2336 if (RA_WINNT
== get_remote_arch()) {
2345 if (!strcasecmp_m(value
, "MinorVersion")) {
2352 * uint32_t size = 0x114
2353 * uint32_t major = 5
2354 * uint32_t minor = [0|1]
2355 * uint32_t build = [2195|2600]
2356 * extra unicode string = e.g. "Service Pack 3"
2358 if (!strcasecmp_m(value
, "OSVersion")) {
2360 enum ndr_err_code ndr_err
;
2361 struct spoolss_OSVersion os
;
2363 os
.major
= 5; /* Windows 2000 == 5.0 */
2365 os
.build
= 2195; /* build */
2366 os
.extra_string
= ""; /* leave extra string empty */
2368 ndr_err
= ndr_push_struct_blob(&blob
, mem_ctx
, &os
,
2369 (ndr_push_flags_fn_t
)ndr_push_spoolss_OSVersion
);
2370 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
2371 return WERR_GENERAL_FAILURE
;
2375 data
->binary
= blob
;
2381 if (!strcasecmp_m(value
, "DefaultSpoolDirectory")) {
2384 data
->string
= talloc_strdup(mem_ctx
, "C:\\PRINTERS");
2385 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2390 if (!strcasecmp_m(value
, "Architecture")) {
2392 data
->string
= talloc_strdup(mem_ctx
,
2393 lp_parm_const_string(GLOBAL_SECTION_SNUM
, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86
));
2394 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2399 if (!strcasecmp_m(value
, "DsPresent")) {
2402 /* only show the publish check box if we are a
2403 member of a AD domain */
2405 if (lp_security() == SEC_ADS
) {
2413 if (!strcasecmp_m(value
, "DNSMachineName")) {
2414 const char *hostname
= get_mydnsfullname();
2417 return WERR_BADFILE
;
2421 data
->string
= talloc_strdup(mem_ctx
, hostname
);
2422 W_ERROR_HAVE_NO_MEMORY(data
->string
);
2429 return WERR_INVALID_PARAM
;
2432 /****************************************************************
2433 _spoolss_GetPrinterData
2434 ****************************************************************/
2436 WERROR
_spoolss_GetPrinterData(struct pipes_struct
*p
,
2437 struct spoolss_GetPrinterData
*r
)
2439 struct spoolss_GetPrinterDataEx r2
;
2441 r2
.in
.handle
= r
->in
.handle
;
2442 r2
.in
.key_name
= "PrinterDriverData";
2443 r2
.in
.value_name
= r
->in
.value_name
;
2444 r2
.in
.offered
= r
->in
.offered
;
2445 r2
.out
.type
= r
->out
.type
;
2446 r2
.out
.data
= r
->out
.data
;
2447 r2
.out
.needed
= r
->out
.needed
;
2449 return _spoolss_GetPrinterDataEx(p
, &r2
);
2452 /*********************************************************
2453 Connect to the client machine.
2454 **********************************************************/
2456 static bool spoolss_connect_to_client(struct rpc_pipe_client
**pp_pipe
,
2457 struct sockaddr_storage
*client_ss
, const char *remote_machine
)
2460 struct cli_state
*the_cli
;
2461 struct sockaddr_storage rm_addr
;
2462 char addr
[INET6_ADDRSTRLEN
];
2464 if ( is_zero_addr(client_ss
) ) {
2465 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2467 if ( !resolve_name( remote_machine
, &rm_addr
, 0x20, false) ) {
2468 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine
));
2471 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2473 rm_addr
= *client_ss
;
2474 print_sockaddr(addr
, sizeof(addr
), &rm_addr
);
2475 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2479 if (ismyaddr((struct sockaddr
*)(void *)&rm_addr
)) {
2480 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2485 /* setup the connection */
2486 ret
= cli_full_connection( &the_cli
, lp_netbios_name(), remote_machine
,
2487 &rm_addr
, 0, "IPC$", "IPC",
2491 0, lp_client_signing());
2493 if ( !NT_STATUS_IS_OK( ret
) ) {
2494 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2499 if ( cli_state_protocol(the_cli
) != PROTOCOL_NT1
) {
2500 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine
));
2501 cli_shutdown(the_cli
);
2506 * Ok - we have an anonymous connection to the IPC$ share.
2507 * Now start the NT Domain stuff :-).
2510 ret
= cli_rpc_pipe_open_noauth(the_cli
, &ndr_table_spoolss
.syntax_id
, pp_pipe
);
2511 if (!NT_STATUS_IS_OK(ret
)) {
2512 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2513 remote_machine
, nt_errstr(ret
)));
2514 cli_shutdown(the_cli
);
2521 /***************************************************************************
2522 Connect to the client.
2523 ****************************************************************************/
2525 static bool srv_spoolss_replyopenprinter(int snum
, const char *printer
,
2526 uint32_t localprinter
,
2527 enum winreg_Type type
,
2528 struct policy_handle
*handle
,
2529 struct notify_back_channel
**_chan
,
2530 struct sockaddr_storage
*client_ss
,
2531 struct messaging_context
*msg_ctx
)
2535 struct notify_back_channel
*chan
;
2537 for (chan
= back_channels
; chan
; chan
= chan
->next
) {
2538 if (memcmp(&chan
->client_address
, client_ss
,
2539 sizeof(struct sockaddr_storage
)) == 0) {
2545 * If it's the first connection, contact the client
2546 * and connect to the IPC$ share anonymously
2549 fstring unix_printer
;
2551 /* the +2 is to strip the leading 2 backslashs */
2552 fstrcpy(unix_printer
, printer
+ 2);
2554 chan
= talloc_zero(NULL
, struct notify_back_channel
);
2558 chan
->client_address
= *client_ss
;
2560 if (!spoolss_connect_to_client(&chan
->cli_pipe
, client_ss
, unix_printer
)) {
2565 DLIST_ADD(back_channels
, chan
);
2567 messaging_register(msg_ctx
, NULL
, MSG_PRINTER_NOTIFY2
,
2568 receive_notify2_message_list
);
2571 if (chan
->cli_pipe
== NULL
||
2572 chan
->cli_pipe
->binding_handle
== NULL
) {
2573 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2574 "NULL %s for printer %s\n",
2575 chan
->cli_pipe
== NULL
?
2576 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2582 * Tell the specific printing tdb we want messages for this printer
2583 * by registering our PID.
2586 if (!print_notify_register_pid(snum
)) {
2587 DEBUG(0, ("Failed to register our pid for printer %s\n",
2591 status
= dcerpc_spoolss_ReplyOpenPrinter(chan
->cli_pipe
->binding_handle
,
2600 if (!NT_STATUS_IS_OK(status
)) {
2601 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status
)));
2602 result
= ntstatus_to_werror(status
);
2603 } else if (!W_ERROR_IS_OK(result
)) {
2604 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result
)));
2607 chan
->active_connections
++;
2610 return (W_ERROR_IS_OK(result
));
2613 /****************************************************************
2614 ****************************************************************/
2616 static struct spoolss_NotifyOption
*dup_spoolss_NotifyOption(TALLOC_CTX
*mem_ctx
,
2617 const struct spoolss_NotifyOption
*r
)
2619 struct spoolss_NotifyOption
*option
;
2626 option
= talloc_zero(mem_ctx
, struct spoolss_NotifyOption
);
2633 if (!option
->count
) {
2637 option
->types
= talloc_zero_array(option
,
2638 struct spoolss_NotifyOptionType
, option
->count
);
2639 if (!option
->types
) {
2640 talloc_free(option
);
2644 for (i
=0; i
< option
->count
; i
++) {
2645 option
->types
[i
] = r
->types
[i
];
2647 if (option
->types
[i
].count
) {
2648 option
->types
[i
].fields
= talloc_zero_array(option
,
2649 union spoolss_Field
, option
->types
[i
].count
);
2650 if (!option
->types
[i
].fields
) {
2651 talloc_free(option
);
2654 for (k
=0; k
<option
->types
[i
].count
; k
++) {
2655 option
->types
[i
].fields
[k
] =
2656 r
->types
[i
].fields
[k
];
2664 /****************************************************************
2665 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2667 * before replying OK: status=0 a rpc call is made to the workstation
2668 * asking ReplyOpenPrinter
2670 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2671 * called from api_spoolss_rffpcnex
2672 ****************************************************************/
2674 WERROR
_spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct
*p
,
2675 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx
*r
)
2678 struct spoolss_NotifyOption
*option
= r
->in
.notify_options
;
2679 struct sockaddr_storage client_ss
;
2680 socklen_t client_len
;
2682 /* store the notify value in the printer struct */
2684 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
2687 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2688 "Invalid handle (%s:%u:%u).\n",
2689 OUR_HANDLE(r
->in
.handle
)));
2693 Printer
->notify
.flags
= r
->in
.flags
;
2694 Printer
->notify
.options
= r
->in
.options
;
2695 Printer
->notify
.printerlocal
= r
->in
.printer_local
;
2696 Printer
->notify
.msg_ctx
= p
->msg_ctx
;
2698 TALLOC_FREE(Printer
->notify
.option
);
2699 Printer
->notify
.option
= dup_spoolss_NotifyOption(Printer
, option
);
2701 fstrcpy(Printer
->notify
.localmachine
, r
->in
.local_machine
);
2703 /* Connect to the client machine and send a ReplyOpenPrinter */
2705 if ( Printer
->printer_type
== SPLHND_SERVER
)
2707 else if ( (Printer
->printer_type
== SPLHND_PRINTER
) &&
2708 !get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
) )
2711 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2712 "remote_address is %s\n",
2713 tsocket_address_string(p
->remote_address
, p
->mem_ctx
)));
2715 if (!lp_print_notify_backchannel(snum
)) {
2716 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2717 "backchannel disabled\n"));
2718 return WERR_SERVER_UNAVAILABLE
;
2721 client_len
= tsocket_address_bsd_sockaddr(p
->remote_address
,
2722 (struct sockaddr
*) &client_ss
,
2723 sizeof(struct sockaddr_storage
));
2724 if (client_len
< 0) {
2728 if(!srv_spoolss_replyopenprinter(snum
, Printer
->notify
.localmachine
,
2729 Printer
->notify
.printerlocal
, REG_SZ
,
2730 &Printer
->notify
.cli_hnd
,
2731 &Printer
->notify
.cli_chan
,
2732 &client_ss
, p
->msg_ctx
)) {
2733 return WERR_SERVER_UNAVAILABLE
;
2739 /*******************************************************************
2740 * fill a notify_info_data with the servername
2741 ********************************************************************/
2743 static void spoolss_notify_server_name(struct messaging_context
*msg_ctx
,
2745 struct spoolss_Notify
*data
,
2746 print_queue_struct
*queue
,
2747 struct spoolss_PrinterInfo2
*pinfo2
,
2748 TALLOC_CTX
*mem_ctx
)
2750 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->servername
);
2753 /*******************************************************************
2754 * fill a notify_info_data with the printername (not including the servername).
2755 ********************************************************************/
2757 static void spoolss_notify_printer_name(struct messaging_context
*msg_ctx
,
2759 struct spoolss_Notify
*data
,
2760 print_queue_struct
*queue
,
2761 struct spoolss_PrinterInfo2
*pinfo2
,
2762 TALLOC_CTX
*mem_ctx
)
2764 /* the notify name should not contain the \\server\ part */
2765 const char *p
= strrchr(pinfo2
->printername
, '\\');
2768 p
= pinfo2
->printername
;
2773 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2776 /*******************************************************************
2777 * fill a notify_info_data with the servicename
2778 ********************************************************************/
2780 static void spoolss_notify_share_name(struct messaging_context
*msg_ctx
,
2782 struct spoolss_Notify
*data
,
2783 print_queue_struct
*queue
,
2784 struct spoolss_PrinterInfo2
*pinfo2
,
2785 TALLOC_CTX
*mem_ctx
)
2787 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, lp_servicename(snum
));
2790 /*******************************************************************
2791 * fill a notify_info_data with the port name
2792 ********************************************************************/
2794 static void spoolss_notify_port_name(struct messaging_context
*msg_ctx
,
2796 struct spoolss_Notify
*data
,
2797 print_queue_struct
*queue
,
2798 struct spoolss_PrinterInfo2
*pinfo2
,
2799 TALLOC_CTX
*mem_ctx
)
2801 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->portname
);
2804 /*******************************************************************
2805 * fill a notify_info_data with the printername
2806 * but it doesn't exist, have to see what to do
2807 ********************************************************************/
2809 static void spoolss_notify_driver_name(struct messaging_context
*msg_ctx
,
2811 struct spoolss_Notify
*data
,
2812 print_queue_struct
*queue
,
2813 struct spoolss_PrinterInfo2
*pinfo2
,
2814 TALLOC_CTX
*mem_ctx
)
2816 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->drivername
);
2819 /*******************************************************************
2820 * fill a notify_info_data with the comment
2821 ********************************************************************/
2823 static void spoolss_notify_comment(struct messaging_context
*msg_ctx
,
2825 struct spoolss_Notify
*data
,
2826 print_queue_struct
*queue
,
2827 struct spoolss_PrinterInfo2
*pinfo2
,
2828 TALLOC_CTX
*mem_ctx
)
2832 if (*pinfo2
->comment
== '\0') {
2833 p
= lp_comment(snum
);
2835 p
= pinfo2
->comment
;
2838 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
2841 /*******************************************************************
2842 * fill a notify_info_data with the comment
2843 * location = "Room 1, floor 2, building 3"
2844 ********************************************************************/
2846 static void spoolss_notify_location(struct messaging_context
*msg_ctx
,
2848 struct spoolss_Notify
*data
,
2849 print_queue_struct
*queue
,
2850 struct spoolss_PrinterInfo2
*pinfo2
,
2851 TALLOC_CTX
*mem_ctx
)
2853 const char *loc
= pinfo2
->location
;
2856 status
= printer_list_get_printer(mem_ctx
,
2861 if (NT_STATUS_IS_OK(status
)) {
2863 loc
= pinfo2
->location
;
2867 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, loc
);
2870 /*******************************************************************
2871 * fill a notify_info_data with the device mode
2872 * jfm:xxxx don't to it for know but that's a real problem !!!
2873 ********************************************************************/
2875 static void spoolss_notify_devmode(struct messaging_context
*msg_ctx
,
2877 struct spoolss_Notify
*data
,
2878 print_queue_struct
*queue
,
2879 struct spoolss_PrinterInfo2
*pinfo2
,
2880 TALLOC_CTX
*mem_ctx
)
2882 /* for a dummy implementation we have to zero the fields */
2883 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data
, NULL
);
2886 /*******************************************************************
2887 * fill a notify_info_data with the separator file name
2888 ********************************************************************/
2890 static void spoolss_notify_sepfile(struct messaging_context
*msg_ctx
,
2892 struct spoolss_Notify
*data
,
2893 print_queue_struct
*queue
,
2894 struct spoolss_PrinterInfo2
*pinfo2
,
2895 TALLOC_CTX
*mem_ctx
)
2897 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->sepfile
);
2900 /*******************************************************************
2901 * fill a notify_info_data with the print processor
2902 * jfm:xxxx return always winprint to indicate we don't do anything to it
2903 ********************************************************************/
2905 static void spoolss_notify_print_processor(struct messaging_context
*msg_ctx
,
2907 struct spoolss_Notify
*data
,
2908 print_queue_struct
*queue
,
2909 struct spoolss_PrinterInfo2
*pinfo2
,
2910 TALLOC_CTX
*mem_ctx
)
2912 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->printprocessor
);
2915 /*******************************************************************
2916 * fill a notify_info_data with the print processor options
2917 * jfm:xxxx send an empty string
2918 ********************************************************************/
2920 static void spoolss_notify_parameters(struct messaging_context
*msg_ctx
,
2922 struct spoolss_Notify
*data
,
2923 print_queue_struct
*queue
,
2924 struct spoolss_PrinterInfo2
*pinfo2
,
2925 TALLOC_CTX
*mem_ctx
)
2927 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->parameters
);
2930 /*******************************************************************
2931 * fill a notify_info_data with the data type
2932 * jfm:xxxx always send RAW as data type
2933 ********************************************************************/
2935 static void spoolss_notify_datatype(struct messaging_context
*msg_ctx
,
2937 struct spoolss_Notify
*data
,
2938 print_queue_struct
*queue
,
2939 struct spoolss_PrinterInfo2
*pinfo2
,
2940 TALLOC_CTX
*mem_ctx
)
2942 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, pinfo2
->datatype
);
2945 /*******************************************************************
2946 * fill a notify_info_data with the security descriptor
2947 * jfm:xxxx send an null pointer to say no security desc
2948 * have to implement security before !
2949 ********************************************************************/
2951 static void spoolss_notify_security_desc(struct messaging_context
*msg_ctx
,
2953 struct spoolss_Notify
*data
,
2954 print_queue_struct
*queue
,
2955 struct spoolss_PrinterInfo2
*pinfo2
,
2956 TALLOC_CTX
*mem_ctx
)
2958 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data
, pinfo2
->secdesc
);
2961 /*******************************************************************
2962 * fill a notify_info_data with the attributes
2963 * jfm:xxxx a samba printer is always shared
2964 ********************************************************************/
2966 static void spoolss_notify_attributes(struct messaging_context
*msg_ctx
,
2968 struct spoolss_Notify
*data
,
2969 print_queue_struct
*queue
,
2970 struct spoolss_PrinterInfo2
*pinfo2
,
2971 TALLOC_CTX
*mem_ctx
)
2973 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->attributes
);
2976 /*******************************************************************
2977 * fill a notify_info_data with the priority
2978 ********************************************************************/
2980 static void spoolss_notify_priority(struct messaging_context
*msg_ctx
,
2982 struct spoolss_Notify
*data
,
2983 print_queue_struct
*queue
,
2984 struct spoolss_PrinterInfo2
*pinfo2
,
2985 TALLOC_CTX
*mem_ctx
)
2987 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->priority
);
2990 /*******************************************************************
2991 * fill a notify_info_data with the default priority
2992 ********************************************************************/
2994 static void spoolss_notify_default_priority(struct messaging_context
*msg_ctx
,
2996 struct spoolss_Notify
*data
,
2997 print_queue_struct
*queue
,
2998 struct spoolss_PrinterInfo2
*pinfo2
,
2999 TALLOC_CTX
*mem_ctx
)
3001 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->defaultpriority
);
3004 /*******************************************************************
3005 * fill a notify_info_data with the start time
3006 ********************************************************************/
3008 static void spoolss_notify_start_time(struct messaging_context
*msg_ctx
,
3010 struct spoolss_Notify
*data
,
3011 print_queue_struct
*queue
,
3012 struct spoolss_PrinterInfo2
*pinfo2
,
3013 TALLOC_CTX
*mem_ctx
)
3015 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->starttime
);
3018 /*******************************************************************
3019 * fill a notify_info_data with the until time
3020 ********************************************************************/
3022 static void spoolss_notify_until_time(struct messaging_context
*msg_ctx
,
3024 struct spoolss_Notify
*data
,
3025 print_queue_struct
*queue
,
3026 struct spoolss_PrinterInfo2
*pinfo2
,
3027 TALLOC_CTX
*mem_ctx
)
3029 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->untiltime
);
3032 /*******************************************************************
3033 * fill a notify_info_data with the status
3034 ********************************************************************/
3036 static void spoolss_notify_status(struct messaging_context
*msg_ctx
,
3038 struct spoolss_Notify
*data
,
3039 print_queue_struct
*queue
,
3040 struct spoolss_PrinterInfo2
*pinfo2
,
3041 TALLOC_CTX
*mem_ctx
)
3043 print_status_struct status
;
3045 print_queue_length(msg_ctx
, snum
, &status
);
3046 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, status
.status
);
3049 /*******************************************************************
3050 * fill a notify_info_data with the number of jobs queued
3051 ********************************************************************/
3053 static void spoolss_notify_cjobs(struct messaging_context
*msg_ctx
,
3055 struct spoolss_Notify
*data
,
3056 print_queue_struct
*queue
,
3057 struct spoolss_PrinterInfo2
*pinfo2
,
3058 TALLOC_CTX
*mem_ctx
)
3060 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3061 data
, print_queue_length(msg_ctx
, snum
, NULL
));
3064 /*******************************************************************
3065 * fill a notify_info_data with the average ppm
3066 ********************************************************************/
3068 static void spoolss_notify_average_ppm(struct messaging_context
*msg_ctx
,
3070 struct spoolss_Notify
*data
,
3071 print_queue_struct
*queue
,
3072 struct spoolss_PrinterInfo2
*pinfo2
,
3073 TALLOC_CTX
*mem_ctx
)
3075 /* always respond 8 pages per minutes */
3076 /* a little hard ! */
3077 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, pinfo2
->averageppm
);
3080 /*******************************************************************
3081 * fill a notify_info_data with username
3082 ********************************************************************/
3084 static void spoolss_notify_username(struct messaging_context
*msg_ctx
,
3086 struct spoolss_Notify
*data
,
3087 print_queue_struct
*queue
,
3088 struct spoolss_PrinterInfo2
*pinfo2
,
3089 TALLOC_CTX
*mem_ctx
)
3091 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_user
);
3094 /*******************************************************************
3095 * fill a notify_info_data with job status
3096 ********************************************************************/
3098 static void spoolss_notify_job_status(struct messaging_context
*msg_ctx
,
3100 struct spoolss_Notify
*data
,
3101 print_queue_struct
*queue
,
3102 struct spoolss_PrinterInfo2
*pinfo2
,
3103 TALLOC_CTX
*mem_ctx
)
3105 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, nt_printj_status(queue
->status
));
3108 /*******************************************************************
3109 * fill a notify_info_data with job name
3110 ********************************************************************/
3112 static void spoolss_notify_job_name(struct messaging_context
*msg_ctx
,
3114 struct spoolss_Notify
*data
,
3115 print_queue_struct
*queue
,
3116 struct spoolss_PrinterInfo2
*pinfo2
,
3117 TALLOC_CTX
*mem_ctx
)
3119 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, queue
->fs_file
);
3122 /*******************************************************************
3123 * fill a notify_info_data with job status
3124 ********************************************************************/
3126 static void spoolss_notify_job_status_string(struct messaging_context
*msg_ctx
,
3128 struct spoolss_Notify
*data
,
3129 print_queue_struct
*queue
,
3130 struct spoolss_PrinterInfo2
*pinfo2
,
3131 TALLOC_CTX
*mem_ctx
)
3134 * Now we're returning job status codes we just return a "" here. JRA.
3139 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3142 switch (queue
->status
) {
3147 p
= ""; /* NT provides the paused string */
3156 #endif /* NO LONGER NEEDED. */
3158 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data
, p
);
3161 /*******************************************************************
3162 * fill a notify_info_data with job time
3163 ********************************************************************/
3165 static void spoolss_notify_job_time(struct messaging_context
*msg_ctx
,
3167 struct spoolss_Notify
*data
,
3168 print_queue_struct
*queue
,
3169 struct spoolss_PrinterInfo2
*pinfo2
,
3170 TALLOC_CTX
*mem_ctx
)
3172 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3175 /*******************************************************************
3176 * fill a notify_info_data with job size
3177 ********************************************************************/
3179 static void spoolss_notify_job_size(struct messaging_context
*msg_ctx
,
3181 struct spoolss_Notify
*data
,
3182 print_queue_struct
*queue
,
3183 struct spoolss_PrinterInfo2
*pinfo2
,
3184 TALLOC_CTX
*mem_ctx
)
3186 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->size
);
3189 /*******************************************************************
3190 * fill a notify_info_data with page info
3191 ********************************************************************/
3192 static void spoolss_notify_total_pages(struct messaging_context
*msg_ctx
,
3194 struct spoolss_Notify
*data
,
3195 print_queue_struct
*queue
,
3196 struct spoolss_PrinterInfo2
*pinfo2
,
3197 TALLOC_CTX
*mem_ctx
)
3199 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->page_count
);
3202 /*******************************************************************
3203 * fill a notify_info_data with pages printed info.
3204 ********************************************************************/
3205 static void spoolss_notify_pages_printed(struct messaging_context
*msg_ctx
,
3207 struct spoolss_Notify
*data
,
3208 print_queue_struct
*queue
,
3209 struct spoolss_PrinterInfo2
*pinfo2
,
3210 TALLOC_CTX
*mem_ctx
)
3212 /* Add code when back-end tracks this */
3213 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, 0);
3216 /*******************************************************************
3217 Fill a notify_info_data with job position.
3218 ********************************************************************/
3220 static void spoolss_notify_job_position(struct messaging_context
*msg_ctx
,
3222 struct spoolss_Notify
*data
,
3223 print_queue_struct
*queue
,
3224 struct spoolss_PrinterInfo2
*pinfo2
,
3225 TALLOC_CTX
*mem_ctx
)
3227 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data
, queue
->job
);
3230 /*******************************************************************
3231 Fill a notify_info_data with submitted time.
3232 ********************************************************************/
3234 static void spoolss_notify_submitted_time(struct messaging_context
*msg_ctx
,
3236 struct spoolss_Notify
*data
,
3237 print_queue_struct
*queue
,
3238 struct spoolss_PrinterInfo2
*pinfo2
,
3239 TALLOC_CTX
*mem_ctx
)
3241 data
->data
.string
.string
= NULL
;
3242 data
->data
.string
.size
= 0;
3244 init_systemtime_buffer(mem_ctx
, gmtime(&queue
->time
),
3245 &data
->data
.string
.string
,
3246 &data
->data
.string
.size
);
3250 struct s_notify_info_data_table
3252 enum spoolss_NotifyType type
;
3255 enum spoolss_NotifyTable variable_type
;
3256 void (*fn
) (struct messaging_context
*msg_ctx
,
3257 int snum
, struct spoolss_Notify
*data
,
3258 print_queue_struct
*queue
,
3259 struct spoolss_PrinterInfo2
*pinfo2
,
3260 TALLOC_CTX
*mem_ctx
);
3263 /* A table describing the various print notification constants and
3264 whether the notification data is a pointer to a variable sized
3265 buffer, a one value uint32_t or a two value uint32_t. */
3267 static const struct s_notify_info_data_table notify_info_data_table
[] =
3269 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SERVER_NAME
, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3270 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINTER_NAME
, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3271 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SHARE_NAME
, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_share_name
},
3272 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PORT_NAME
, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3273 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DRIVER_NAME
, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3274 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_COMMENT
, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING
, spoolss_notify_comment
},
3275 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_LOCATION
, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING
, spoolss_notify_location
},
3276 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEVMODE
, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3277 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SEPFILE
, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING
, spoolss_notify_sepfile
},
3278 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR
, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3279 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PARAMETERS
, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3280 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DATATYPE
, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3281 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, spoolss_notify_security_desc
},
3282 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_ATTRIBUTES
, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD
, spoolss_notify_attributes
},
3283 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PRIORITY
, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3284 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY
, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_default_priority
},
3285 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_START_TIME
, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3286 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_UNTIL_TIME
, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3287 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS
, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_status
},
3288 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_STATUS_STRING
, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, NULL
},
3289 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_CJOBS
, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD
, spoolss_notify_cjobs
},
3290 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_AVERAGE_PPM
, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD
, spoolss_notify_average_ppm
},
3291 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_PAGES
, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, NULL
},
3292 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_PAGES_PRINTED
, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3293 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_TOTAL_BYTES
, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, NULL
},
3294 { PRINTER_NOTIFY_TYPE
, PRINTER_NOTIFY_FIELD_BYTES_PRINTED
, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD
, NULL
},
3295 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINTER_NAME
, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_printer_name
},
3296 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_MACHINE_NAME
, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_server_name
},
3297 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PORT_NAME
, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_port_name
},
3298 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_USER_NAME
, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3299 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_NOTIFY_NAME
, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_username
},
3300 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DATATYPE
, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING
, spoolss_notify_datatype
},
3301 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRINT_PROCESSOR
, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING
, spoolss_notify_print_processor
},
3302 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PARAMETERS
, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING
, spoolss_notify_parameters
},
3303 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DRIVER_NAME
, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING
, spoolss_notify_driver_name
},
3304 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DEVMODE
, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE
, spoolss_notify_devmode
},
3305 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS
, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD
, spoolss_notify_job_status
},
3306 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_STATUS_STRING
, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING
, spoolss_notify_job_status_string
},
3307 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR
, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR
, NULL
},
3308 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_DOCUMENT
, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING
, spoolss_notify_job_name
},
3309 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PRIORITY
, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD
, spoolss_notify_priority
},
3310 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_POSITION
, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD
, spoolss_notify_job_position
},
3311 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_SUBMITTED
, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME
, spoolss_notify_submitted_time
},
3312 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_START_TIME
, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_start_time
},
3313 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_UNTIL_TIME
, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_until_time
},
3314 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TIME
, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD
, spoolss_notify_job_time
},
3315 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_PAGES
, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD
, spoolss_notify_total_pages
},
3316 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_PAGES_PRINTED
, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD
, spoolss_notify_pages_printed
},
3317 { JOB_NOTIFY_TYPE
, JOB_NOTIFY_FIELD_TOTAL_BYTES
, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD
, spoolss_notify_job_size
},
3320 /*******************************************************************
3321 Return the variable_type of info_data structure.
3322 ********************************************************************/
3324 static enum spoolss_NotifyTable
variable_type_of_notify_info_data(enum spoolss_NotifyType type
,
3329 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3330 if ( (notify_info_data_table
[i
].type
== type
) &&
3331 (notify_info_data_table
[i
].field
== field
) ) {
3332 return notify_info_data_table
[i
].variable_type
;
3336 DEBUG(5, ("invalid notify data type %d/%d\n", type
, field
));
3338 return (enum spoolss_NotifyTable
) 0;
3341 /****************************************************************************
3342 ****************************************************************************/
3344 static bool search_notify(enum spoolss_NotifyType type
,
3350 for (i
= 0; i
< ARRAY_SIZE(notify_info_data_table
); i
++) {
3351 if (notify_info_data_table
[i
].type
== type
&&
3352 notify_info_data_table
[i
].field
== field
&&
3353 notify_info_data_table
[i
].fn
!= NULL
) {
3362 /****************************************************************************
3363 ****************************************************************************/
3365 static void construct_info_data(struct spoolss_Notify
*info_data
,
3366 enum spoolss_NotifyType type
,
3367 uint16_t field
, int id
)
3369 info_data
->type
= type
;
3370 info_data
->field
.field
= field
;
3371 info_data
->variable_type
= variable_type_of_notify_info_data(type
, field
);
3372 info_data
->job_id
= id
;
3375 /*******************************************************************
3377 * fill a notify_info struct with info asked
3379 ********************************************************************/
3381 static bool construct_notify_printer_info(struct messaging_context
*msg_ctx
,
3382 struct printer_handle
*print_hnd
,
3383 struct spoolss_NotifyInfo
*info
,
3384 struct spoolss_PrinterInfo2
*pinfo2
,
3386 const struct spoolss_NotifyOptionType
*option_type
,
3388 TALLOC_CTX
*mem_ctx
)
3391 enum spoolss_NotifyType type
;
3394 struct spoolss_Notify
*current_data
;
3396 type
= option_type
->type
;
3398 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3399 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3400 option_type
->count
, lp_servicename(snum
)));
3402 for(field_num
=0; field_num
< option_type
->count
; field_num
++) {
3403 field
= option_type
->fields
[field_num
].field
;
3405 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num
, type
, field
));
3407 if (!search_notify(type
, field
, &j
) )
3410 info
->notifies
= talloc_realloc(info
, info
->notifies
,
3411 struct spoolss_Notify
,
3413 if (info
->notifies
== NULL
) {
3414 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3418 current_data
= &info
->notifies
[info
->count
];
3420 construct_info_data(current_data
, type
, field
, id
);
3422 DEBUG(10, ("construct_notify_printer_info: "
3423 "calling [%s] snum=%d printername=[%s])\n",
3424 notify_info_data_table
[j
].name
, snum
,
3425 pinfo2
->printername
));
3427 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3428 NULL
, pinfo2
, mem_ctx
);
3436 /*******************************************************************
3438 * fill a notify_info struct with info asked
3440 ********************************************************************/
3442 static bool construct_notify_jobs_info(struct messaging_context
*msg_ctx
,
3443 print_queue_struct
*queue
,
3444 struct spoolss_NotifyInfo
*info
,
3445 struct spoolss_PrinterInfo2
*pinfo2
,
3447 const struct spoolss_NotifyOptionType
*option_type
,
3449 TALLOC_CTX
*mem_ctx
)
3452 enum spoolss_NotifyType type
;
3454 struct spoolss_Notify
*current_data
;
3456 DEBUG(4,("construct_notify_jobs_info\n"));
3458 type
= option_type
->type
;
3460 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3461 (type
== PRINTER_NOTIFY_TYPE
? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3462 option_type
->count
));
3464 for(field_num
=0; field_num
<option_type
->count
; field_num
++) {
3465 field
= option_type
->fields
[field_num
].field
;
3467 if (!search_notify(type
, field
, &j
) )
3470 info
->notifies
= talloc_realloc(info
, info
->notifies
,
3471 struct spoolss_Notify
,
3473 if (info
->notifies
== NULL
) {
3474 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3478 current_data
=&(info
->notifies
[info
->count
]);
3480 construct_info_data(current_data
, type
, field
, id
);
3481 notify_info_data_table
[j
].fn(msg_ctx
, snum
, current_data
,
3482 queue
, pinfo2
, mem_ctx
);
3490 * JFM: The enumeration is not that simple, it's even non obvious.
3492 * let's take an example: I want to monitor the PRINTER SERVER for
3493 * the printer's name and the number of jobs currently queued.
3494 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3495 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3497 * I have 3 printers on the back of my server.
3499 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3502 * 1 printer 1 name 1
3503 * 2 printer 1 cjob 1
3504 * 3 printer 2 name 2
3505 * 4 printer 2 cjob 2
3506 * 5 printer 3 name 3
3507 * 6 printer 3 name 3
3509 * that's the print server case, the printer case is even worse.
3512 /*******************************************************************
3514 * enumerate all printers on the printserver
3515 * fill a notify_info struct with info asked
3517 ********************************************************************/
3519 static WERROR
printserver_notify_info(struct pipes_struct
*p
,
3520 struct policy_handle
*hnd
,
3521 struct spoolss_NotifyInfo
*info
,
3522 TALLOC_CTX
*mem_ctx
)
3525 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3526 int n_services
=lp_numservices();
3528 struct spoolss_NotifyOption
*option
;
3529 struct spoolss_NotifyOptionType option_type
;
3530 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3533 DEBUG(4,("printserver_notify_info\n"));
3538 option
= Printer
->notify
.option
;
3541 info
->notifies
= NULL
;
3544 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3545 sending a ffpcn() request first */
3550 for (i
=0; i
<option
->count
; i
++) {
3551 option_type
= option
->types
[i
];
3553 if (option_type
.type
!= PRINTER_NOTIFY_TYPE
)
3556 for (snum
= 0; snum
< n_services
; snum
++) {
3557 if (!lp_browseable(snum
) ||
3558 !lp_snum_ok(snum
) ||
3559 !lp_print_ok(snum
)) {
3560 continue; /* skip */
3563 /* Maybe we should use the SYSTEM session_info here... */
3564 result
= winreg_get_printer_internal(mem_ctx
,
3565 get_session_info_system(),
3567 lp_servicename(snum
),
3569 if (!W_ERROR_IS_OK(result
)) {
3570 DEBUG(4, ("printserver_notify_info: "
3571 "Failed to get printer [%s]\n",
3572 lp_servicename(snum
)));
3577 construct_notify_printer_info(p
->msg_ctx
,
3583 TALLOC_FREE(pinfo2
);
3589 * Debugging information, don't delete.
3592 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3593 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info
->version
, info
->flags
, info
->count
));
3594 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3596 for (i
=0; i
<info
->count
; i
++) {
3597 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3598 i
, info
->data
[i
].type
, info
->data
[i
].field
, info
->data
[i
].reserved
,
3599 info
->data
[i
].id
, info
->data
[i
].size
, info
->data
[i
].enc_type
));
3606 /*******************************************************************
3608 * fill a notify_info struct with info asked
3610 ********************************************************************/
3612 static WERROR
printer_notify_info(struct pipes_struct
*p
,
3613 struct policy_handle
*hnd
,
3614 struct spoolss_NotifyInfo
*info
,
3615 TALLOC_CTX
*mem_ctx
)
3618 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, hnd
);
3621 struct spoolss_NotifyOption
*option
;
3622 struct spoolss_NotifyOptionType option_type
;
3624 print_queue_struct
*queue
=NULL
;
3625 print_status_struct status
;
3626 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
3629 DEBUG(4,("printer_notify_info\n"));
3634 option
= Printer
->notify
.option
;
3638 info
->notifies
= NULL
;
3641 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3642 sending a ffpcn() request first */
3647 if (!get_printer_snum(p
, hnd
, &snum
, NULL
)) {
3651 /* Maybe we should use the SYSTEM session_info here... */
3652 result
= winreg_get_printer_internal(mem_ctx
,
3653 get_session_info_system(),
3655 lp_servicename(snum
), &pinfo2
);
3656 if (!W_ERROR_IS_OK(result
)) {
3661 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3662 * correct servername.
3664 pinfo2
->servername
= talloc_strdup(pinfo2
, Printer
->servername
);
3665 if (pinfo2
->servername
== NULL
) {
3669 for (i
=0; i
<option
->count
; i
++) {
3670 option_type
= option
->types
[i
];
3672 switch (option_type
.type
) {
3673 case PRINTER_NOTIFY_TYPE
:
3674 if (construct_notify_printer_info(p
->msg_ctx
,
3683 case JOB_NOTIFY_TYPE
:
3685 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
,
3688 for (j
=0; j
<count
; j
++) {
3689 construct_notify_jobs_info(p
->msg_ctx
,
3703 * Debugging information, don't delete.
3706 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3707 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3708 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3710 for (i=0; i<info->count; i++) {
3711 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3712 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3713 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3717 talloc_free(pinfo2
);
3721 /****************************************************************
3722 _spoolss_RouterRefreshPrinterChangeNotify
3723 ****************************************************************/
3725 WERROR
_spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct
*p
,
3726 struct spoolss_RouterRefreshPrinterChangeNotify
*r
)
3728 struct spoolss_NotifyInfo
*info
;
3730 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
3731 WERROR result
= WERR_BADFID
;
3733 /* we always have a spoolss_NotifyInfo struct */
3734 info
= talloc_zero(p
->mem_ctx
, struct spoolss_NotifyInfo
);
3736 result
= WERR_NOMEM
;
3740 *r
->out
.info
= info
;
3743 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3744 "Invalid handle (%s:%u:%u).\n",
3745 OUR_HANDLE(r
->in
.handle
)));
3749 DEBUG(4,("Printer type %x\n",Printer
->printer_type
));
3752 * We are now using the change value, and
3753 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3754 * I don't have a global notification system, I'm sending back all the
3755 * information even when _NOTHING_ has changed.
3758 /* We need to keep track of the change value to send back in
3759 RRPCN replies otherwise our updates are ignored. */
3761 Printer
->notify
.fnpcn
= true;
3763 if (Printer
->notify
.cli_chan
!= NULL
&&
3764 Printer
->notify
.cli_chan
->active_connections
> 0) {
3765 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3766 "Saving change value in request [%x]\n",
3768 Printer
->notify
.change
= r
->in
.change_low
;
3771 /* just ignore the spoolss_NotifyOption */
3773 switch (Printer
->printer_type
) {
3775 result
= printserver_notify_info(p
, r
->in
.handle
,
3779 case SPLHND_PRINTER
:
3780 result
= printer_notify_info(p
, r
->in
.handle
,
3785 Printer
->notify
.fnpcn
= false;
3791 /********************************************************************
3792 ********************************************************************/
3794 static WERROR
create_printername(TALLOC_CTX
*mem_ctx
,
3795 const char *servername
,
3796 const char *printername
,
3797 const char **printername_p
)
3799 /* FIXME: add lp_force_printername() */
3801 if (servername
== NULL
) {
3802 *printername_p
= talloc_strdup(mem_ctx
, printername
);
3803 W_ERROR_HAVE_NO_MEMORY(*printername_p
);
3807 if (servername
[0] == '\\' && servername
[1] == '\\') {
3811 *printername_p
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s", servername
, printername
);
3812 W_ERROR_HAVE_NO_MEMORY(*printername_p
);
3817 /********************************************************************
3818 ********************************************************************/
3820 static void compose_devicemode_devicename(struct spoolss_DeviceMode
*dm
,
3821 const char *printername
)
3827 dm
->devicename
= talloc_strndup(dm
, printername
,
3828 MIN(strlen(printername
), 31));
3831 /********************************************************************
3832 * construct_printer_info_0
3833 * fill a printer_info_0 struct
3834 ********************************************************************/
3836 static WERROR
construct_printer_info0(TALLOC_CTX
*mem_ctx
,
3837 const struct auth_session_info
*session_info
,
3838 struct messaging_context
*msg_ctx
,
3839 struct spoolss_PrinterInfo2
*info2
,
3840 const char *servername
,
3841 struct spoolss_PrinterInfo0
*r
,
3845 struct printer_session_counter
*session_counter
;
3846 struct timeval setuptime
;
3847 print_status_struct status
;
3850 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
3851 if (!W_ERROR_IS_OK(result
)) {
3856 r
->servername
= talloc_strdup(mem_ctx
, servername
);
3857 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3859 r
->servername
= NULL
;
3862 count
= print_queue_length(msg_ctx
, snum
, &status
);
3864 /* check if we already have a counter for this printer */
3865 for (session_counter
= counter_list
; session_counter
; session_counter
= session_counter
->next
) {
3866 if (session_counter
->snum
== snum
)
3870 /* it's the first time, add it to the list */
3871 if (session_counter
== NULL
) {
3872 session_counter
= talloc_zero(counter_list
, struct printer_session_counter
);
3873 W_ERROR_HAVE_NO_MEMORY(session_counter
);
3874 session_counter
->snum
= snum
;
3875 session_counter
->counter
= 0;
3876 DLIST_ADD(counter_list
, session_counter
);
3880 session_counter
->counter
++;
3886 get_startup_time(&setuptime
);
3887 init_systemtime(&r
->time
, gmtime(&setuptime
.tv_sec
));
3890 * the global_counter should be stored in a TDB as it's common to all the clients
3891 * and should be zeroed on samba startup
3893 r
->global_counter
= session_counter
->counter
;
3895 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3896 SSVAL(&r
->version
, 0, 0x0005); /* NT 5 */
3897 SSVAL(&r
->version
, 2, 0x0893); /* build 2195 */
3898 r
->free_build
= SPOOLSS_RELEASE_BUILD
;
3900 r
->max_spooling
= 0;
3901 r
->session_counter
= session_counter
->counter
;
3902 r
->num_error_out_of_paper
= 0x0;
3903 r
->num_error_not_ready
= 0x0; /* number of print failure */
3905 r
->number_of_processors
= 0x1;
3906 r
->processor_type
= PROCESSOR_INTEL_PENTIUM
; /* 586 Pentium ? */
3907 r
->high_part_total_bytes
= 0x0;
3909 /* ChangeID in milliseconds*/
3910 winreg_printer_get_changeid_internal(mem_ctx
, session_info
, msg_ctx
,
3911 info2
->sharename
, &r
->change_id
);
3913 r
->last_error
= WERR_OK
;
3914 r
->status
= nt_printq_status(status
.status
);
3915 r
->enumerate_network_printers
= 0x0;
3916 r
->c_setprinter
= 0x0;
3917 r
->processor_architecture
= PROCESSOR_ARCHITECTURE_INTEL
;
3918 r
->processor_level
= 0x6; /* 6 ???*/
3927 /********************************************************************
3928 * construct_printer_info1
3929 * fill a spoolss_PrinterInfo1 struct
3930 ********************************************************************/
3932 static WERROR
construct_printer_info1(TALLOC_CTX
*mem_ctx
,
3933 const struct spoolss_PrinterInfo2
*info2
,
3935 const char *servername
,
3936 struct spoolss_PrinterInfo1
*r
,
3943 if (info2
->comment
== NULL
|| info2
->comment
[0] == '\0') {
3944 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
3946 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
); /* saved comment */
3948 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
3950 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->name
);
3951 if (!W_ERROR_IS_OK(result
)) {
3955 r
->description
= talloc_asprintf(mem_ctx
, "%s,%s,%s",
3959 W_ERROR_HAVE_NO_MEMORY(r
->description
);
3964 /********************************************************************
3965 * construct_printer_info2
3966 * fill a spoolss_PrinterInfo2 struct
3967 ********************************************************************/
3969 static WERROR
construct_printer_info2(TALLOC_CTX
*mem_ctx
,
3970 struct messaging_context
*msg_ctx
,
3971 const struct spoolss_PrinterInfo2
*info2
,
3972 const char *servername
,
3973 struct spoolss_PrinterInfo2
*r
,
3977 print_status_struct status
;
3980 count
= print_queue_length(msg_ctx
, snum
, &status
);
3983 r
->servername
= talloc_strdup(mem_ctx
, servername
);
3984 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
3986 r
->servername
= NULL
;
3989 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
3990 if (!W_ERROR_IS_OK(result
)) {
3994 r
->sharename
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
3995 W_ERROR_HAVE_NO_MEMORY(r
->sharename
);
3996 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
3997 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
3998 r
->drivername
= talloc_strdup(mem_ctx
, info2
->drivername
);
3999 W_ERROR_HAVE_NO_MEMORY(r
->drivername
);
4001 if (info2
->comment
[0] == '\0') {
4002 r
->comment
= talloc_strdup(mem_ctx
, lp_comment(snum
));
4004 r
->comment
= talloc_strdup(mem_ctx
, info2
->comment
);
4006 W_ERROR_HAVE_NO_MEMORY(r
->comment
);
4008 r
->location
= talloc_strdup(mem_ctx
, info2
->location
);
4009 if (info2
->location
[0] == '\0') {
4010 const char *loc
= NULL
;
4013 nt_status
= printer_list_get_printer(mem_ctx
,
4018 if (NT_STATUS_IS_OK(nt_status
)) {
4020 r
->location
= talloc_strdup(mem_ctx
, loc
);
4024 W_ERROR_HAVE_NO_MEMORY(r
->location
);
4026 r
->sepfile
= talloc_strdup(mem_ctx
, info2
->sepfile
);
4027 W_ERROR_HAVE_NO_MEMORY(r
->sepfile
);
4028 r
->printprocessor
= talloc_strdup(mem_ctx
, info2
->printprocessor
);
4029 W_ERROR_HAVE_NO_MEMORY(r
->printprocessor
);
4030 r
->datatype
= talloc_strdup(mem_ctx
, info2
->datatype
);
4031 W_ERROR_HAVE_NO_MEMORY(r
->datatype
);
4032 r
->parameters
= talloc_strdup(mem_ctx
, info2
->parameters
);
4033 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
4035 r
->attributes
= info2
->attributes
;
4037 r
->priority
= info2
->priority
;
4038 r
->defaultpriority
= info2
->defaultpriority
;
4039 r
->starttime
= info2
->starttime
;
4040 r
->untiltime
= info2
->untiltime
;
4041 r
->status
= nt_printq_status(status
.status
);
4043 r
->averageppm
= info2
->averageppm
;
4045 copy_devicemode(mem_ctx
, info2
->devmode
, &r
->devmode
);
4047 DEBUG(8,("Returning NULL Devicemode!\n"));
4050 compose_devicemode_devicename(r
->devmode
, r
->printername
);
4054 if (info2
->secdesc
!= NULL
) {
4055 /* don't use talloc_steal() here unless you do a deep steal of all
4056 the SEC_DESC members */
4058 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
4064 /********************************************************************
4065 * construct_printer_info3
4066 * fill a spoolss_PrinterInfo3 struct
4067 ********************************************************************/
4069 static WERROR
construct_printer_info3(TALLOC_CTX
*mem_ctx
,
4070 const struct spoolss_PrinterInfo2
*info2
,
4071 const char *servername
,
4072 struct spoolss_PrinterInfo3
*r
,
4075 /* These are the components of the SD we are returning. */
4077 if (info2
->secdesc
!= NULL
) {
4078 /* don't use talloc_steal() here unless you do a deep steal of all
4079 the SEC_DESC members */
4081 r
->secdesc
= dup_sec_desc(mem_ctx
, info2
->secdesc
);
4082 W_ERROR_HAVE_NO_MEMORY(r
->secdesc
);
4088 /********************************************************************
4089 * construct_printer_info4
4090 * fill a spoolss_PrinterInfo4 struct
4091 ********************************************************************/
4093 static WERROR
construct_printer_info4(TALLOC_CTX
*mem_ctx
,
4094 const struct spoolss_PrinterInfo2
*info2
,
4095 const char *servername
,
4096 struct spoolss_PrinterInfo4
*r
,
4101 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4102 if (!W_ERROR_IS_OK(result
)) {
4107 r
->servername
= talloc_strdup(mem_ctx
, servername
);
4108 W_ERROR_HAVE_NO_MEMORY(r
->servername
);
4110 r
->servername
= NULL
;
4113 r
->attributes
= info2
->attributes
;
4118 /********************************************************************
4119 * construct_printer_info5
4120 * fill a spoolss_PrinterInfo5 struct
4121 ********************************************************************/
4123 static WERROR
construct_printer_info5(TALLOC_CTX
*mem_ctx
,
4124 const struct spoolss_PrinterInfo2
*info2
,
4125 const char *servername
,
4126 struct spoolss_PrinterInfo5
*r
,
4131 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &r
->printername
);
4132 if (!W_ERROR_IS_OK(result
)) {
4136 r
->portname
= talloc_strdup(mem_ctx
, info2
->portname
);
4137 W_ERROR_HAVE_NO_MEMORY(r
->portname
);
4139 r
->attributes
= info2
->attributes
;
4141 /* these two are not used by NT+ according to MSDN */
4142 r
->device_not_selected_timeout
= 0x0; /* have seen 0x3a98 */
4143 r
->transmission_retry_timeout
= 0x0; /* have seen 0xafc8 */
4148 /********************************************************************
4149 * construct_printer_info_6
4150 * fill a spoolss_PrinterInfo6 struct
4151 ********************************************************************/
4153 static WERROR
construct_printer_info6(TALLOC_CTX
*mem_ctx
,
4154 struct messaging_context
*msg_ctx
,
4155 const struct spoolss_PrinterInfo2
*info2
,
4156 const char *servername
,
4157 struct spoolss_PrinterInfo6
*r
,
4160 print_status_struct status
;
4162 print_queue_length(msg_ctx
, snum
, &status
);
4164 r
->status
= nt_printq_status(status
.status
);
4169 /********************************************************************
4170 * construct_printer_info7
4171 * fill a spoolss_PrinterInfo7 struct
4172 ********************************************************************/
4174 static WERROR
construct_printer_info7(TALLOC_CTX
*mem_ctx
,
4175 struct messaging_context
*msg_ctx
,
4176 const char *servername
,
4177 struct spoolss_PrinterInfo7
*r
,
4180 const struct auth_session_info
*session_info
= get_session_info_system();
4183 if (is_printer_published(mem_ctx
, session_info
, msg_ctx
,
4185 lp_servicename(snum
), &guid
, NULL
)) {
4186 r
->guid
= talloc_strdup_upper(mem_ctx
, GUID_string2(mem_ctx
, &guid
));
4187 r
->action
= DSPRINT_PUBLISH
;
4189 r
->guid
= talloc_strdup(mem_ctx
, "");
4190 r
->action
= DSPRINT_UNPUBLISH
;
4192 W_ERROR_HAVE_NO_MEMORY(r
->guid
);
4197 /********************************************************************
4198 * construct_printer_info8
4199 * fill a spoolss_PrinterInfo8 struct
4200 ********************************************************************/
4202 static WERROR
construct_printer_info8(TALLOC_CTX
*mem_ctx
,
4203 const struct spoolss_PrinterInfo2
*info2
,
4204 const char *servername
,
4205 struct spoolss_DeviceModeInfo
*r
,
4209 const char *printername
;
4211 result
= create_printername(mem_ctx
, servername
, info2
->printername
, &printername
);
4212 if (!W_ERROR_IS_OK(result
)) {
4216 copy_devicemode(mem_ctx
, info2
->devmode
, &r
->devmode
);
4218 DEBUG(8,("Returning NULL Devicemode!\n"));
4221 compose_devicemode_devicename(r
->devmode
, printername
);
4227 /********************************************************************
4228 ********************************************************************/
4230 static bool snum_is_shared_printer(int snum
)
4232 return (lp_browseable(snum
) && lp_snum_ok(snum
) && lp_print_ok(snum
));
4235 /********************************************************************
4236 Spoolss_enumprinters.
4237 ********************************************************************/
4239 static WERROR
enum_all_printers_info_level(TALLOC_CTX
*mem_ctx
,
4240 const struct auth_session_info
*session_info
,
4241 struct messaging_context
*msg_ctx
,
4242 const char *servername
,
4245 union spoolss_PrinterInfo
**info_p
,
4249 int n_services
= lp_numservices();
4250 union spoolss_PrinterInfo
*info
= NULL
;
4252 WERROR result
= WERR_OK
;
4253 struct dcerpc_binding_handle
*b
= NULL
;
4254 TALLOC_CTX
*tmp_ctx
= NULL
;
4256 tmp_ctx
= talloc_new(mem_ctx
);
4264 for (snum
= 0; snum
< n_services
; snum
++) {
4266 const char *printer
;
4267 struct spoolss_PrinterInfo2
*info2
;
4269 if (!snum_is_shared_printer(snum
)) {
4273 printer
= lp_const_servicename(snum
);
4275 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4279 result
= winreg_printer_binding_handle(tmp_ctx
,
4283 if (!W_ERROR_IS_OK(result
)) {
4288 result
= winreg_create_printer(tmp_ctx
, b
,
4290 if (!W_ERROR_IS_OK(result
)) {
4294 info
= talloc_realloc(tmp_ctx
, info
,
4295 union spoolss_PrinterInfo
,
4298 result
= WERR_NOMEM
;
4302 result
= winreg_get_printer(tmp_ctx
, b
,
4304 if (!W_ERROR_IS_OK(result
)) {
4310 result
= construct_printer_info0(info
, session_info
,
4313 &info
[count
].info0
, snum
);
4316 result
= construct_printer_info1(info
, info2
, flags
,
4318 &info
[count
].info1
, snum
);
4321 result
= construct_printer_info2(info
, msg_ctx
, info2
,
4323 &info
[count
].info2
, snum
);
4326 result
= construct_printer_info4(info
, info2
,
4328 &info
[count
].info4
, snum
);
4331 result
= construct_printer_info5(info
, info2
,
4333 &info
[count
].info5
, snum
);
4337 result
= WERR_UNKNOWN_LEVEL
;
4341 if (!W_ERROR_IS_OK(result
)) {
4349 if (W_ERROR_IS_OK(result
)) {
4350 *info_p
= talloc_move(mem_ctx
, &info
);
4354 talloc_free(tmp_ctx
);
4359 /********************************************************************
4360 * handle enumeration of printers at level 0
4361 ********************************************************************/
4363 static WERROR
enumprinters_level0(TALLOC_CTX
*mem_ctx
,
4364 const struct auth_session_info
*session_info
,
4365 struct messaging_context
*msg_ctx
,
4367 const char *servername
,
4368 union spoolss_PrinterInfo
**info
,
4371 DEBUG(4,("enum_all_printers_info_0\n"));
4373 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4374 servername
, 0, flags
, info
, count
);
4378 /********************************************************************
4379 ********************************************************************/
4381 static WERROR
enum_all_printers_info_1(TALLOC_CTX
*mem_ctx
,
4382 const struct auth_session_info
*session_info
,
4383 struct messaging_context
*msg_ctx
,
4384 const char *servername
,
4386 union spoolss_PrinterInfo
**info
,
4389 DEBUG(4,("enum_all_printers_info_1\n"));
4391 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4392 servername
, 1, flags
, info
, count
);
4395 /********************************************************************
4396 enum_all_printers_info_1_local.
4397 *********************************************************************/
4399 static WERROR
enum_all_printers_info_1_local(TALLOC_CTX
*mem_ctx
,
4400 const struct auth_session_info
*session_info
,
4401 struct messaging_context
*msg_ctx
,
4402 const char *servername
,
4403 union spoolss_PrinterInfo
**info
,
4406 DEBUG(4,("enum_all_printers_info_1_local\n"));
4408 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4409 servername
, PRINTER_ENUM_ICON8
, info
, count
);
4412 /********************************************************************
4413 enum_all_printers_info_1_name.
4414 *********************************************************************/
4416 static WERROR
enum_all_printers_info_1_name(TALLOC_CTX
*mem_ctx
,
4417 const struct auth_session_info
*session_info
,
4418 struct messaging_context
*msg_ctx
,
4419 const char *servername
,
4420 union spoolss_PrinterInfo
**info
,
4423 const char *s
= servername
;
4425 DEBUG(4,("enum_all_printers_info_1_name\n"));
4427 if ((servername
[0] == '\\') && (servername
[1] == '\\')) {
4431 if (!is_myname_or_ipaddr(s
)) {
4432 return WERR_INVALID_NAME
;
4435 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4436 servername
, PRINTER_ENUM_ICON8
, info
, count
);
4439 /********************************************************************
4440 enum_all_printers_info_1_network.
4441 *********************************************************************/
4443 static WERROR
enum_all_printers_info_1_network(TALLOC_CTX
*mem_ctx
,
4444 const struct auth_session_info
*session_info
,
4445 struct messaging_context
*msg_ctx
,
4446 const char *servername
,
4447 union spoolss_PrinterInfo
**info
,
4450 const char *s
= servername
;
4452 DEBUG(4,("enum_all_printers_info_1_network\n"));
4454 /* If we respond to a enum_printers level 1 on our name with flags
4455 set to PRINTER_ENUM_REMOTE with a list of printers then these
4456 printers incorrectly appear in the APW browse list.
4457 Specifically the printers for the server appear at the workgroup
4458 level where all the other servers in the domain are
4459 listed. Windows responds to this call with a
4460 WERR_CAN_NOT_COMPLETE so we should do the same. */
4462 if (servername
[0] == '\\' && servername
[1] == '\\') {
4466 if (is_myname_or_ipaddr(s
)) {
4467 return WERR_CAN_NOT_COMPLETE
;
4470 return enum_all_printers_info_1(mem_ctx
, session_info
, msg_ctx
,
4471 servername
, PRINTER_ENUM_NAME
, info
, count
);
4474 /********************************************************************
4475 * api_spoolss_enumprinters
4477 * called from api_spoolss_enumprinters (see this to understand)
4478 ********************************************************************/
4480 static WERROR
enum_all_printers_info_2(TALLOC_CTX
*mem_ctx
,
4481 const struct auth_session_info
*session_info
,
4482 struct messaging_context
*msg_ctx
,
4483 const char *servername
,
4484 union spoolss_PrinterInfo
**info
,
4487 DEBUG(4,("enum_all_printers_info_2\n"));
4489 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4490 servername
, 2, 0, info
, count
);
4493 /********************************************************************
4494 * handle enumeration of printers at level 1
4495 ********************************************************************/
4497 static WERROR
enumprinters_level1(TALLOC_CTX
*mem_ctx
,
4498 const struct auth_session_info
*session_info
,
4499 struct messaging_context
*msg_ctx
,
4501 const char *servername
,
4502 union spoolss_PrinterInfo
**info
,
4505 /* Not all the flags are equals */
4507 if (flags
& PRINTER_ENUM_LOCAL
) {
4508 return enum_all_printers_info_1_local(mem_ctx
, session_info
,
4509 msg_ctx
, servername
, info
, count
);
4512 if (flags
& PRINTER_ENUM_NAME
) {
4513 return enum_all_printers_info_1_name(mem_ctx
, session_info
,
4514 msg_ctx
, servername
, info
,
4518 if (flags
& PRINTER_ENUM_NETWORK
) {
4519 return enum_all_printers_info_1_network(mem_ctx
, session_info
,
4520 msg_ctx
, servername
, info
,
4524 return WERR_OK
; /* NT4sp5 does that */
4527 /********************************************************************
4528 * handle enumeration of printers at level 2
4529 ********************************************************************/
4531 static WERROR
enumprinters_level2(TALLOC_CTX
*mem_ctx
,
4532 const struct auth_session_info
*session_info
,
4533 struct messaging_context
*msg_ctx
,
4535 const char *servername
,
4536 union spoolss_PrinterInfo
**info
,
4539 if (flags
& PRINTER_ENUM_LOCAL
) {
4541 return enum_all_printers_info_2(mem_ctx
, session_info
, msg_ctx
,
4546 if (flags
& PRINTER_ENUM_NAME
) {
4547 if (servername
&& !is_myname_or_ipaddr(canon_servername(servername
))) {
4548 return WERR_INVALID_NAME
;
4551 return enum_all_printers_info_2(mem_ctx
, session_info
, msg_ctx
,
4556 if (flags
& PRINTER_ENUM_REMOTE
) {
4557 return WERR_UNKNOWN_LEVEL
;
4563 /********************************************************************
4564 * handle enumeration of printers at level 4
4565 ********************************************************************/
4567 static WERROR
enumprinters_level4(TALLOC_CTX
*mem_ctx
,
4568 const struct auth_session_info
*session_info
,
4569 struct messaging_context
*msg_ctx
,
4571 const char *servername
,
4572 union spoolss_PrinterInfo
**info
,
4575 DEBUG(4,("enum_all_printers_info_4\n"));
4577 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4578 servername
, 4, flags
, info
, count
);
4582 /********************************************************************
4583 * handle enumeration of printers at level 5
4584 ********************************************************************/
4586 static WERROR
enumprinters_level5(TALLOC_CTX
*mem_ctx
,
4587 const struct auth_session_info
*session_info
,
4588 struct messaging_context
*msg_ctx
,
4590 const char *servername
,
4591 union spoolss_PrinterInfo
**info
,
4594 DEBUG(4,("enum_all_printers_info_5\n"));
4596 return enum_all_printers_info_level(mem_ctx
, session_info
, msg_ctx
,
4597 servername
, 5, flags
, info
, count
);
4600 /****************************************************************
4601 _spoolss_EnumPrinters
4602 ****************************************************************/
4604 WERROR
_spoolss_EnumPrinters(struct pipes_struct
*p
,
4605 struct spoolss_EnumPrinters
*r
)
4607 const struct auth_session_info
*session_info
= get_session_info_system();
4610 /* that's an [in out] buffer */
4612 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4613 return WERR_INVALID_PARAM
;
4616 DEBUG(4,("_spoolss_EnumPrinters\n"));
4620 *r
->out
.info
= NULL
;
4624 * flags==PRINTER_ENUM_NAME
4625 * if name=="" then enumerates all printers
4626 * if name!="" then enumerate the printer
4627 * flags==PRINTER_ENUM_REMOTE
4628 * name is NULL, enumerate printers
4629 * Level 2: name!="" enumerates printers, name can't be NULL
4630 * Level 3: doesn't exist
4631 * Level 4: does a local registry lookup
4632 * Level 5: same as Level 2
4635 if (r
->in
.server
&& r
->in
.server
[0] == '\0') {
4636 r
->in
.server
= NULL
;
4639 switch (r
->in
.level
) {
4641 result
= enumprinters_level0(p
->mem_ctx
, session_info
,
4642 p
->msg_ctx
, r
->in
.flags
,
4644 r
->out
.info
, r
->out
.count
);
4647 result
= enumprinters_level1(p
->mem_ctx
, session_info
,
4648 p
->msg_ctx
, r
->in
.flags
,
4650 r
->out
.info
, r
->out
.count
);
4653 result
= enumprinters_level2(p
->mem_ctx
, session_info
,
4654 p
->msg_ctx
, r
->in
.flags
,
4656 r
->out
.info
, r
->out
.count
);
4659 result
= enumprinters_level4(p
->mem_ctx
, session_info
,
4660 p
->msg_ctx
, r
->in
.flags
,
4662 r
->out
.info
, r
->out
.count
);
4665 result
= enumprinters_level5(p
->mem_ctx
, session_info
,
4666 p
->msg_ctx
, r
->in
.flags
,
4668 r
->out
.info
, r
->out
.count
);
4671 return WERR_UNKNOWN_LEVEL
;
4674 if (!W_ERROR_IS_OK(result
)) {
4678 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
4679 spoolss_EnumPrinters
,
4680 *r
->out
.info
, r
->in
.level
,
4682 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
4683 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
4685 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4688 /****************************************************************
4690 ****************************************************************/
4692 WERROR
_spoolss_GetPrinter(struct pipes_struct
*p
,
4693 struct spoolss_GetPrinter
*r
)
4695 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
4696 struct spoolss_PrinterInfo2
*info2
= NULL
;
4697 WERROR result
= WERR_OK
;
4700 /* that's an [in out] buffer */
4702 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
4703 return WERR_INVALID_PARAM
;
4708 if (Printer
== NULL
) {
4712 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
4716 result
= winreg_get_printer_internal(p
->mem_ctx
,
4717 get_session_info_system(),
4719 lp_const_servicename(snum
),
4721 if (!W_ERROR_IS_OK(result
)) {
4725 switch (r
->in
.level
) {
4727 result
= construct_printer_info0(p
->mem_ctx
,
4728 get_session_info_system(),
4731 Printer
->servername
,
4732 &r
->out
.info
->info0
,
4736 result
= construct_printer_info1(p
->mem_ctx
, info2
,
4738 Printer
->servername
,
4739 &r
->out
.info
->info1
, snum
);
4742 result
= construct_printer_info2(p
->mem_ctx
, p
->msg_ctx
, info2
,
4743 Printer
->servername
,
4744 &r
->out
.info
->info2
, snum
);
4747 result
= construct_printer_info3(p
->mem_ctx
, info2
,
4748 Printer
->servername
,
4749 &r
->out
.info
->info3
, snum
);
4752 result
= construct_printer_info4(p
->mem_ctx
, info2
,
4753 Printer
->servername
,
4754 &r
->out
.info
->info4
, snum
);
4757 result
= construct_printer_info5(p
->mem_ctx
, info2
,
4758 Printer
->servername
,
4759 &r
->out
.info
->info5
, snum
);
4762 result
= construct_printer_info6(p
->mem_ctx
, p
->msg_ctx
, info2
,
4763 Printer
->servername
,
4764 &r
->out
.info
->info6
, snum
);
4767 result
= construct_printer_info7(p
->mem_ctx
, p
->msg_ctx
,
4768 Printer
->servername
,
4769 &r
->out
.info
->info7
, snum
);
4772 result
= construct_printer_info8(p
->mem_ctx
, info2
,
4773 Printer
->servername
,
4774 &r
->out
.info
->info8
, snum
);
4777 result
= WERR_UNKNOWN_LEVEL
;
4783 if (!W_ERROR_IS_OK(result
)) {
4784 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4785 r
->in
.level
, win_errstr(result
)));
4786 TALLOC_FREE(r
->out
.info
);
4790 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo
,
4791 r
->out
.info
, r
->in
.level
);
4792 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
4794 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
4797 /********************************************************************
4798 ********************************************************************/
4800 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4802 if (in && strlen(in)) { \
4803 out = talloc_strdup(mem_ctx, in); \
4805 out = talloc_strdup(mem_ctx, ""); \
4807 W_ERROR_HAVE_NO_MEMORY(out); \
4810 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4812 if (in && strlen(in)) { \
4813 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4815 out = talloc_strdup(mem_ctx, ""); \
4817 W_ERROR_HAVE_NO_MEMORY(out); \
4820 static WERROR
string_array_from_driver_info(TALLOC_CTX
*mem_ctx
,
4821 const char **string_array
,
4822 const char ***presult
,
4823 const char *cservername
,
4827 int i
, num_strings
= 0;
4828 const char **array
= NULL
;
4830 if (string_array
== NULL
) {
4831 return WERR_INVALID_PARAMETER
;
4834 for (i
=0; string_array
[i
] && string_array
[i
][0] != '\0'; i
++) {
4835 const char *str
= NULL
;
4837 if (cservername
== NULL
|| arch
== NULL
) {
4838 FILL_DRIVER_STRING(mem_ctx
, string_array
[i
], str
);
4840 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
, arch
, version
, string_array
[i
], str
);
4843 if (!add_string_to_array(mem_ctx
, str
, &array
, &num_strings
)) {
4850 ADD_TO_ARRAY(mem_ctx
, const char *, NULL
,
4851 &array
, &num_strings
);
4861 /********************************************************************
4862 * fill a spoolss_DriverInfo1 struct
4863 ********************************************************************/
4865 static WERROR
fill_printer_driver_info1(TALLOC_CTX
*mem_ctx
,
4866 struct spoolss_DriverInfo1
*r
,
4867 const struct spoolss_DriverInfo8
*driver
,
4868 const char *servername
)
4870 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4871 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4876 /********************************************************************
4877 * fill a spoolss_DriverInfo2 struct
4878 ********************************************************************/
4880 static WERROR
fill_printer_driver_info2(TALLOC_CTX
*mem_ctx
,
4881 struct spoolss_DriverInfo2
*r
,
4882 const struct spoolss_DriverInfo8
*driver
,
4883 const char *servername
)
4886 const char *cservername
= canon_servername(servername
);
4888 r
->version
= driver
->version
;
4890 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4891 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4892 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4893 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4895 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4896 driver
->architecture
,
4898 driver
->driver_path
,
4901 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4902 driver
->architecture
,
4907 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4908 driver
->architecture
,
4910 driver
->config_file
,
4916 /********************************************************************
4917 * fill a spoolss_DriverInfo3 struct
4918 ********************************************************************/
4920 static WERROR
fill_printer_driver_info3(TALLOC_CTX
*mem_ctx
,
4921 struct spoolss_DriverInfo3
*r
,
4922 const struct spoolss_DriverInfo8
*driver
,
4923 const char *servername
)
4925 const char *cservername
= canon_servername(servername
);
4927 r
->version
= driver
->version
;
4929 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4930 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4931 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4932 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4934 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4935 driver
->architecture
,
4937 driver
->driver_path
,
4940 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4941 driver
->architecture
,
4946 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4947 driver
->architecture
,
4949 driver
->config_file
,
4952 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4953 driver
->architecture
,
4958 FILL_DRIVER_STRING(mem_ctx
,
4959 driver
->monitor_name
,
4962 FILL_DRIVER_STRING(mem_ctx
,
4963 driver
->default_datatype
,
4964 r
->default_datatype
);
4966 return string_array_from_driver_info(mem_ctx
,
4967 driver
->dependent_files
,
4968 &r
->dependent_files
,
4970 driver
->architecture
,
4974 /********************************************************************
4975 * fill a spoolss_DriverInfo4 struct
4976 ********************************************************************/
4978 static WERROR
fill_printer_driver_info4(TALLOC_CTX
*mem_ctx
,
4979 struct spoolss_DriverInfo4
*r
,
4980 const struct spoolss_DriverInfo8
*driver
,
4981 const char *servername
)
4983 const char *cservername
= canon_servername(servername
);
4986 r
->version
= driver
->version
;
4988 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
4989 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
4990 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
4991 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
4993 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
4994 driver
->architecture
,
4996 driver
->driver_path
,
4999 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5000 driver
->architecture
,
5005 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5006 driver
->architecture
,
5008 driver
->config_file
,
5011 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5012 driver
->architecture
,
5017 result
= string_array_from_driver_info(mem_ctx
,
5018 driver
->dependent_files
,
5019 &r
->dependent_files
,
5021 driver
->architecture
,
5023 if (!W_ERROR_IS_OK(result
)) {
5027 FILL_DRIVER_STRING(mem_ctx
,
5028 driver
->monitor_name
,
5031 FILL_DRIVER_STRING(mem_ctx
,
5032 driver
->default_datatype
,
5033 r
->default_datatype
);
5036 result
= string_array_from_driver_info(mem_ctx
,
5037 driver
->previous_names
,
5044 /********************************************************************
5045 * fill a spoolss_DriverInfo5 struct
5046 ********************************************************************/
5048 static WERROR
fill_printer_driver_info5(TALLOC_CTX
*mem_ctx
,
5049 struct spoolss_DriverInfo5
*r
,
5050 const struct spoolss_DriverInfo8
*driver
,
5051 const char *servername
)
5053 const char *cservername
= canon_servername(servername
);
5055 r
->version
= driver
->version
;
5057 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5058 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5059 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5060 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5062 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5063 driver
->architecture
,
5065 driver
->driver_path
,
5068 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5069 driver
->architecture
,
5074 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5075 driver
->architecture
,
5077 driver
->config_file
,
5080 r
->driver_attributes
= 0;
5081 r
->config_version
= 0;
5082 r
->driver_version
= 0;
5086 /********************************************************************
5087 * fill a spoolss_DriverInfo6 struct
5088 ********************************************************************/
5090 static WERROR
fill_printer_driver_info6(TALLOC_CTX
*mem_ctx
,
5091 struct spoolss_DriverInfo6
*r
,
5092 const struct spoolss_DriverInfo8
*driver
,
5093 const char *servername
)
5095 const char *cservername
= canon_servername(servername
);
5098 r
->version
= driver
->version
;
5100 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5101 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5102 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5103 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5105 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5106 driver
->architecture
,
5108 driver
->driver_path
,
5111 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5112 driver
->architecture
,
5117 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5118 driver
->architecture
,
5120 driver
->config_file
,
5123 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5124 driver
->architecture
,
5129 FILL_DRIVER_STRING(mem_ctx
,
5130 driver
->monitor_name
,
5133 FILL_DRIVER_STRING(mem_ctx
,
5134 driver
->default_datatype
,
5135 r
->default_datatype
);
5137 result
= string_array_from_driver_info(mem_ctx
,
5138 driver
->dependent_files
,
5139 &r
->dependent_files
,
5141 driver
->architecture
,
5143 if (!W_ERROR_IS_OK(result
)) {
5147 result
= string_array_from_driver_info(mem_ctx
,
5148 driver
->previous_names
,
5151 if (!W_ERROR_IS_OK(result
)) {
5155 r
->driver_date
= driver
->driver_date
;
5156 r
->driver_version
= driver
->driver_version
;
5158 FILL_DRIVER_STRING(mem_ctx
,
5159 driver
->manufacturer_name
,
5160 r
->manufacturer_name
);
5161 FILL_DRIVER_STRING(mem_ctx
,
5162 driver
->manufacturer_url
,
5163 r
->manufacturer_url
);
5164 FILL_DRIVER_STRING(mem_ctx
,
5165 driver
->hardware_id
,
5167 FILL_DRIVER_STRING(mem_ctx
,
5174 /********************************************************************
5175 * fill a spoolss_DriverInfo8 struct
5176 ********************************************************************/
5178 static WERROR
fill_printer_driver_info8(TALLOC_CTX
*mem_ctx
,
5179 struct spoolss_DriverInfo8
*r
,
5180 const struct spoolss_DriverInfo8
*driver
,
5181 const char *servername
)
5183 const char *cservername
= canon_servername(servername
);
5186 r
->version
= driver
->version
;
5188 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5189 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5190 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5191 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5193 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5194 driver
->architecture
,
5196 driver
->driver_path
,
5199 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5200 driver
->architecture
,
5205 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5206 driver
->architecture
,
5208 driver
->config_file
,
5211 FILL_DRIVER_UNC_STRING(mem_ctx
, cservername
,
5212 driver
->architecture
,
5217 FILL_DRIVER_STRING(mem_ctx
,
5218 driver
->monitor_name
,
5221 FILL_DRIVER_STRING(mem_ctx
,
5222 driver
->default_datatype
,
5223 r
->default_datatype
);
5225 result
= string_array_from_driver_info(mem_ctx
,
5226 driver
->dependent_files
,
5227 &r
->dependent_files
,
5229 driver
->architecture
,
5231 if (!W_ERROR_IS_OK(result
)) {
5235 result
= string_array_from_driver_info(mem_ctx
,
5236 driver
->previous_names
,
5239 if (!W_ERROR_IS_OK(result
)) {
5243 r
->driver_date
= driver
->driver_date
;
5244 r
->driver_version
= driver
->driver_version
;
5246 FILL_DRIVER_STRING(mem_ctx
,
5247 driver
->manufacturer_name
,
5248 r
->manufacturer_name
);
5249 FILL_DRIVER_STRING(mem_ctx
,
5250 driver
->manufacturer_url
,
5251 r
->manufacturer_url
);
5252 FILL_DRIVER_STRING(mem_ctx
,
5253 driver
->hardware_id
,
5255 FILL_DRIVER_STRING(mem_ctx
,
5259 FILL_DRIVER_STRING(mem_ctx
,
5260 driver
->print_processor
,
5261 r
->print_processor
);
5262 FILL_DRIVER_STRING(mem_ctx
,
5263 driver
->vendor_setup
,
5266 result
= string_array_from_driver_info(mem_ctx
,
5267 driver
->color_profiles
,
5270 if (!W_ERROR_IS_OK(result
)) {
5274 FILL_DRIVER_STRING(mem_ctx
,
5278 r
->printer_driver_attributes
= driver
->printer_driver_attributes
;
5280 result
= string_array_from_driver_info(mem_ctx
,
5281 driver
->core_driver_dependencies
,
5282 &r
->core_driver_dependencies
,
5284 if (!W_ERROR_IS_OK(result
)) {
5288 r
->min_inbox_driver_ver_date
= driver
->min_inbox_driver_ver_date
;
5289 r
->min_inbox_driver_ver_version
= driver
->min_inbox_driver_ver_version
;
5294 #if 0 /* disabled until marshalling issues are resolved - gd */
5295 /********************************************************************
5296 ********************************************************************/
5298 static WERROR
fill_spoolss_DriverFileInfo(TALLOC_CTX
*mem_ctx
,
5299 struct spoolss_DriverFileInfo
*r
,
5300 const char *cservername
,
5301 const char *file_name
,
5302 enum spoolss_DriverFileType file_type
,
5303 uint32_t file_version
)
5305 r
->file_name
= talloc_asprintf(mem_ctx
, "\\\\%s%s",
5306 cservername
, file_name
);
5307 W_ERROR_HAVE_NO_MEMORY(r
->file_name
);
5308 r
->file_type
= file_type
;
5309 r
->file_version
= file_version
;
5314 /********************************************************************
5315 ********************************************************************/
5317 static WERROR
spoolss_DriverFileInfo_from_driver(TALLOC_CTX
*mem_ctx
,
5318 const struct spoolss_DriverInfo8
*driver
,
5319 const char *cservername
,
5320 struct spoolss_DriverFileInfo
**info_p
,
5323 struct spoolss_DriverFileInfo
*info
= NULL
;
5331 if (strlen(driver
->driver_path
)) {
5332 info
= talloc_realloc(mem_ctx
, info
,
5333 struct spoolss_DriverFileInfo
,
5335 W_ERROR_HAVE_NO_MEMORY(info
);
5336 result
= fill_spoolss_DriverFileInfo(info
,
5339 driver
->driver_path
,
5340 SPOOLSS_DRIVER_FILE_TYPE_RENDERING
,
5342 W_ERROR_NOT_OK_RETURN(result
);
5346 if (strlen(driver
->config_file
)) {
5347 info
= talloc_realloc(mem_ctx
, info
,
5348 struct spoolss_DriverFileInfo
,
5350 W_ERROR_HAVE_NO_MEMORY(info
);
5351 result
= fill_spoolss_DriverFileInfo(info
,
5354 driver
->config_file
,
5355 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION
,
5357 W_ERROR_NOT_OK_RETURN(result
);
5361 if (strlen(driver
->data_file
)) {
5362 info
= talloc_realloc(mem_ctx
, info
,
5363 struct spoolss_DriverFileInfo
,
5365 W_ERROR_HAVE_NO_MEMORY(info
);
5366 result
= fill_spoolss_DriverFileInfo(info
,
5370 SPOOLSS_DRIVER_FILE_TYPE_DATA
,
5372 W_ERROR_NOT_OK_RETURN(result
);
5376 if (strlen(driver
->help_file
)) {
5377 info
= talloc_realloc(mem_ctx
, info
,
5378 struct spoolss_DriverFileInfo
,
5380 W_ERROR_HAVE_NO_MEMORY(info
);
5381 result
= fill_spoolss_DriverFileInfo(info
,
5385 SPOOLSS_DRIVER_FILE_TYPE_HELP
,
5387 W_ERROR_NOT_OK_RETURN(result
);
5391 for (i
=0; driver
->dependent_files
[i
] && driver
->dependent_files
[i
][0] != '\0'; i
++) {
5392 info
= talloc_realloc(mem_ctx
, info
,
5393 struct spoolss_DriverFileInfo
,
5395 W_ERROR_HAVE_NO_MEMORY(info
);
5396 result
= fill_spoolss_DriverFileInfo(info
,
5399 driver
->dependent_files
[i
],
5400 SPOOLSS_DRIVER_FILE_TYPE_OTHER
,
5402 W_ERROR_NOT_OK_RETURN(result
);
5412 /********************************************************************
5413 * fill a spoolss_DriverInfo101 struct
5414 ********************************************************************/
5416 static WERROR
fill_printer_driver_info101(TALLOC_CTX
*mem_ctx
,
5417 struct spoolss_DriverInfo101
*r
,
5418 const struct spoolss_DriverInfo8
*driver
,
5419 const char *servername
)
5421 const char *cservername
= canon_servername(servername
);
5424 r
->version
= driver
->version
;
5426 r
->driver_name
= talloc_strdup(mem_ctx
, driver
->driver_name
);
5427 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
5428 r
->architecture
= talloc_strdup(mem_ctx
, driver
->architecture
);
5429 W_ERROR_HAVE_NO_MEMORY(r
->architecture
);
5431 result
= spoolss_DriverFileInfo_from_driver(mem_ctx
, driver
,
5435 if (!W_ERROR_IS_OK(result
)) {
5439 FILL_DRIVER_STRING(mem_ctx
,
5440 driver
->monitor_name
,
5443 FILL_DRIVER_STRING(mem_ctx
,
5444 driver
->default_datatype
,
5445 r
->default_datatype
);
5447 result
= string_array_from_driver_info(mem_ctx
,
5448 driver
->previous_names
,
5451 if (!W_ERROR_IS_OK(result
)) {
5455 r
->driver_date
= driver
->driver_date
;
5456 r
->driver_version
= driver
->driver_version
;
5458 FILL_DRIVER_STRING(mem_ctx
,
5459 driver
->manufacturer_name
,
5460 r
->manufacturer_name
);
5461 FILL_DRIVER_STRING(mem_ctx
,
5462 driver
->manufacturer_url
,
5463 r
->manufacturer_url
);
5464 FILL_DRIVER_STRING(mem_ctx
,
5465 driver
->hardware_id
,
5467 FILL_DRIVER_STRING(mem_ctx
,
5474 /********************************************************************
5475 ********************************************************************/
5477 static WERROR
construct_printer_driver_info_level(TALLOC_CTX
*mem_ctx
,
5478 const struct auth_session_info
*session_info
,
5479 struct messaging_context
*msg_ctx
,
5481 union spoolss_DriverInfo
*r
,
5483 const char *servername
,
5484 const char *architecture
,
5487 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
5488 struct spoolss_DriverInfo8
*driver
;
5490 struct dcerpc_binding_handle
*b
;
5491 TALLOC_CTX
*tmp_ctx
= NULL
;
5494 return WERR_UNKNOWN_LEVEL
;
5497 tmp_ctx
= talloc_new(mem_ctx
);
5502 result
= winreg_printer_binding_handle(tmp_ctx
,
5506 if (!W_ERROR_IS_OK(result
)) {
5510 result
= winreg_get_printer(tmp_ctx
, b
,
5511 lp_const_servicename(snum
),
5514 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5515 win_errstr(result
)));
5517 if (!W_ERROR_IS_OK(result
)) {
5518 result
= WERR_INVALID_PRINTER_NAME
;
5522 result
= winreg_get_driver(tmp_ctx
, b
,
5524 pinfo2
->drivername
, version
, &driver
);
5526 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5527 win_errstr(result
)));
5529 if (!W_ERROR_IS_OK(result
)) {
5531 * Is this a W2k client ?
5535 result
= WERR_UNKNOWN_PRINTER_DRIVER
;
5539 /* Yes - try again with a WinNT driver. */
5541 result
= winreg_get_driver(tmp_ctx
, b
,
5545 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5546 win_errstr(result
)));
5547 if (!W_ERROR_IS_OK(result
)) {
5548 result
= WERR_UNKNOWN_PRINTER_DRIVER
;
5553 /* these are allocated on mem_ctx and not tmp_ctx because they are
5554 * the 'return value' and need to utlive this call */
5557 result
= fill_printer_driver_info1(mem_ctx
, &r
->info1
, driver
, servername
);
5560 result
= fill_printer_driver_info2(mem_ctx
, &r
->info2
, driver
, servername
);
5563 result
= fill_printer_driver_info3(mem_ctx
, &r
->info3
, driver
, servername
);
5566 result
= fill_printer_driver_info4(mem_ctx
, &r
->info4
, driver
, servername
);
5569 result
= fill_printer_driver_info5(mem_ctx
, &r
->info5
, driver
, servername
);
5572 result
= fill_printer_driver_info6(mem_ctx
, &r
->info6
, driver
, servername
);
5575 result
= fill_printer_driver_info8(mem_ctx
, &r
->info8
, driver
, servername
);
5577 #if 0 /* disabled until marshalling issues are resolved - gd */
5579 result
= fill_printer_driver_info101(mem_ctx
, &r
->info101
, driver
, servername
);
5583 result
= WERR_UNKNOWN_LEVEL
;
5588 talloc_free(tmp_ctx
);
5592 /****************************************************************
5593 _spoolss_GetPrinterDriver2
5594 ****************************************************************/
5596 WERROR
_spoolss_GetPrinterDriver2(struct pipes_struct
*p
,
5597 struct spoolss_GetPrinterDriver2
*r
)
5599 struct printer_handle
*printer
;
5604 /* that's an [in out] buffer */
5606 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
5607 return WERR_INVALID_PARAM
;
5610 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5612 if (!(printer
= find_printer_index_by_hnd(p
, r
->in
.handle
))) {
5613 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5614 return WERR_INVALID_PRINTER_NAME
;
5618 *r
->out
.server_major_version
= 0;
5619 *r
->out
.server_minor_version
= 0;
5621 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5625 result
= construct_printer_driver_info_level(p
->mem_ctx
,
5626 get_session_info_system(),
5628 r
->in
.level
, r
->out
.info
,
5629 snum
, printer
->servername
,
5631 r
->in
.client_major_version
);
5632 if (!W_ERROR_IS_OK(result
)) {
5633 TALLOC_FREE(r
->out
.info
);
5637 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverInfo
,
5638 r
->out
.info
, r
->in
.level
);
5639 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
5641 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
5645 /****************************************************************
5646 _spoolss_StartPagePrinter
5647 ****************************************************************/
5649 WERROR
_spoolss_StartPagePrinter(struct pipes_struct
*p
,
5650 struct spoolss_StartPagePrinter
*r
)
5652 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5655 DEBUG(3,("_spoolss_StartPagePrinter: "
5656 "Error in startpageprinter printer handle\n"));
5660 Printer
->page_started
= true;
5664 /****************************************************************
5665 _spoolss_EndPagePrinter
5666 ****************************************************************/
5668 WERROR
_spoolss_EndPagePrinter(struct pipes_struct
*p
,
5669 struct spoolss_EndPagePrinter
*r
)
5673 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5676 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5677 OUR_HANDLE(r
->in
.handle
)));
5681 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5684 Printer
->page_started
= false;
5685 print_job_endpage(p
->msg_ctx
, snum
, Printer
->jobid
);
5690 /****************************************************************
5691 _spoolss_StartDocPrinter
5692 ****************************************************************/
5694 WERROR
_spoolss_StartDocPrinter(struct pipes_struct
*p
,
5695 struct spoolss_StartDocPrinter
*r
)
5697 struct spoolss_DocumentInfo1
*info_1
;
5699 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5705 DEBUG(2,("_spoolss_StartDocPrinter: "
5706 "Invalid handle (%s:%u:%u)\n",
5707 OUR_HANDLE(r
->in
.handle
)));
5711 if (Printer
->jobid
) {
5712 DEBUG(2, ("_spoolss_StartDocPrinter: "
5713 "StartDocPrinter called twice! "
5714 "(existing jobid = %d)\n", Printer
->jobid
));
5715 return WERR_INVALID_HANDLE
;
5718 if (r
->in
.level
!= 1) {
5719 return WERR_UNKNOWN_LEVEL
;
5722 info_1
= r
->in
.info
.info1
;
5725 * a nice thing with NT is it doesn't listen to what you tell it.
5726 * when asked to send _only_ RAW datas, it tries to send datas
5729 * So I add checks like in NT Server ...
5732 if (info_1
->datatype
) {
5733 if (strcmp(info_1
->datatype
, "RAW") != 0) {
5735 return WERR_INVALID_DATATYPE
;
5739 /* get the share number of the printer */
5740 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5744 rc
= get_remote_hostname(p
->remote_address
,
5750 if (strequal(rhost
,"UNKNOWN")) {
5751 rhost
= tsocket_address_inet_addr_string(p
->remote_address
,
5753 if (rhost
== NULL
) {
5758 werr
= print_job_start(p
->session_info
,
5762 info_1
->document_name
,
5763 info_1
->output_file
,
5767 /* An error occured in print_job_start() so return an appropriate
5770 if (!W_ERROR_IS_OK(werr
)) {
5774 Printer
->document_started
= true;
5775 *r
->out
.job_id
= Printer
->jobid
;
5780 /****************************************************************
5781 _spoolss_EndDocPrinter
5782 ****************************************************************/
5784 WERROR
_spoolss_EndDocPrinter(struct pipes_struct
*p
,
5785 struct spoolss_EndDocPrinter
*r
)
5787 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5792 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5793 OUR_HANDLE(r
->in
.handle
)));
5797 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
5801 Printer
->document_started
= false;
5802 status
= print_job_end(p
->msg_ctx
, snum
, Printer
->jobid
, NORMAL_CLOSE
);
5803 if (!NT_STATUS_IS_OK(status
)) {
5804 DEBUG(2, ("_spoolss_EndDocPrinter: "
5805 "print_job_end failed [%s]\n",
5806 nt_errstr(status
)));
5810 return ntstatus_to_werror(status
);
5813 /****************************************************************
5814 _spoolss_WritePrinter
5815 ****************************************************************/
5817 WERROR
_spoolss_WritePrinter(struct pipes_struct
*p
,
5818 struct spoolss_WritePrinter
*r
)
5820 ssize_t buffer_written
;
5822 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5825 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5826 OUR_HANDLE(r
->in
.handle
)));
5827 *r
->out
.num_written
= r
->in
._data_size
;
5831 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5834 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5835 buffer_written
= print_job_write(server_event_context(),p
->msg_ctx
,
5836 snum
, Printer
->jobid
,
5837 (const char *)r
->in
.data
.data
,
5838 (size_t)r
->in
._data_size
);
5839 if (buffer_written
== (ssize_t
)-1) {
5840 *r
->out
.num_written
= 0;
5841 if (errno
== ENOSPC
)
5842 return WERR_NO_SPOOL_SPACE
;
5844 return WERR_ACCESS_DENIED
;
5847 *r
->out
.num_written
= r
->in
._data_size
;
5852 /********************************************************************
5853 * api_spoolss_getprinter
5854 * called from the spoolss dispatcher
5856 ********************************************************************/
5858 static WERROR
control_printer(struct policy_handle
*handle
, uint32_t command
,
5859 struct pipes_struct
*p
)
5861 const struct auth_session_info
*session_info
= p
->session_info
;
5863 WERROR errcode
= WERR_BADFUNC
;
5864 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
5867 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5868 OUR_HANDLE(handle
)));
5872 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
5876 case SPOOLSS_PRINTER_CONTROL_PAUSE
:
5877 errcode
= print_queue_pause(session_info
, p
->msg_ctx
, snum
);
5879 case SPOOLSS_PRINTER_CONTROL_RESUME
:
5880 case SPOOLSS_PRINTER_CONTROL_UNPAUSE
:
5881 errcode
= print_queue_resume(session_info
, p
->msg_ctx
, snum
);
5883 case SPOOLSS_PRINTER_CONTROL_PURGE
:
5884 errcode
= print_queue_purge(session_info
, p
->msg_ctx
, snum
);
5887 return WERR_UNKNOWN_LEVEL
;
5894 /****************************************************************
5895 _spoolss_AbortPrinter
5896 * From MSDN: "Deletes printer's spool file if printer is configured
5898 ****************************************************************/
5900 WERROR
_spoolss_AbortPrinter(struct pipes_struct
*p
,
5901 struct spoolss_AbortPrinter
*r
)
5903 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
5905 WERROR errcode
= WERR_OK
;
5908 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5909 OUR_HANDLE(r
->in
.handle
)));
5913 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
5916 if (!Printer
->document_started
) {
5917 return WERR_SPL_NO_STARTDOC
;
5920 errcode
= print_job_delete(p
->session_info
,
5928 /********************************************************************
5929 * called by spoolss_api_setprinter
5930 * when updating a printer description
5931 ********************************************************************/
5933 static WERROR
update_printer_sec(struct policy_handle
*handle
,
5934 struct pipes_struct
*p
,
5935 struct sec_desc_buf
*secdesc_ctr
)
5937 struct spoolss_security_descriptor
*new_secdesc
= NULL
;
5938 struct spoolss_security_descriptor
*old_secdesc
= NULL
;
5939 const char *printer
;
5942 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
5943 struct dcerpc_binding_handle
*b
;
5944 TALLOC_CTX
*tmp_ctx
= NULL
;
5946 if (!Printer
|| !get_printer_snum(p
, handle
, &snum
, NULL
)) {
5947 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5948 OUR_HANDLE(handle
)));
5950 result
= WERR_BADFID
;
5954 if (secdesc_ctr
== NULL
) {
5955 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5956 result
= WERR_INVALID_PARAM
;
5959 printer
= lp_const_servicename(snum
);
5961 /* Check the user has permissions to change the security
5962 descriptor. By experimentation with two NT machines, the user
5963 requires Full Access to the printer to change security
5966 if ( Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
5967 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5968 result
= WERR_ACCESS_DENIED
;
5972 tmp_ctx
= talloc_new(p
->mem_ctx
);
5977 result
= winreg_printer_binding_handle(tmp_ctx
,
5978 get_session_info_system(),
5981 if (!W_ERROR_IS_OK(result
)) {
5985 /* NT seems to like setting the security descriptor even though
5986 nothing may have actually changed. */
5987 result
= winreg_get_printer_secdesc(tmp_ctx
, b
,
5990 if (!W_ERROR_IS_OK(result
)) {
5991 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5992 result
= WERR_BADFID
;
5996 if (DEBUGLEVEL
>= 10) {
5997 struct security_acl
*the_acl
;
6000 the_acl
= old_secdesc
->dacl
;
6001 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6002 printer
, the_acl
->num_aces
));
6004 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6005 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6006 &the_acl
->aces
[i
].trustee
),
6007 the_acl
->aces
[i
].access_mask
));
6010 the_acl
= secdesc_ctr
->sd
->dacl
;
6013 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6014 printer
, the_acl
->num_aces
));
6016 for (i
= 0; i
< the_acl
->num_aces
; i
++) {
6017 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6018 &the_acl
->aces
[i
].trustee
),
6019 the_acl
->aces
[i
].access_mask
));
6022 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6026 new_secdesc
= sec_desc_merge(tmp_ctx
, secdesc_ctr
->sd
, old_secdesc
);
6027 if (new_secdesc
== NULL
) {
6028 result
= WERR_NOMEM
;
6032 if (security_descriptor_equal(new_secdesc
, old_secdesc
)) {
6037 result
= winreg_set_printer_secdesc(tmp_ctx
, b
,
6042 talloc_free(tmp_ctx
);
6046 /********************************************************************
6047 Canonicalize printer info from a client
6048 ********************************************************************/
6050 static bool check_printer_ok(TALLOC_CTX
*mem_ctx
,
6051 struct spoolss_SetPrinterInfo2
*info2
,
6054 fstring printername
;
6057 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6058 "portname=%s drivername=%s comment=%s location=%s\n",
6059 info2
->servername
, info2
->printername
, info2
->sharename
,
6060 info2
->portname
, info2
->drivername
, info2
->comment
,
6063 /* we force some elements to "correct" values */
6064 info2
->servername
= talloc_asprintf(mem_ctx
, "\\\\%s", lp_netbios_name());
6065 if (info2
->servername
== NULL
) {
6068 info2
->sharename
= talloc_strdup(mem_ctx
, lp_const_servicename(snum
));
6069 if (info2
->sharename
== NULL
) {
6073 /* check to see if we allow printername != sharename */
6074 if (lp_force_printername(snum
)) {
6075 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6076 lp_netbios_name(), info2
->sharename
);
6078 /* make sure printername is in \\server\printername format */
6079 fstrcpy(printername
, info2
->printername
);
6081 if ( printername
[0] == '\\' && printername
[1] == '\\' ) {
6082 if ( (p
= strchr_m( &printername
[2], '\\' )) != NULL
)
6086 info2
->printername
= talloc_asprintf(mem_ctx
, "\\\\%s\\%s",
6087 lp_netbios_name(), p
);
6089 if (info2
->printername
== NULL
) {
6093 info2
->attributes
|= PRINTER_ATTRIBUTE_SAMBA
;
6094 info2
->attributes
&= ~PRINTER_ATTRIBUTE_NOT_SAMBA
;
6099 /****************************************************************************
6100 ****************************************************************************/
6102 static WERROR
add_port_hook(TALLOC_CTX
*ctx
, struct security_token
*token
, const char *portname
, const char *uri
)
6104 char *cmd
= lp_addport_cmd();
6105 char *command
= NULL
;
6107 bool is_print_op
= false;
6110 return WERR_ACCESS_DENIED
;
6113 command
= talloc_asprintf(ctx
,
6114 "%s \"%s\" \"%s\"", cmd
, portname
, uri
);
6120 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
6122 DEBUG(10,("Running [%s]\n", command
));
6124 /********* BEGIN SePrintOperatorPrivilege **********/
6129 ret
= smbrun(command
, NULL
);
6134 /********* END SePrintOperatorPrivilege **********/
6136 DEBUGADD(10,("returned [%d]\n", ret
));
6138 TALLOC_FREE(command
);
6141 return WERR_ACCESS_DENIED
;
6147 /****************************************************************************
6148 ****************************************************************************/
6150 static bool spoolss_conn_snum_used(struct smbd_server_connection
*sconn
,
6154 * As we do not know if we are embedded in the file server process
6155 * or not, we have to pretend that all shares are in use.
6160 static bool add_printer_hook(TALLOC_CTX
*ctx
, struct security_token
*token
,
6161 struct spoolss_SetPrinterInfo2
*info2
,
6162 const char *remote_machine
,
6163 struct messaging_context
*msg_ctx
)
6165 char *cmd
= lp_addprinter_cmd();
6167 char *command
= NULL
;
6171 bool is_print_op
= false;
6173 if (!remote_machine
) {
6177 command
= talloc_asprintf(ctx
,
6178 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6179 cmd
, info2
->printername
, info2
->sharename
,
6180 info2
->portname
, info2
->drivername
,
6181 info2
->location
, info2
->comment
, remote_machine
);
6187 is_print_op
= security_token_has_privilege(token
, SEC_PRIV_PRINT_OPERATOR
);
6189 DEBUG(10,("Running [%s]\n", command
));
6191 /********* BEGIN SePrintOperatorPrivilege **********/
6196 if ( (ret
= smbrun(command
, &fd
)) == 0 ) {
6197 /* Tell everyone we updated smb.conf. */
6198 message_send_all(msg_ctx
, MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
6204 /********* END SePrintOperatorPrivilege **********/
6206 DEBUGADD(10,("returned [%d]\n", ret
));
6208 TALLOC_FREE(command
);
6216 /* reload our services immediately */
6218 reload_services(NULL
, spoolss_conn_snum_used
, false);
6222 /* Get lines and convert them back to dos-codepage */
6223 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
6224 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
6227 /* Set the portname to what the script says the portname should be. */
6228 /* but don't require anything to be return from the script exit a good error code */
6231 /* Set the portname to what the script says the portname should be. */
6232 info2
->portname
= talloc_strdup(ctx
, qlines
[0]);
6233 DEBUGADD(6,("Line[0] = [%s]\n", qlines
[0]));
6236 TALLOC_FREE(qlines
);
6240 static WERROR
update_dsspooler(TALLOC_CTX
*mem_ctx
,
6241 const struct auth_session_info
*session_info
,
6242 struct messaging_context
*msg_ctx
,
6244 struct spoolss_SetPrinterInfo2
*printer
,
6245 struct spoolss_PrinterInfo2
*old_printer
)
6247 bool force_update
= (old_printer
== NULL
);
6248 const char *dnsdomname
;
6249 const char *longname
;
6250 const char *uncname
;
6251 const char *spooling
;
6253 WERROR result
= WERR_OK
;
6254 struct dcerpc_binding_handle
*b
;
6255 TALLOC_CTX
*tmp_ctx
;
6257 tmp_ctx
= talloc_new(mem_ctx
);
6262 result
= winreg_printer_binding_handle(tmp_ctx
,
6266 if (!W_ERROR_IS_OK(result
)) {
6270 if (force_update
|| !strequal(printer
->drivername
, old_printer
->drivername
)) {
6271 push_reg_sz(tmp_ctx
, &buffer
, printer
->drivername
);
6272 winreg_set_printer_dataex(tmp_ctx
, b
,
6274 SPOOL_DSSPOOLER_KEY
,
6275 SPOOL_REG_DRIVERNAME
,
6280 if (!force_update
) {
6281 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6282 printer
->drivername
));
6284 notify_printer_driver(server_event_context(), msg_ctx
,
6285 snum
, printer
->drivername
?
6286 printer
->drivername
: "");
6290 if (force_update
|| !strequal(printer
->comment
, old_printer
->comment
)) {
6291 push_reg_sz(tmp_ctx
, &buffer
, printer
->comment
);
6292 winreg_set_printer_dataex(tmp_ctx
, b
,
6294 SPOOL_DSSPOOLER_KEY
,
6295 SPOOL_REG_DESCRIPTION
,
6300 if (!force_update
) {
6301 notify_printer_comment(server_event_context(), msg_ctx
,
6302 snum
, printer
->comment
?
6303 printer
->comment
: "");
6307 if (force_update
|| !strequal(printer
->sharename
, old_printer
->sharename
)) {
6308 push_reg_sz(tmp_ctx
, &buffer
, printer
->sharename
);
6309 winreg_set_printer_dataex(tmp_ctx
, b
,
6311 SPOOL_DSSPOOLER_KEY
,
6312 SPOOL_REG_PRINTSHARENAME
,
6317 if (!force_update
) {
6318 notify_printer_sharename(server_event_context(),
6320 snum
, printer
->sharename
?
6321 printer
->sharename
: "");
6325 if (force_update
|| !strequal(printer
->printername
, old_printer
->printername
)) {
6328 p
= strrchr(printer
->printername
, '\\' );
6332 p
= printer
->printername
;
6335 push_reg_sz(tmp_ctx
, &buffer
, p
);
6336 winreg_set_printer_dataex(tmp_ctx
, b
,
6338 SPOOL_DSSPOOLER_KEY
,
6339 SPOOL_REG_PRINTERNAME
,
6344 if (!force_update
) {
6345 notify_printer_printername(server_event_context(),
6346 msg_ctx
, snum
, p
? p
: "");
6350 if (force_update
|| !strequal(printer
->portname
, old_printer
->portname
)) {
6351 push_reg_sz(tmp_ctx
, &buffer
, printer
->portname
);
6352 winreg_set_printer_dataex(tmp_ctx
, b
,
6354 SPOOL_DSSPOOLER_KEY
,
6360 if (!force_update
) {
6361 notify_printer_port(server_event_context(),
6362 msg_ctx
, snum
, printer
->portname
?
6363 printer
->portname
: "");
6367 if (force_update
|| !strequal(printer
->location
, old_printer
->location
)) {
6368 push_reg_sz(tmp_ctx
, &buffer
, printer
->location
);
6369 winreg_set_printer_dataex(tmp_ctx
, b
,
6371 SPOOL_DSSPOOLER_KEY
,
6377 if (!force_update
) {
6378 notify_printer_location(server_event_context(),
6381 printer
->location
: "");
6385 if (force_update
|| !strequal(printer
->sepfile
, old_printer
->sepfile
)) {
6386 push_reg_sz(tmp_ctx
, &buffer
, printer
->sepfile
);
6387 winreg_set_printer_dataex(tmp_ctx
, b
,
6389 SPOOL_DSSPOOLER_KEY
,
6390 SPOOL_REG_PRINTSEPARATORFILE
,
6395 if (!force_update
) {
6396 notify_printer_sepfile(server_event_context(),
6399 printer
->sepfile
: "");
6403 if (force_update
|| printer
->starttime
!= old_printer
->starttime
) {
6404 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6405 SIVAL(buffer
.data
, 0, printer
->starttime
);
6406 winreg_set_printer_dataex(tmp_ctx
, b
,
6408 SPOOL_DSSPOOLER_KEY
,
6409 SPOOL_REG_PRINTSTARTTIME
,
6415 if (force_update
|| printer
->untiltime
!= old_printer
->untiltime
) {
6416 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6417 SIVAL(buffer
.data
, 0, printer
->untiltime
);
6418 winreg_set_printer_dataex(tmp_ctx
, b
,
6420 SPOOL_DSSPOOLER_KEY
,
6421 SPOOL_REG_PRINTENDTIME
,
6427 if (force_update
|| printer
->priority
!= old_printer
->priority
) {
6428 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6429 SIVAL(buffer
.data
, 0, printer
->priority
);
6430 winreg_set_printer_dataex(tmp_ctx
, b
,
6432 SPOOL_DSSPOOLER_KEY
,
6439 if (force_update
|| printer
->attributes
!= old_printer
->attributes
) {
6440 buffer
= data_blob_talloc(tmp_ctx
, NULL
, 4);
6441 SIVAL(buffer
.data
, 0, (printer
->attributes
&
6442 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS
));
6443 winreg_set_printer_dataex(tmp_ctx
, b
,
6445 SPOOL_DSSPOOLER_KEY
,
6446 SPOOL_REG_PRINTKEEPPRINTEDJOBS
,
6451 switch (printer
->attributes
& 0x3) {
6453 spooling
= SPOOL_REGVAL_PRINTWHILESPOOLING
;
6456 spooling
= SPOOL_REGVAL_PRINTAFTERSPOOLED
;
6459 spooling
= SPOOL_REGVAL_PRINTDIRECT
;
6462 spooling
= "unknown";
6464 push_reg_sz(tmp_ctx
, &buffer
, spooling
);
6465 winreg_set_printer_dataex(tmp_ctx
, b
,
6467 SPOOL_DSSPOOLER_KEY
,
6468 SPOOL_REG_PRINTSPOOLING
,
6474 push_reg_sz(tmp_ctx
, &buffer
, lp_netbios_name());
6475 winreg_set_printer_dataex(tmp_ctx
, b
,
6477 SPOOL_DSSPOOLER_KEY
,
6478 SPOOL_REG_SHORTSERVERNAME
,
6483 dnsdomname
= get_mydnsfullname();
6484 if (dnsdomname
!= NULL
&& dnsdomname
[0] != '\0') {
6485 longname
= talloc_strdup(tmp_ctx
, dnsdomname
);
6487 longname
= talloc_strdup(tmp_ctx
, lp_netbios_name());
6489 if (longname
== NULL
) {
6490 result
= WERR_NOMEM
;
6494 push_reg_sz(tmp_ctx
, &buffer
, longname
);
6495 winreg_set_printer_dataex(tmp_ctx
, b
,
6497 SPOOL_DSSPOOLER_KEY
,
6498 SPOOL_REG_SERVERNAME
,
6503 uncname
= talloc_asprintf(tmp_ctx
, "\\\\%s\\%s",
6504 lp_netbios_name(), printer
->sharename
);
6505 push_reg_sz(tmp_ctx
, &buffer
, uncname
);
6506 winreg_set_printer_dataex(tmp_ctx
, b
,
6508 SPOOL_DSSPOOLER_KEY
,
6515 talloc_free(tmp_ctx
);
6519 /********************************************************************
6520 * Called by spoolss_api_setprinter
6521 * when updating a printer description.
6522 ********************************************************************/
6524 static WERROR
update_printer(struct pipes_struct
*p
,
6525 struct policy_handle
*handle
,
6526 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
6527 struct spoolss_DeviceMode
*devmode
)
6529 uint32_t printer_mask
= SPOOLSS_PRINTER_INFO_ALL
;
6530 struct spoolss_SetPrinterInfo2
*printer
= info_ctr
->info
.info2
;
6531 struct spoolss_PrinterInfo2
*old_printer
;
6532 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6534 WERROR result
= WERR_OK
;
6535 TALLOC_CTX
*tmp_ctx
;
6536 struct dcerpc_binding_handle
*b
;
6538 DEBUG(8,("update_printer\n"));
6540 tmp_ctx
= talloc_new(p
->mem_ctx
);
6541 if (tmp_ctx
== NULL
) {
6546 result
= WERR_BADFID
;
6550 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6551 result
= WERR_BADFID
;
6555 result
= winreg_printer_binding_handle(tmp_ctx
,
6556 get_session_info_system(),
6559 if (!W_ERROR_IS_OK(result
)) {
6563 result
= winreg_get_printer(tmp_ctx
, b
,
6564 lp_const_servicename(snum
),
6566 if (!W_ERROR_IS_OK(result
)) {
6567 result
= WERR_BADFID
;
6571 /* Do sanity check on the requested changes for Samba */
6572 if (!check_printer_ok(tmp_ctx
, printer
, snum
)) {
6573 result
= WERR_INVALID_PARAM
;
6577 /* FIXME!!! If the driver has changed we really should verify that
6578 it is installed before doing much else --jerry */
6580 /* Check calling user has permission to update printer description */
6581 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6582 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6583 result
= WERR_ACCESS_DENIED
;
6587 /* Call addprinter hook */
6588 /* Check changes to see if this is really needed */
6590 if (*lp_addprinter_cmd() &&
6591 (!strequal(printer
->drivername
, old_printer
->drivername
) ||
6592 !strequal(printer
->comment
, old_printer
->comment
) ||
6593 !strequal(printer
->portname
, old_printer
->portname
) ||
6594 !strequal(printer
->location
, old_printer
->location
)) )
6598 raddr
= tsocket_address_inet_addr_string(p
->remote_address
,
6600 if (raddr
== NULL
) {
6604 /* add_printer_hook() will call reload_services() */
6605 if (!add_printer_hook(tmp_ctx
, p
->session_info
->security_token
,
6608 result
= WERR_ACCESS_DENIED
;
6613 update_dsspooler(tmp_ctx
,
6614 get_session_info_system(),
6620 printer_mask
&= ~SPOOLSS_PRINTER_INFO_SECDESC
;
6622 if (devmode
== NULL
) {
6623 printer_mask
&= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
6625 result
= winreg_update_printer(tmp_ctx
, b
,
6633 talloc_free(tmp_ctx
);
6638 /****************************************************************************
6639 ****************************************************************************/
6640 static WERROR
publish_or_unpublish_printer(struct pipes_struct
*p
,
6641 struct policy_handle
*handle
,
6642 struct spoolss_SetPrinterInfo7
*info7
)
6645 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
6648 struct printer_handle
*Printer
;
6650 if ( lp_security() != SEC_ADS
) {
6651 return WERR_UNKNOWN_LEVEL
;
6654 Printer
= find_printer_index_by_hnd(p
, handle
);
6656 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7
->action
));
6661 if (!get_printer_snum(p
, handle
, &snum
, NULL
))
6664 result
= winreg_get_printer_internal(p
->mem_ctx
,
6665 get_session_info_system(),
6667 lp_servicename(snum
),
6669 if (!W_ERROR_IS_OK(result
)) {
6673 nt_printer_publish(pinfo2
,
6674 get_session_info_system(),
6679 TALLOC_FREE(pinfo2
);
6682 return WERR_UNKNOWN_LEVEL
;
6686 /********************************************************************
6687 ********************************************************************/
6689 static WERROR
update_printer_devmode(struct pipes_struct
*p
,
6690 struct policy_handle
*handle
,
6691 struct spoolss_DeviceMode
*devmode
)
6694 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, handle
);
6695 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_DEVMODE
;
6697 DEBUG(8,("update_printer_devmode\n"));
6703 if (!get_printer_snum(p
, handle
, &snum
, NULL
)) {
6707 /* Check calling user has permission to update printer description */
6708 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
6709 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6710 return WERR_ACCESS_DENIED
;
6713 return winreg_update_printer_internal(p
->mem_ctx
,
6714 get_session_info_system(),
6716 lp_const_servicename(snum
),
6724 /****************************************************************
6726 ****************************************************************/
6728 WERROR
_spoolss_SetPrinter(struct pipes_struct
*p
,
6729 struct spoolss_SetPrinter
*r
)
6733 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6736 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6737 OUR_HANDLE(r
->in
.handle
)));
6741 /* check the level */
6742 switch (r
->in
.info_ctr
->level
) {
6744 return control_printer(r
->in
.handle
, r
->in
.command
, p
);
6746 result
= update_printer(p
, r
->in
.handle
,
6748 r
->in
.devmode_ctr
->devmode
);
6749 if (!W_ERROR_IS_OK(result
))
6751 if (r
->in
.secdesc_ctr
->sd
)
6752 result
= update_printer_sec(r
->in
.handle
, p
,
6756 return update_printer_sec(r
->in
.handle
, p
,
6759 return publish_or_unpublish_printer(p
, r
->in
.handle
,
6760 r
->in
.info_ctr
->info
.info7
);
6762 return update_printer_devmode(p
, r
->in
.handle
,
6763 r
->in
.devmode_ctr
->devmode
);
6765 return WERR_UNKNOWN_LEVEL
;
6769 /****************************************************************
6770 _spoolss_FindClosePrinterNotify
6771 ****************************************************************/
6773 WERROR
_spoolss_FindClosePrinterNotify(struct pipes_struct
*p
,
6774 struct spoolss_FindClosePrinterNotify
*r
)
6776 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
6779 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6780 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r
->in
.handle
)));
6784 if (Printer
->notify
.cli_chan
!= NULL
&&
6785 Printer
->notify
.cli_chan
->active_connections
> 0) {
6788 if (Printer
->printer_type
== SPLHND_PRINTER
) {
6789 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
6794 srv_spoolss_replycloseprinter(snum
, Printer
);
6797 Printer
->notify
.flags
=0;
6798 Printer
->notify
.options
=0;
6799 Printer
->notify
.localmachine
[0]='\0';
6800 Printer
->notify
.printerlocal
=0;
6801 TALLOC_FREE(Printer
->notify
.option
);
6806 /****************************************************************
6808 ****************************************************************/
6810 WERROR
_spoolss_AddJob(struct pipes_struct
*p
,
6811 struct spoolss_AddJob
*r
)
6813 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
6814 return WERR_INVALID_PARAM
;
6817 /* this is what a NT server returns for AddJob. AddJob must fail on
6818 * non-local printers */
6820 if (r
->in
.level
!= 1) {
6821 return WERR_UNKNOWN_LEVEL
;
6824 return WERR_INVALID_PARAM
;
6827 /****************************************************************************
6829 ****************************************************************************/
6831 static WERROR
fill_job_info1(TALLOC_CTX
*mem_ctx
,
6832 struct spoolss_JobInfo1
*r
,
6833 const print_queue_struct
*queue
,
6834 int position
, int snum
,
6835 struct spoolss_PrinterInfo2
*pinfo2
)
6839 t
= gmtime(&queue
->time
);
6841 r
->job_id
= queue
->job
;
6843 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6844 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6845 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
6846 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6847 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6848 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6849 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6850 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6851 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6852 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6853 r
->text_status
= talloc_strdup(mem_ctx
, "");
6854 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6856 r
->status
= nt_printj_status(queue
->status
);
6857 r
->priority
= queue
->priority
;
6858 r
->position
= position
;
6859 r
->total_pages
= queue
->page_count
;
6860 r
->pages_printed
= 0; /* ??? */
6862 init_systemtime(&r
->submitted
, t
);
6867 /****************************************************************************
6869 ****************************************************************************/
6871 static WERROR
fill_job_info2(TALLOC_CTX
*mem_ctx
,
6872 struct spoolss_JobInfo2
*r
,
6873 const print_queue_struct
*queue
,
6874 int position
, int snum
,
6875 struct spoolss_PrinterInfo2
*pinfo2
,
6876 struct spoolss_DeviceMode
*devmode
)
6880 t
= gmtime(&queue
->time
);
6882 r
->job_id
= queue
->job
;
6884 r
->printer_name
= talloc_strdup(mem_ctx
, lp_servicename(snum
));
6885 W_ERROR_HAVE_NO_MEMORY(r
->printer_name
);
6886 r
->server_name
= talloc_strdup(mem_ctx
, pinfo2
->servername
);
6887 W_ERROR_HAVE_NO_MEMORY(r
->server_name
);
6888 r
->user_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6889 W_ERROR_HAVE_NO_MEMORY(r
->user_name
);
6890 r
->document_name
= talloc_strdup(mem_ctx
, queue
->fs_file
);
6891 W_ERROR_HAVE_NO_MEMORY(r
->document_name
);
6892 r
->notify_name
= talloc_strdup(mem_ctx
, queue
->fs_user
);
6893 W_ERROR_HAVE_NO_MEMORY(r
->notify_name
);
6894 r
->data_type
= talloc_strdup(mem_ctx
, "RAW");
6895 W_ERROR_HAVE_NO_MEMORY(r
->data_type
);
6896 r
->print_processor
= talloc_strdup(mem_ctx
, "winprint");
6897 W_ERROR_HAVE_NO_MEMORY(r
->print_processor
);
6898 r
->parameters
= talloc_strdup(mem_ctx
, "");
6899 W_ERROR_HAVE_NO_MEMORY(r
->parameters
);
6900 r
->driver_name
= talloc_strdup(mem_ctx
, pinfo2
->drivername
);
6901 W_ERROR_HAVE_NO_MEMORY(r
->driver_name
);
6903 r
->devmode
= devmode
;
6905 r
->text_status
= talloc_strdup(mem_ctx
, "");
6906 W_ERROR_HAVE_NO_MEMORY(r
->text_status
);
6910 r
->status
= nt_printj_status(queue
->status
);
6911 r
->priority
= queue
->priority
;
6912 r
->position
= position
;
6915 r
->total_pages
= queue
->page_count
;
6916 r
->size
= queue
->size
;
6917 init_systemtime(&r
->submitted
, t
);
6919 r
->pages_printed
= 0; /* ??? */
6924 /****************************************************************************
6926 ****************************************************************************/
6928 static WERROR
fill_job_info3(TALLOC_CTX
*mem_ctx
,
6929 struct spoolss_JobInfo3
*r
,
6930 const print_queue_struct
*queue
,
6931 const print_queue_struct
*next_queue
,
6932 int position
, int snum
,
6933 struct spoolss_PrinterInfo2
*pinfo2
)
6935 r
->job_id
= queue
->job
;
6938 r
->next_job_id
= next_queue
->job
;
6945 /****************************************************************************
6946 Enumjobs at level 1.
6947 ****************************************************************************/
6949 static WERROR
enumjobs_level1(TALLOC_CTX
*mem_ctx
,
6950 const print_queue_struct
*queue
,
6951 uint32_t num_queues
, int snum
,
6952 struct spoolss_PrinterInfo2
*pinfo2
,
6953 union spoolss_JobInfo
**info_p
,
6956 union spoolss_JobInfo
*info
;
6958 WERROR result
= WERR_OK
;
6960 info
= talloc_array(mem_ctx
, union spoolss_JobInfo
, num_queues
);
6961 W_ERROR_HAVE_NO_MEMORY(info
);
6963 *count
= num_queues
;
6965 for (i
=0; i
<*count
; i
++) {
6966 result
= fill_job_info1(info
,
6972 if (!W_ERROR_IS_OK(result
)) {
6978 if (!W_ERROR_IS_OK(result
)) {
6989 /****************************************************************************
6990 Enumjobs at level 2.
6991 ****************************************************************************/
6993 static WERROR
enumjobs_level2(TALLOC_CTX
*mem_ctx
,
6994 const print_queue_struct
*queue
,
6995 uint32_t num_queues
, int snum
,
6996 struct spoolss_PrinterInfo2
*pinfo2
,
6997 union spoolss_JobInfo
**info_p
,
7000 union spoolss_JobInfo
*info
;
7002 WERROR result
= WERR_OK
;
7004 info
= talloc_array(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7005 W_ERROR_HAVE_NO_MEMORY(info
);
7007 *count
= num_queues
;
7009 for (i
=0; i
<*count
; i
++) {
7010 struct spoolss_DeviceMode
*devmode
;
7012 result
= spoolss_create_default_devmode(info
,
7013 pinfo2
->printername
,
7015 if (!W_ERROR_IS_OK(result
)) {
7016 DEBUG(3, ("Can't proceed w/o a devmode!"));
7020 result
= fill_job_info2(info
,
7027 if (!W_ERROR_IS_OK(result
)) {
7033 if (!W_ERROR_IS_OK(result
)) {
7044 /****************************************************************************
7045 Enumjobs at level 3.
7046 ****************************************************************************/
7048 static WERROR
enumjobs_level3(TALLOC_CTX
*mem_ctx
,
7049 const print_queue_struct
*queue
,
7050 uint32_t num_queues
, int snum
,
7051 struct spoolss_PrinterInfo2
*pinfo2
,
7052 union spoolss_JobInfo
**info_p
,
7055 union spoolss_JobInfo
*info
;
7057 WERROR result
= WERR_OK
;
7059 info
= talloc_array(mem_ctx
, union spoolss_JobInfo
, num_queues
);
7060 W_ERROR_HAVE_NO_MEMORY(info
);
7062 *count
= num_queues
;
7064 for (i
=0; i
<*count
; i
++) {
7065 const print_queue_struct
*next_queue
= NULL
;
7068 next_queue
= &queue
[i
+1];
7071 result
= fill_job_info3(info
,
7078 if (!W_ERROR_IS_OK(result
)) {
7084 if (!W_ERROR_IS_OK(result
)) {
7095 /****************************************************************
7097 ****************************************************************/
7099 WERROR
_spoolss_EnumJobs(struct pipes_struct
*p
,
7100 struct spoolss_EnumJobs
*r
)
7103 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
7105 print_status_struct prt_status
;
7106 print_queue_struct
*queue
= NULL
;
7109 /* that's an [in out] buffer */
7111 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7112 return WERR_INVALID_PARAM
;
7115 DEBUG(4,("_spoolss_EnumJobs\n"));
7119 *r
->out
.info
= NULL
;
7121 /* lookup the printer snum and tdb entry */
7123 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7127 result
= winreg_get_printer_internal(p
->mem_ctx
,
7128 get_session_info_system(),
7130 lp_const_servicename(snum
),
7132 if (!W_ERROR_IS_OK(result
)) {
7136 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
7137 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7138 count
, prt_status
.status
, prt_status
.message
));
7142 TALLOC_FREE(pinfo2
);
7146 switch (r
->in
.level
) {
7148 result
= enumjobs_level1(p
->mem_ctx
, queue
, count
, snum
,
7149 pinfo2
, r
->out
.info
, r
->out
.count
);
7152 result
= enumjobs_level2(p
->mem_ctx
, queue
, count
, snum
,
7153 pinfo2
, r
->out
.info
, r
->out
.count
);
7156 result
= enumjobs_level3(p
->mem_ctx
, queue
, count
, snum
,
7157 pinfo2
, r
->out
.info
, r
->out
.count
);
7160 result
= WERR_UNKNOWN_LEVEL
;
7165 TALLOC_FREE(pinfo2
);
7167 if (!W_ERROR_IS_OK(result
)) {
7171 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7173 *r
->out
.info
, r
->in
.level
,
7175 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7176 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7178 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7181 /****************************************************************
7182 _spoolss_ScheduleJob
7183 ****************************************************************/
7185 WERROR
_spoolss_ScheduleJob(struct pipes_struct
*p
,
7186 struct spoolss_ScheduleJob
*r
)
7191 /****************************************************************
7192 ****************************************************************/
7194 static WERROR
spoolss_setjob_1(TALLOC_CTX
*mem_ctx
,
7195 struct messaging_context
*msg_ctx
,
7196 const char *printer_name
,
7198 struct spoolss_SetJobInfo1
*r
)
7202 if (!print_job_get_name(mem_ctx
, printer_name
, job_id
, &old_doc_name
)) {
7206 if (strequal(old_doc_name
, r
->document_name
)) {
7210 if (!print_job_set_name(server_event_context(), msg_ctx
,
7211 printer_name
, job_id
, r
->document_name
)) {
7218 /****************************************************************
7220 ****************************************************************/
7222 WERROR
_spoolss_SetJob(struct pipes_struct
*p
,
7223 struct spoolss_SetJob
*r
)
7225 const struct auth_session_info
*session_info
= p
->session_info
;
7227 WERROR errcode
= WERR_BADFUNC
;
7229 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
7233 if (!print_job_exists(lp_const_servicename(snum
), r
->in
.job_id
)) {
7234 return WERR_INVALID_PRINTER_NAME
;
7237 switch (r
->in
.command
) {
7238 case SPOOLSS_JOB_CONTROL_CANCEL
:
7239 case SPOOLSS_JOB_CONTROL_DELETE
:
7240 errcode
= print_job_delete(session_info
, p
->msg_ctx
,
7241 snum
, r
->in
.job_id
);
7242 if (W_ERROR_EQUAL(errcode
, WERR_PRINTER_HAS_JOBS_QUEUED
)) {
7246 case SPOOLSS_JOB_CONTROL_PAUSE
:
7247 if (print_job_pause(session_info
, p
->msg_ctx
,
7248 snum
, r
->in
.job_id
, &errcode
)) {
7252 case SPOOLSS_JOB_CONTROL_RESTART
:
7253 case SPOOLSS_JOB_CONTROL_RESUME
:
7254 if (print_job_resume(session_info
, p
->msg_ctx
,
7255 snum
, r
->in
.job_id
, &errcode
)) {
7263 return WERR_UNKNOWN_LEVEL
;
7266 if (!W_ERROR_IS_OK(errcode
)) {
7270 if (r
->in
.ctr
== NULL
) {
7274 switch (r
->in
.ctr
->level
) {
7276 errcode
= spoolss_setjob_1(p
->mem_ctx
, p
->msg_ctx
,
7277 lp_const_servicename(snum
),
7279 r
->in
.ctr
->info
.info1
);
7285 return WERR_UNKNOWN_LEVEL
;
7291 /****************************************************************************
7292 Enumerates all printer drivers by level and architecture.
7293 ****************************************************************************/
7295 static WERROR
enumprinterdrivers_level_by_architecture(TALLOC_CTX
*mem_ctx
,
7296 const struct auth_session_info
*session_info
,
7297 struct messaging_context
*msg_ctx
,
7298 const char *servername
,
7299 const char *architecture
,
7301 union spoolss_DriverInfo
**info_p
,
7306 struct spoolss_DriverInfo8
*driver
;
7307 union spoolss_DriverInfo
*info
= NULL
;
7309 WERROR result
= WERR_OK
;
7310 uint32_t num_drivers
;
7311 const char **drivers
;
7312 struct dcerpc_binding_handle
*b
;
7313 TALLOC_CTX
*tmp_ctx
= NULL
;
7318 tmp_ctx
= talloc_new(mem_ctx
);
7323 result
= winreg_printer_binding_handle(tmp_ctx
,
7327 if (!W_ERROR_IS_OK(result
)) {
7331 for (version
=0; version
<DRIVER_MAX_VERSION
; version
++) {
7332 result
= winreg_get_driver_list(tmp_ctx
, b
,
7333 architecture
, version
,
7334 &num_drivers
, &drivers
);
7335 if (!W_ERROR_IS_OK(result
)) {
7338 DEBUG(4, ("we have:[%d] drivers in environment"
7339 " [%s] and version [%d]\n",
7340 num_drivers
, architecture
, version
));
7342 if (num_drivers
!= 0) {
7343 info
= talloc_realloc(tmp_ctx
, info
,
7344 union spoolss_DriverInfo
,
7345 count
+ num_drivers
);
7347 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7348 "failed to enlarge driver info buffer!\n"));
7349 result
= WERR_NOMEM
;
7354 for (i
= 0; i
< num_drivers
; i
++) {
7355 DEBUG(5, ("\tdriver: [%s]\n", drivers
[i
]));
7357 result
= winreg_get_driver(tmp_ctx
, b
,
7358 architecture
, drivers
[i
],
7360 if (!W_ERROR_IS_OK(result
)) {
7366 result
= fill_printer_driver_info1(info
, &info
[count
+i
].info1
,
7367 driver
, servername
);
7370 result
= fill_printer_driver_info2(info
, &info
[count
+i
].info2
,
7371 driver
, servername
);
7374 result
= fill_printer_driver_info3(info
, &info
[count
+i
].info3
,
7375 driver
, servername
);
7378 result
= fill_printer_driver_info4(info
, &info
[count
+i
].info4
,
7379 driver
, servername
);
7382 result
= fill_printer_driver_info5(info
, &info
[count
+i
].info5
,
7383 driver
, servername
);
7386 result
= fill_printer_driver_info6(info
, &info
[count
+i
].info6
,
7387 driver
, servername
);
7390 result
= fill_printer_driver_info8(info
, &info
[count
+i
].info8
,
7391 driver
, servername
);
7394 result
= WERR_UNKNOWN_LEVEL
;
7398 TALLOC_FREE(driver
);
7400 if (!W_ERROR_IS_OK(result
)) {
7405 count
+= num_drivers
;
7406 TALLOC_FREE(drivers
);
7410 if (W_ERROR_IS_OK(result
)) {
7411 *info_p
= talloc_move(mem_ctx
, &info
);
7415 talloc_free(tmp_ctx
);
7419 /****************************************************************************
7420 Enumerates all printer drivers by level.
7421 ****************************************************************************/
7423 static WERROR
enumprinterdrivers_level(TALLOC_CTX
*mem_ctx
,
7424 const struct auth_session_info
*session_info
,
7425 struct messaging_context
*msg_ctx
,
7426 const char *servername
,
7427 const char *architecture
,
7429 union spoolss_DriverInfo
**info_p
,
7433 WERROR result
= WERR_OK
;
7435 if (strequal(architecture
, SPOOLSS_ARCHITECTURE_ALL
)) {
7437 for (a
=0; archi_table
[a
].long_archi
!= NULL
; a
++) {
7439 union spoolss_DriverInfo
*info
= NULL
;
7442 result
= enumprinterdrivers_level_by_architecture(mem_ctx
,
7446 archi_table
[a
].long_archi
,
7450 if (!W_ERROR_IS_OK(result
)) {
7454 for (i
=0; i
< count
; i
++) {
7455 ADD_TO_ARRAY(mem_ctx
, union spoolss_DriverInfo
,
7456 info
[i
], info_p
, count_p
);
7463 return enumprinterdrivers_level_by_architecture(mem_ctx
,
7473 /****************************************************************
7474 _spoolss_EnumPrinterDrivers
7475 ****************************************************************/
7477 WERROR
_spoolss_EnumPrinterDrivers(struct pipes_struct
*p
,
7478 struct spoolss_EnumPrinterDrivers
*r
)
7480 const char *cservername
;
7483 /* that's an [in out] buffer */
7485 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7486 return WERR_INVALID_PARAM
;
7489 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7493 *r
->out
.info
= NULL
;
7495 cservername
= canon_servername(r
->in
.server
);
7497 if (!is_myname_or_ipaddr(cservername
)) {
7498 return WERR_UNKNOWN_PRINTER_DRIVER
;
7501 result
= enumprinterdrivers_level(p
->mem_ctx
,
7502 get_session_info_system(),
7509 if (!W_ERROR_IS_OK(result
)) {
7513 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7514 spoolss_EnumPrinterDrivers
,
7515 *r
->out
.info
, r
->in
.level
,
7517 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7518 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7520 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7523 /****************************************************************
7525 ****************************************************************/
7527 WERROR
_spoolss_EnumForms(struct pipes_struct
*p
,
7528 struct spoolss_EnumForms
*r
)
7534 *r
->out
.info
= NULL
;
7536 /* that's an [in out] buffer */
7538 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0) ) {
7539 return WERR_INVALID_PARAM
;
7542 DEBUG(4,("_spoolss_EnumForms\n"));
7543 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7544 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7546 switch (r
->in
.level
) {
7548 result
= winreg_printer_enumforms1_internal(p
->mem_ctx
,
7549 get_session_info_system(),
7555 result
= WERR_UNKNOWN_LEVEL
;
7559 if (!W_ERROR_IS_OK(result
)) {
7563 if (*r
->out
.count
== 0) {
7564 return WERR_NO_MORE_ITEMS
;
7567 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7569 *r
->out
.info
, r
->in
.level
,
7571 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7572 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7574 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7577 /****************************************************************
7579 ****************************************************************/
7581 WERROR
_spoolss_GetForm(struct pipes_struct
*p
,
7582 struct spoolss_GetForm
*r
)
7586 /* that's an [in out] buffer */
7588 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7589 return WERR_INVALID_PARAM
;
7592 DEBUG(4,("_spoolss_GetForm\n"));
7593 DEBUGADD(5,("Offered buffer size [%d]\n", r
->in
.offered
));
7594 DEBUGADD(5,("Info level [%d]\n", r
->in
.level
));
7596 switch (r
->in
.level
) {
7598 result
= winreg_printer_getform1_internal(p
->mem_ctx
,
7599 get_session_info_system(),
7602 &r
->out
.info
->info1
);
7605 result
= WERR_UNKNOWN_LEVEL
;
7609 if (!W_ERROR_IS_OK(result
)) {
7610 TALLOC_FREE(r
->out
.info
);
7614 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_FormInfo
,
7615 r
->out
.info
, r
->in
.level
);
7616 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
7618 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7621 /****************************************************************************
7622 ****************************************************************************/
7624 static WERROR
fill_port_1(TALLOC_CTX
*mem_ctx
,
7625 struct spoolss_PortInfo1
*r
,
7628 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7629 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7634 /****************************************************************************
7635 TODO: This probably needs distinguish between TCP/IP and Local ports
7637 ****************************************************************************/
7639 static WERROR
fill_port_2(TALLOC_CTX
*mem_ctx
,
7640 struct spoolss_PortInfo2
*r
,
7643 r
->port_name
= talloc_strdup(mem_ctx
, name
);
7644 W_ERROR_HAVE_NO_MEMORY(r
->port_name
);
7646 r
->monitor_name
= talloc_strdup(mem_ctx
, "Local Monitor");
7647 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
7649 r
->description
= talloc_strdup(mem_ctx
, SPL_LOCAL_PORT
);
7650 W_ERROR_HAVE_NO_MEMORY(r
->description
);
7652 r
->port_type
= SPOOLSS_PORT_TYPE_WRITE
;
7659 /****************************************************************************
7660 wrapper around the enumer ports command
7661 ****************************************************************************/
7663 static WERROR
enumports_hook(TALLOC_CTX
*ctx
, int *count
, char ***lines
)
7665 char *cmd
= lp_enumports_cmd();
7666 char **qlines
= NULL
;
7667 char *command
= NULL
;
7675 /* if no hook then just fill in the default port */
7678 if (!(qlines
= talloc_array( NULL
, char*, 2 ))) {
7681 if (!(qlines
[0] = talloc_strdup(qlines
, SAMBA_PRINTER_PORT_NAME
))) {
7682 TALLOC_FREE(qlines
);
7689 /* we have a valid enumport command */
7691 command
= talloc_asprintf(ctx
, "%s \"%d\"", cmd
, 1);
7696 DEBUG(10,("Running [%s]\n", command
));
7697 ret
= smbrun(command
, &fd
);
7698 DEBUG(10,("Returned [%d]\n", ret
));
7699 TALLOC_FREE(command
);
7704 return WERR_ACCESS_DENIED
;
7708 qlines
= fd_lines_load(fd
, &numlines
, 0, NULL
);
7709 DEBUGADD(10,("Lines returned = [%d]\n", numlines
));
7719 /****************************************************************************
7721 ****************************************************************************/
7723 static WERROR
enumports_level_1(TALLOC_CTX
*mem_ctx
,
7724 union spoolss_PortInfo
**info_p
,
7727 union spoolss_PortInfo
*info
= NULL
;
7729 WERROR result
= WERR_OK
;
7730 char **qlines
= NULL
;
7733 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7734 if (!W_ERROR_IS_OK(result
)) {
7739 info
= talloc_array(mem_ctx
, union spoolss_PortInfo
, numlines
);
7741 DEBUG(10,("Returning WERR_NOMEM\n"));
7742 result
= WERR_NOMEM
;
7746 for (i
=0; i
<numlines
; i
++) {
7747 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7748 result
= fill_port_1(info
, &info
[i
].info1
, qlines
[i
]);
7749 if (!W_ERROR_IS_OK(result
)) {
7754 TALLOC_FREE(qlines
);
7757 if (!W_ERROR_IS_OK(result
)) {
7759 TALLOC_FREE(qlines
);
7771 /****************************************************************************
7773 ****************************************************************************/
7775 static WERROR
enumports_level_2(TALLOC_CTX
*mem_ctx
,
7776 union spoolss_PortInfo
**info_p
,
7779 union spoolss_PortInfo
*info
= NULL
;
7781 WERROR result
= WERR_OK
;
7782 char **qlines
= NULL
;
7785 result
= enumports_hook(talloc_tos(), &numlines
, &qlines
);
7786 if (!W_ERROR_IS_OK(result
)) {
7791 info
= talloc_array(mem_ctx
, union spoolss_PortInfo
, numlines
);
7793 DEBUG(10,("Returning WERR_NOMEM\n"));
7794 result
= WERR_NOMEM
;
7798 for (i
=0; i
<numlines
; i
++) {
7799 DEBUG(6,("Filling port number [%d] with port [%s]\n", i
, qlines
[i
]));
7800 result
= fill_port_2(info
, &info
[i
].info2
, qlines
[i
]);
7801 if (!W_ERROR_IS_OK(result
)) {
7806 TALLOC_FREE(qlines
);
7809 if (!W_ERROR_IS_OK(result
)) {
7811 TALLOC_FREE(qlines
);
7823 /****************************************************************
7825 ****************************************************************/
7827 WERROR
_spoolss_EnumPorts(struct pipes_struct
*p
,
7828 struct spoolss_EnumPorts
*r
)
7832 /* that's an [in out] buffer */
7834 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
7835 return WERR_INVALID_PARAM
;
7838 DEBUG(4,("_spoolss_EnumPorts\n"));
7842 *r
->out
.info
= NULL
;
7844 switch (r
->in
.level
) {
7846 result
= enumports_level_1(p
->mem_ctx
, r
->out
.info
,
7850 result
= enumports_level_2(p
->mem_ctx
, r
->out
.info
,
7854 return WERR_UNKNOWN_LEVEL
;
7857 if (!W_ERROR_IS_OK(result
)) {
7861 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
7863 *r
->out
.info
, r
->in
.level
,
7865 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
7866 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
7868 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
7871 /****************************************************************************
7872 ****************************************************************************/
7874 static WERROR
spoolss_addprinterex_level_2(struct pipes_struct
*p
,
7876 struct spoolss_SetPrinterInfoCtr
*info_ctr
,
7877 struct spoolss_DeviceMode
*devmode
,
7878 struct security_descriptor
*secdesc
,
7879 struct spoolss_UserLevelCtr
*user_ctr
,
7880 struct policy_handle
*handle
)
7882 struct spoolss_SetPrinterInfo2
*info2
= info_ctr
->info
.info2
;
7883 uint32_t info2_mask
= SPOOLSS_PRINTER_INFO_ALL
;
7885 WERROR err
= WERR_OK
;
7887 /* samba does not have a concept of local, non-shared printers yet, so
7888 * make sure we always setup sharename - gd */
7889 if ((info2
->sharename
== NULL
|| info2
->sharename
[0] == '\0') &&
7890 (info2
->printername
!= NULL
&& info2
->printername
[0] != '\0')) {
7891 DEBUG(5, ("spoolss_addprinterex_level_2: "
7892 "no sharename has been set, setting printername %s as sharename\n",
7893 info2
->printername
));
7894 info2
->sharename
= info2
->printername
;
7897 /* check to see if the printer already exists */
7898 if ((snum
= print_queue_snum(info2
->sharename
)) != -1) {
7899 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7901 return WERR_PRINTER_ALREADY_EXISTS
;
7904 if (!lp_force_printername(GLOBAL_SECTION_SNUM
)) {
7905 if ((snum
= print_queue_snum(info2
->printername
)) != -1) {
7906 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7907 info2
->printername
));
7908 return WERR_PRINTER_ALREADY_EXISTS
;
7912 /* validate printer info struct */
7913 if (!info2
->printername
|| strlen(info2
->printername
) == 0) {
7914 return WERR_INVALID_PRINTER_NAME
;
7916 if (!info2
->portname
|| strlen(info2
->portname
) == 0) {
7917 return WERR_UNKNOWN_PORT
;
7919 if (!info2
->drivername
|| strlen(info2
->drivername
) == 0) {
7920 return WERR_UNKNOWN_PRINTER_DRIVER
;
7922 if (!info2
->printprocessor
|| strlen(info2
->printprocessor
) == 0) {
7923 return WERR_UNKNOWN_PRINTPROCESSOR
;
7926 /* FIXME!!! smbd should check to see if the driver is installed before
7927 trying to add a printer like this --jerry */
7929 if (*lp_addprinter_cmd() ) {
7932 raddr
= tsocket_address_inet_addr_string(p
->remote_address
,
7934 if (raddr
== NULL
) {
7938 if ( !add_printer_hook(p
->mem_ctx
, p
->session_info
->security_token
,
7941 return WERR_ACCESS_DENIED
;
7944 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7945 "smb.conf parameter \"addprinter command\" is defined. This "
7946 "parameter must exist for this call to succeed\n",
7947 info2
->sharename
));
7950 if ((snum
= print_queue_snum(info2
->sharename
)) == -1) {
7951 return WERR_ACCESS_DENIED
;
7954 /* you must be a printer admin to add a new printer */
7955 if (!print_access_check(p
->session_info
,
7958 PRINTER_ACCESS_ADMINISTER
)) {
7959 return WERR_ACCESS_DENIED
;
7963 * Do sanity check on the requested changes for Samba.
7966 if (!check_printer_ok(p
->mem_ctx
, info2
, snum
)) {
7967 return WERR_INVALID_PARAM
;
7970 if (devmode
== NULL
) {
7971 info2_mask
= ~SPOOLSS_PRINTER_INFO_DEVMODE
;
7974 update_dsspooler(p
->mem_ctx
,
7975 get_session_info_system(),
7981 err
= winreg_update_printer_internal(p
->mem_ctx
,
7982 get_session_info_system(),
7989 if (!W_ERROR_IS_OK(err
)) {
7993 err
= open_printer_hnd(p
, handle
, info2
->printername
, PRINTER_ACCESS_ADMINISTER
);
7994 if (!W_ERROR_IS_OK(err
)) {
7995 /* Handle open failed - remove addition. */
7996 ZERO_STRUCTP(handle
);
8003 /****************************************************************
8004 _spoolss_AddPrinterEx
8005 ****************************************************************/
8007 WERROR
_spoolss_AddPrinterEx(struct pipes_struct
*p
,
8008 struct spoolss_AddPrinterEx
*r
)
8010 switch (r
->in
.info_ctr
->level
) {
8012 /* we don't handle yet */
8013 /* but I know what to do ... */
8014 return WERR_UNKNOWN_LEVEL
;
8016 return spoolss_addprinterex_level_2(p
, r
->in
.server
,
8018 r
->in
.devmode_ctr
->devmode
,
8019 r
->in
.secdesc_ctr
->sd
,
8020 r
->in
.userlevel_ctr
,
8023 return WERR_UNKNOWN_LEVEL
;
8027 /****************************************************************
8029 ****************************************************************/
8031 WERROR
_spoolss_AddPrinter(struct pipes_struct
*p
,
8032 struct spoolss_AddPrinter
*r
)
8034 struct spoolss_AddPrinterEx a
;
8035 struct spoolss_UserLevelCtr userlevel_ctr
;
8037 ZERO_STRUCT(userlevel_ctr
);
8039 userlevel_ctr
.level
= 1;
8041 a
.in
.server
= r
->in
.server
;
8042 a
.in
.info_ctr
= r
->in
.info_ctr
;
8043 a
.in
.devmode_ctr
= r
->in
.devmode_ctr
;
8044 a
.in
.secdesc_ctr
= r
->in
.secdesc_ctr
;
8045 a
.in
.userlevel_ctr
= &userlevel_ctr
;
8046 a
.out
.handle
= r
->out
.handle
;
8048 return _spoolss_AddPrinterEx(p
, &a
);
8051 /****************************************************************
8052 _spoolss_AddPrinterDriverEx
8053 ****************************************************************/
8055 WERROR
_spoolss_AddPrinterDriverEx(struct pipes_struct
*p
,
8056 struct spoolss_AddPrinterDriverEx
*r
)
8058 WERROR err
= WERR_OK
;
8059 const char *driver_name
= NULL
;
8064 case NDR_SPOOLSS_ADDPRINTERDRIVER
:
8065 fn
= "_spoolss_AddPrinterDriver";
8067 case NDR_SPOOLSS_ADDPRINTERDRIVEREX
:
8068 fn
= "_spoolss_AddPrinterDriverEx";
8071 return WERR_INVALID_PARAM
;
8075 * we only support the semantics of AddPrinterDriver()
8076 * i.e. only copy files that are newer than existing ones
8079 if (r
->in
.flags
== 0) {
8080 return WERR_INVALID_PARAM
;
8083 if (r
->in
.flags
!= APD_COPY_NEW_FILES
) {
8084 return WERR_ACCESS_DENIED
;
8088 if (r
->in
.info_ctr
->level
!= 3 && r
->in
.info_ctr
->level
!= 6) {
8089 /* Clever hack from Martin Zielinski <mz@seh.de>
8090 * to allow downgrade from level 8 (Vista).
8092 DEBUG(0,("%s: level %d not yet implemented\n", fn
,
8093 r
->in
.info_ctr
->level
));
8094 return WERR_UNKNOWN_LEVEL
;
8097 DEBUG(5,("Cleaning driver's information\n"));
8098 err
= clean_up_driver_struct(p
->mem_ctx
, p
->session_info
, r
->in
.info_ctr
);
8099 if (!W_ERROR_IS_OK(err
))
8102 DEBUG(5,("Moving driver to final destination\n"));
8103 err
= move_driver_to_download_area(p
->session_info
, r
->in
.info_ctr
);
8104 if (!W_ERROR_IS_OK(err
)) {
8108 err
= winreg_add_driver_internal(p
->mem_ctx
,
8109 get_session_info_system(),
8114 if (!W_ERROR_IS_OK(err
)) {
8119 * I think this is where he DrvUpgradePrinter() hook would be
8120 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8121 * server. Right now, we just need to send ourselves a message
8122 * to update each printer bound to this driver. --jerry
8125 if (!srv_spoolss_drv_upgrade_printer(driver_name
, p
->msg_ctx
)) {
8126 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8134 /****************************************************************
8135 _spoolss_AddPrinterDriver
8136 ****************************************************************/
8138 WERROR
_spoolss_AddPrinterDriver(struct pipes_struct
*p
,
8139 struct spoolss_AddPrinterDriver
*r
)
8141 struct spoolss_AddPrinterDriverEx a
;
8143 switch (r
->in
.info_ctr
->level
) {
8150 return WERR_UNKNOWN_LEVEL
;
8153 a
.in
.servername
= r
->in
.servername
;
8154 a
.in
.info_ctr
= r
->in
.info_ctr
;
8155 a
.in
.flags
= APD_COPY_NEW_FILES
;
8157 return _spoolss_AddPrinterDriverEx(p
, &a
);
8160 /****************************************************************************
8161 ****************************************************************************/
8163 struct _spoolss_paths
{
8169 enum { SPOOLSS_DRIVER_PATH
, SPOOLSS_PRTPROCS_PATH
};
8171 static const struct _spoolss_paths spoolss_paths
[]= {
8172 { SPOOLSS_DRIVER_PATH
, "print$", "DRIVERS" },
8173 { SPOOLSS_PRTPROCS_PATH
, "prnproc$", "PRTPROCS" }
8176 static WERROR
compose_spoolss_server_path(TALLOC_CTX
*mem_ctx
,
8177 const char *servername
,
8178 const char *environment
,
8182 const char *pservername
= NULL
;
8183 const char *long_archi
= SPOOLSS_ARCHITECTURE_NT_X86
;
8184 const char *short_archi
;
8188 /* environment may be empty */
8189 if (environment
&& strlen(environment
)) {
8190 long_archi
= environment
;
8193 /* servername may be empty */
8194 if (servername
&& strlen(servername
)) {
8195 pservername
= canon_servername(servername
);
8197 if (!is_myname_or_ipaddr(pservername
)) {
8198 return WERR_INVALID_PARAM
;
8202 if (!(short_archi
= get_short_archi(long_archi
))) {
8203 return WERR_INVALID_ENVIRONMENT
;
8206 switch (component
) {
8207 case SPOOLSS_PRTPROCS_PATH
:
8208 case SPOOLSS_DRIVER_PATH
:
8210 *path
= talloc_asprintf(mem_ctx
,
8213 spoolss_paths
[component
].share
,
8216 *path
= talloc_asprintf(mem_ctx
, "%s\\%s\\%s",
8217 SPOOLSS_DEFAULT_SERVER_PATH
,
8218 spoolss_paths
[component
].dir
,
8223 return WERR_INVALID_PARAM
;
8233 /****************************************************************************
8234 ****************************************************************************/
8236 static WERROR
getprinterdriverdir_level_1(TALLOC_CTX
*mem_ctx
,
8237 const char *servername
,
8238 const char *environment
,
8239 struct spoolss_DriverDirectoryInfo1
*r
)
8244 werr
= compose_spoolss_server_path(mem_ctx
,
8247 SPOOLSS_DRIVER_PATH
,
8249 if (!W_ERROR_IS_OK(werr
)) {
8253 DEBUG(4,("printer driver directory: [%s]\n", path
));
8255 r
->directory_name
= path
;
8260 /****************************************************************
8261 _spoolss_GetPrinterDriverDirectory
8262 ****************************************************************/
8264 WERROR
_spoolss_GetPrinterDriverDirectory(struct pipes_struct
*p
,
8265 struct spoolss_GetPrinterDriverDirectory
*r
)
8269 /* that's an [in out] buffer */
8271 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8272 return WERR_INVALID_PARAM
;
8275 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8280 /* r->in.level is ignored */
8282 werror
= getprinterdriverdir_level_1(p
->mem_ctx
,
8285 &r
->out
.info
->info1
);
8286 if (!W_ERROR_IS_OK(werror
)) {
8287 TALLOC_FREE(r
->out
.info
);
8291 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo
,
8292 r
->out
.info
, r
->in
.level
);
8293 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
8295 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8298 /****************************************************************
8299 _spoolss_EnumPrinterData
8300 ****************************************************************/
8302 WERROR
_spoolss_EnumPrinterData(struct pipes_struct
*p
,
8303 struct spoolss_EnumPrinterData
*r
)
8306 struct spoolss_EnumPrinterDataEx r2
;
8308 struct spoolss_PrinterEnumValues
*info
, *val
= NULL
;
8311 r2
.in
.handle
= r
->in
.handle
;
8312 r2
.in
.key_name
= "PrinterDriverData";
8314 r2
.out
.count
= &count
;
8315 r2
.out
.info
= &info
;
8316 r2
.out
.needed
= &needed
;
8318 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
8319 if (W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
8320 r2
.in
.offered
= needed
;
8321 result
= _spoolss_EnumPrinterDataEx(p
, &r2
);
8323 if (!W_ERROR_IS_OK(result
)) {
8328 * The NT machine wants to know the biggest size of value and data
8330 * cf: MSDN EnumPrinterData remark section
8333 if (!r
->in
.value_offered
&& !r
->in
.data_offered
) {
8334 uint32_t biggest_valuesize
= 0;
8335 uint32_t biggest_datasize
= 0;
8338 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8340 for (i
=0; i
<count
; i
++) {
8342 name_length
= strlen(info
[i
].value_name
);
8343 if (strlen(info
[i
].value_name
) > biggest_valuesize
) {
8344 biggest_valuesize
= name_length
;
8347 if (info
[i
].data_length
> biggest_datasize
) {
8348 biggest_datasize
= info
[i
].data_length
;
8351 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize
,
8355 /* the value is an UNICODE string but real_value_size is the length
8356 in bytes including the trailing 0 */
8358 *r
->out
.value_needed
= 2 * (1 + biggest_valuesize
);
8359 *r
->out
.data_needed
= biggest_datasize
;
8361 DEBUG(6,("final values: [%d], [%d]\n",
8362 *r
->out
.value_needed
, *r
->out
.data_needed
));
8367 if (r
->in
.enum_index
< count
) {
8368 val
= &info
[r
->in
.enum_index
];
8372 /* out_value should default to "" or else NT4 has
8373 problems unmarshalling the response */
8375 if (r
->in
.value_offered
) {
8376 *r
->out
.value_needed
= 1;
8377 r
->out
.value_name
= talloc_strdup(r
, "");
8378 if (!r
->out
.value_name
) {
8382 r
->out
.value_name
= NULL
;
8383 *r
->out
.value_needed
= 0;
8386 /* the data is counted in bytes */
8388 *r
->out
.data_needed
= r
->in
.data_offered
;
8390 result
= WERR_NO_MORE_ITEMS
;
8394 * - counted in bytes in the request
8395 * - counted in UNICODE chars in the max reply
8396 * - counted in bytes in the real size
8398 * take a pause *before* coding not *during* coding
8402 if (r
->in
.value_offered
) {
8403 r
->out
.value_name
= talloc_strdup(r
, val
->value_name
);
8404 if (!r
->out
.value_name
) {
8407 *r
->out
.value_needed
= val
->value_name_len
;
8409 r
->out
.value_name
= NULL
;
8410 *r
->out
.value_needed
= 0;
8415 *r
->out
.type
= val
->type
;
8417 /* data - counted in bytes */
8420 * See the section "Dynamically Typed Query Parameters"
8424 if (r
->out
.data
&& val
->data
&& val
->data
->data
&&
8425 val
->data_length
&& r
->in
.data_offered
) {
8426 memcpy(r
->out
.data
, val
->data
->data
,
8427 MIN(val
->data_length
,r
->in
.data_offered
));
8430 *r
->out
.data_needed
= val
->data_length
;
8438 /****************************************************************
8439 _spoolss_SetPrinterData
8440 ****************************************************************/
8442 WERROR
_spoolss_SetPrinterData(struct pipes_struct
*p
,
8443 struct spoolss_SetPrinterData
*r
)
8445 struct spoolss_SetPrinterDataEx r2
;
8447 r2
.in
.handle
= r
->in
.handle
;
8448 r2
.in
.key_name
= "PrinterDriverData";
8449 r2
.in
.value_name
= r
->in
.value_name
;
8450 r2
.in
.type
= r
->in
.type
;
8451 r2
.in
.data
= r
->in
.data
;
8452 r2
.in
.offered
= r
->in
.offered
;
8454 return _spoolss_SetPrinterDataEx(p
, &r2
);
8457 /****************************************************************
8458 _spoolss_ResetPrinter
8459 ****************************************************************/
8461 WERROR
_spoolss_ResetPrinter(struct pipes_struct
*p
,
8462 struct spoolss_ResetPrinter
*r
)
8464 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8467 DEBUG(5,("_spoolss_ResetPrinter\n"));
8470 * All we do is to check to see if the handle and queue is valid.
8471 * This call really doesn't mean anything to us because we only
8472 * support RAW printing. --jerry
8476 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8477 OUR_HANDLE(r
->in
.handle
)));
8481 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
))
8485 /* blindly return success */
8489 /****************************************************************
8490 _spoolss_DeletePrinterData
8491 ****************************************************************/
8493 WERROR
_spoolss_DeletePrinterData(struct pipes_struct
*p
,
8494 struct spoolss_DeletePrinterData
*r
)
8496 struct spoolss_DeletePrinterDataEx r2
;
8498 r2
.in
.handle
= r
->in
.handle
;
8499 r2
.in
.key_name
= "PrinterDriverData";
8500 r2
.in
.value_name
= r
->in
.value_name
;
8502 return _spoolss_DeletePrinterDataEx(p
, &r2
);
8505 /****************************************************************
8507 ****************************************************************/
8509 WERROR
_spoolss_AddForm(struct pipes_struct
*p
,
8510 struct spoolss_AddForm
*r
)
8512 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8514 WERROR status
= WERR_OK
;
8515 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8516 struct dcerpc_binding_handle
*b
;
8517 TALLOC_CTX
*tmp_ctx
= NULL
;
8519 DEBUG(5,("_spoolss_AddForm\n"));
8522 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8523 OUR_HANDLE(r
->in
.handle
)));
8527 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8528 and not a printer admin, then fail */
8530 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
8531 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
8532 !token_contains_name_in_list(uidtoname(p
->session_info
->unix_token
->uid
),
8533 p
->session_info
->info
->domain_name
,
8535 p
->session_info
->security_token
,
8536 lp_printer_admin(snum
))) {
8537 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8538 return WERR_ACCESS_DENIED
;
8541 switch (form
->flags
) {
8542 case SPOOLSS_FORM_USER
:
8543 case SPOOLSS_FORM_BUILTIN
:
8544 case SPOOLSS_FORM_PRINTER
:
8547 return WERR_INVALID_PARAM
;
8550 tmp_ctx
= talloc_new(p
->mem_ctx
);
8555 status
= winreg_printer_binding_handle(tmp_ctx
,
8556 get_session_info_system(),
8559 if (!W_ERROR_IS_OK(status
)) {
8563 status
= winreg_printer_addform1(tmp_ctx
, b
, form
);
8564 if (!W_ERROR_IS_OK(status
)) {
8569 * ChangeID must always be set if this is a printer
8571 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8572 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8573 status
= WERR_BADFID
;
8577 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
8578 lp_const_servicename(snum
));
8582 talloc_free(tmp_ctx
);
8586 /****************************************************************
8588 ****************************************************************/
8590 WERROR
_spoolss_DeleteForm(struct pipes_struct
*p
,
8591 struct spoolss_DeleteForm
*r
)
8593 const char *form_name
= r
->in
.form_name
;
8594 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8596 WERROR status
= WERR_OK
;
8597 struct dcerpc_binding_handle
*b
;
8598 TALLOC_CTX
*tmp_ctx
= NULL
;
8600 DEBUG(5,("_spoolss_DeleteForm\n"));
8603 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8604 OUR_HANDLE(r
->in
.handle
)));
8608 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
8609 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
8610 !token_contains_name_in_list(uidtoname(p
->session_info
->unix_token
->uid
),
8611 p
->session_info
->info
->domain_name
,
8613 p
->session_info
->security_token
,
8614 lp_printer_admin(snum
))) {
8615 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8616 return WERR_ACCESS_DENIED
;
8619 tmp_ctx
= talloc_new(p
->mem_ctx
);
8624 status
= winreg_printer_binding_handle(tmp_ctx
,
8625 get_session_info_system(),
8628 if (!W_ERROR_IS_OK(status
)) {
8632 status
= winreg_printer_deleteform1(tmp_ctx
, b
, form_name
);
8633 if (!W_ERROR_IS_OK(status
)) {
8638 * ChangeID must always be set if this is a printer
8640 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8641 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8642 status
= WERR_BADFID
;
8646 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
8647 lp_const_servicename(snum
));
8651 talloc_free(tmp_ctx
);
8655 /****************************************************************
8657 ****************************************************************/
8659 WERROR
_spoolss_SetForm(struct pipes_struct
*p
,
8660 struct spoolss_SetForm
*r
)
8662 struct spoolss_AddFormInfo1
*form
= r
->in
.info
.info1
;
8663 const char *form_name
= r
->in
.form_name
;
8665 WERROR status
= WERR_OK
;
8666 struct dcerpc_binding_handle
*b
;
8667 TALLOC_CTX
*tmp_ctx
= NULL
;
8669 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
8671 DEBUG(5,("_spoolss_SetForm\n"));
8674 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8675 OUR_HANDLE(r
->in
.handle
)));
8679 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8680 and not a printer admin, then fail */
8682 if ((p
->session_info
->unix_token
->uid
!= sec_initial_uid()) &&
8683 !security_token_has_privilege(p
->session_info
->security_token
, SEC_PRIV_PRINT_OPERATOR
) &&
8684 !token_contains_name_in_list(uidtoname(p
->session_info
->unix_token
->uid
),
8685 p
->session_info
->info
->domain_name
,
8687 p
->session_info
->security_token
,
8688 lp_printer_admin(snum
))) {
8689 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8690 return WERR_ACCESS_DENIED
;
8693 tmp_ctx
= talloc_new(p
->mem_ctx
);
8698 status
= winreg_printer_binding_handle(tmp_ctx
,
8699 get_session_info_system(),
8702 if (!W_ERROR_IS_OK(status
)) {
8706 status
= winreg_printer_setform1(tmp_ctx
, b
,
8709 if (!W_ERROR_IS_OK(status
)) {
8714 * ChangeID must always be set if this is a printer
8716 if (Printer
->printer_type
== SPLHND_PRINTER
) {
8717 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
8718 status
= WERR_BADFID
;
8722 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
8723 lp_const_servicename(snum
));
8727 talloc_free(tmp_ctx
);
8731 /****************************************************************************
8732 fill_print_processor1
8733 ****************************************************************************/
8735 static WERROR
fill_print_processor1(TALLOC_CTX
*mem_ctx
,
8736 struct spoolss_PrintProcessorInfo1
*r
,
8737 const char *print_processor_name
)
8739 r
->print_processor_name
= talloc_strdup(mem_ctx
, print_processor_name
);
8740 W_ERROR_HAVE_NO_MEMORY(r
->print_processor_name
);
8745 /****************************************************************************
8746 enumprintprocessors level 1.
8747 ****************************************************************************/
8749 static WERROR
enumprintprocessors_level_1(TALLOC_CTX
*mem_ctx
,
8750 union spoolss_PrintProcessorInfo
**info_p
,
8753 union spoolss_PrintProcessorInfo
*info
;
8756 info
= talloc_array(mem_ctx
, union spoolss_PrintProcessorInfo
, 1);
8757 W_ERROR_HAVE_NO_MEMORY(info
);
8761 result
= fill_print_processor1(info
, &info
[0].info1
, "winprint");
8762 if (!W_ERROR_IS_OK(result
)) {
8767 if (!W_ERROR_IS_OK(result
)) {
8778 /****************************************************************
8779 _spoolss_EnumPrintProcessors
8780 ****************************************************************/
8782 WERROR
_spoolss_EnumPrintProcessors(struct pipes_struct
*p
,
8783 struct spoolss_EnumPrintProcessors
*r
)
8787 /* that's an [in out] buffer */
8789 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8790 return WERR_INVALID_PARAM
;
8793 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8796 * Enumerate the print processors ...
8798 * Just reply with "winprint", to keep NT happy
8799 * and I can use my nice printer checker.
8804 *r
->out
.info
= NULL
;
8806 if (!get_short_archi(r
->in
.environment
)) {
8807 return WERR_INVALID_ENVIRONMENT
;
8810 switch (r
->in
.level
) {
8812 result
= enumprintprocessors_level_1(p
->mem_ctx
, r
->out
.info
,
8816 return WERR_UNKNOWN_LEVEL
;
8819 if (!W_ERROR_IS_OK(result
)) {
8823 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8824 spoolss_EnumPrintProcessors
,
8825 *r
->out
.info
, r
->in
.level
,
8827 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8828 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8830 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8833 /****************************************************************************
8834 fill_printprocdatatype1
8835 ****************************************************************************/
8837 static WERROR
fill_printprocdatatype1(TALLOC_CTX
*mem_ctx
,
8838 struct spoolss_PrintProcDataTypesInfo1
*r
,
8839 const char *name_array
)
8841 r
->name_array
= talloc_strdup(mem_ctx
, name_array
);
8842 W_ERROR_HAVE_NO_MEMORY(r
->name_array
);
8847 /****************************************************************************
8848 enumprintprocdatatypes level 1.
8849 ****************************************************************************/
8851 static WERROR
enumprintprocdatatypes_level_1(TALLOC_CTX
*mem_ctx
,
8852 union spoolss_PrintProcDataTypesInfo
**info_p
,
8856 union spoolss_PrintProcDataTypesInfo
*info
;
8858 info
= talloc_array(mem_ctx
, union spoolss_PrintProcDataTypesInfo
, 1);
8859 W_ERROR_HAVE_NO_MEMORY(info
);
8863 result
= fill_printprocdatatype1(info
, &info
[0].info1
, "RAW");
8864 if (!W_ERROR_IS_OK(result
)) {
8869 if (!W_ERROR_IS_OK(result
)) {
8880 /****************************************************************
8881 _spoolss_EnumPrintProcDataTypes
8882 ****************************************************************/
8884 WERROR
_spoolss_EnumPrintProcDataTypes(struct pipes_struct
*p
,
8885 struct spoolss_EnumPrintProcDataTypes
*r
)
8889 /* that's an [in out] buffer */
8891 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
8892 return WERR_INVALID_PARAM
;
8895 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8899 *r
->out
.info
= NULL
;
8901 if (r
->in
.print_processor_name
== NULL
||
8902 !strequal(r
->in
.print_processor_name
, "winprint")) {
8903 return WERR_UNKNOWN_PRINTPROCESSOR
;
8906 switch (r
->in
.level
) {
8908 result
= enumprintprocdatatypes_level_1(p
->mem_ctx
, r
->out
.info
,
8912 return WERR_UNKNOWN_LEVEL
;
8915 if (!W_ERROR_IS_OK(result
)) {
8919 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
8920 spoolss_EnumPrintProcDataTypes
,
8921 *r
->out
.info
, r
->in
.level
,
8923 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
8924 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
8926 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
8929 /****************************************************************************
8931 ****************************************************************************/
8933 static WERROR
fill_monitor_1(TALLOC_CTX
*mem_ctx
,
8934 struct spoolss_MonitorInfo1
*r
,
8935 const char *monitor_name
)
8937 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8938 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8943 /****************************************************************************
8945 ****************************************************************************/
8947 static WERROR
fill_monitor_2(TALLOC_CTX
*mem_ctx
,
8948 struct spoolss_MonitorInfo2
*r
,
8949 const char *monitor_name
,
8950 const char *environment
,
8951 const char *dll_name
)
8953 r
->monitor_name
= talloc_strdup(mem_ctx
, monitor_name
);
8954 W_ERROR_HAVE_NO_MEMORY(r
->monitor_name
);
8955 r
->environment
= talloc_strdup(mem_ctx
, environment
);
8956 W_ERROR_HAVE_NO_MEMORY(r
->environment
);
8957 r
->dll_name
= talloc_strdup(mem_ctx
, dll_name
);
8958 W_ERROR_HAVE_NO_MEMORY(r
->dll_name
);
8963 /****************************************************************************
8964 enumprintmonitors level 1.
8965 ****************************************************************************/
8967 static WERROR
enumprintmonitors_level_1(TALLOC_CTX
*mem_ctx
,
8968 union spoolss_MonitorInfo
**info_p
,
8971 union spoolss_MonitorInfo
*info
;
8972 WERROR result
= WERR_OK
;
8974 info
= talloc_array(mem_ctx
, union spoolss_MonitorInfo
, 2);
8975 W_ERROR_HAVE_NO_MEMORY(info
);
8979 result
= fill_monitor_1(info
, &info
[0].info1
,
8981 if (!W_ERROR_IS_OK(result
)) {
8985 result
= fill_monitor_1(info
, &info
[1].info1
,
8987 if (!W_ERROR_IS_OK(result
)) {
8992 if (!W_ERROR_IS_OK(result
)) {
9003 /****************************************************************************
9004 enumprintmonitors level 2.
9005 ****************************************************************************/
9007 static WERROR
enumprintmonitors_level_2(TALLOC_CTX
*mem_ctx
,
9008 union spoolss_MonitorInfo
**info_p
,
9011 union spoolss_MonitorInfo
*info
;
9012 WERROR result
= WERR_OK
;
9014 info
= talloc_array(mem_ctx
, union spoolss_MonitorInfo
, 2);
9015 W_ERROR_HAVE_NO_MEMORY(info
);
9019 result
= fill_monitor_2(info
, &info
[0].info2
,
9021 "Windows NT X86", /* FIXME */
9023 if (!W_ERROR_IS_OK(result
)) {
9027 result
= fill_monitor_2(info
, &info
[1].info2
,
9029 "Windows NT X86", /* FIXME */
9031 if (!W_ERROR_IS_OK(result
)) {
9036 if (!W_ERROR_IS_OK(result
)) {
9047 /****************************************************************
9048 _spoolss_EnumMonitors
9049 ****************************************************************/
9051 WERROR
_spoolss_EnumMonitors(struct pipes_struct
*p
,
9052 struct spoolss_EnumMonitors
*r
)
9056 /* that's an [in out] buffer */
9058 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9059 return WERR_INVALID_PARAM
;
9062 DEBUG(5,("_spoolss_EnumMonitors\n"));
9065 * Enumerate the print monitors ...
9067 * Just reply with "Local Port", to keep NT happy
9068 * and I can use my nice printer checker.
9073 *r
->out
.info
= NULL
;
9075 switch (r
->in
.level
) {
9077 result
= enumprintmonitors_level_1(p
->mem_ctx
, r
->out
.info
,
9081 result
= enumprintmonitors_level_2(p
->mem_ctx
, r
->out
.info
,
9085 return WERR_UNKNOWN_LEVEL
;
9088 if (!W_ERROR_IS_OK(result
)) {
9092 *r
->out
.needed
= SPOOLSS_BUFFER_UNION_ARRAY(p
->mem_ctx
,
9093 spoolss_EnumMonitors
,
9094 *r
->out
.info
, r
->in
.level
,
9096 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9097 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, 0);
9099 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9102 /****************************************************************************
9103 ****************************************************************************/
9105 static WERROR
getjob_level_1(TALLOC_CTX
*mem_ctx
,
9106 const print_queue_struct
*queue
,
9107 int count
, int snum
,
9108 struct spoolss_PrinterInfo2
*pinfo2
,
9110 struct spoolss_JobInfo1
*r
)
9115 for (i
=0; i
<count
; i
++) {
9116 if (queue
[i
].job
== (int)jobid
) {
9122 if (found
== false) {
9123 /* NT treats not found as bad param... yet another bad choice */
9124 return WERR_INVALID_PARAM
;
9127 return fill_job_info1(mem_ctx
,
9135 /****************************************************************************
9136 ****************************************************************************/
9138 static WERROR
getjob_level_2(TALLOC_CTX
*mem_ctx
,
9139 const print_queue_struct
*queue
,
9140 int count
, int snum
,
9141 struct spoolss_PrinterInfo2
*pinfo2
,
9143 struct spoolss_JobInfo2
*r
)
9147 struct spoolss_DeviceMode
*devmode
;
9150 for (i
=0; i
<count
; i
++) {
9151 if (queue
[i
].job
== (int)jobid
) {
9157 if (found
== false) {
9158 /* NT treats not found as bad param... yet another bad
9160 return WERR_INVALID_PARAM
;
9164 * if the print job does not have a DEVMODE associated with it,
9165 * just use the one for the printer. A NULL devicemode is not
9166 * a failure condition
9169 devmode
= print_job_devmode(lp_const_servicename(snum
), jobid
);
9171 result
= spoolss_create_default_devmode(mem_ctx
,
9172 pinfo2
->printername
,
9174 if (!W_ERROR_IS_OK(result
)) {
9175 DEBUG(3, ("Can't proceed w/o a devmode!"));
9180 return fill_job_info2(mem_ctx
,
9189 /****************************************************************
9191 ****************************************************************/
9193 WERROR
_spoolss_GetJob(struct pipes_struct
*p
,
9194 struct spoolss_GetJob
*r
)
9196 WERROR result
= WERR_OK
;
9197 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
9200 print_queue_struct
*queue
= NULL
;
9201 print_status_struct prt_status
;
9203 /* that's an [in out] buffer */
9205 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9206 return WERR_INVALID_PARAM
;
9209 DEBUG(5,("_spoolss_GetJob\n"));
9213 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9217 result
= winreg_get_printer_internal(p
->mem_ctx
,
9218 get_session_info_system(),
9220 lp_const_servicename(snum
),
9222 if (!W_ERROR_IS_OK(result
)) {
9226 count
= print_queue_status(p
->msg_ctx
, snum
, &queue
, &prt_status
);
9228 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9229 count
, prt_status
.status
, prt_status
.message
));
9231 switch (r
->in
.level
) {
9233 result
= getjob_level_1(p
->mem_ctx
,
9234 queue
, count
, snum
, pinfo2
,
9235 r
->in
.job_id
, &r
->out
.info
->info1
);
9238 result
= getjob_level_2(p
->mem_ctx
,
9239 queue
, count
, snum
, pinfo2
,
9240 r
->in
.job_id
, &r
->out
.info
->info2
);
9243 result
= WERR_UNKNOWN_LEVEL
;
9248 TALLOC_FREE(pinfo2
);
9250 if (!W_ERROR_IS_OK(result
)) {
9251 TALLOC_FREE(r
->out
.info
);
9255 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_JobInfo
, r
->out
.info
,
9257 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9259 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9262 /****************************************************************
9263 _spoolss_GetPrinterDataEx
9264 ****************************************************************/
9266 WERROR
_spoolss_GetPrinterDataEx(struct pipes_struct
*p
,
9267 struct spoolss_GetPrinterDataEx
*r
)
9270 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9271 const char *printer
;
9273 WERROR result
= WERR_OK
;
9275 enum winreg_Type val_type
= REG_NONE
;
9276 uint8_t *val_data
= NULL
;
9277 uint32_t val_size
= 0;
9278 struct dcerpc_binding_handle
*b
;
9279 TALLOC_CTX
*tmp_ctx
;
9281 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9283 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9284 r
->in
.key_name
, r
->in
.value_name
));
9286 /* in case of problem, return some default values */
9289 *r
->out
.type
= REG_NONE
;
9291 tmp_ctx
= talloc_new(p
->mem_ctx
);
9297 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9298 OUR_HANDLE(r
->in
.handle
)));
9299 result
= WERR_BADFID
;
9303 /* check to see if the keyname is valid */
9304 if (!strlen(r
->in
.key_name
)) {
9305 result
= WERR_INVALID_PARAM
;
9309 /* Is the handle to a printer or to the server? */
9311 if (Printer
->printer_type
== SPLHND_SERVER
) {
9313 union spoolss_PrinterData data
;
9315 result
= getprinterdata_printer_server(tmp_ctx
,
9319 if (!W_ERROR_IS_OK(result
)) {
9323 result
= push_spoolss_PrinterData(tmp_ctx
, &blob
,
9324 *r
->out
.type
, &data
);
9325 if (!W_ERROR_IS_OK(result
)) {
9329 *r
->out
.needed
= blob
.length
;
9331 if (r
->in
.offered
>= *r
->out
.needed
) {
9332 memcpy(r
->out
.data
, blob
.data
, blob
.length
);
9339 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9340 result
= WERR_BADFID
;
9343 printer
= lp_const_servicename(snum
);
9345 result
= winreg_printer_binding_handle(tmp_ctx
,
9346 get_session_info_system(),
9349 if (!W_ERROR_IS_OK(result
)) {
9353 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9354 if (strequal(r
->in
.key_name
, SPOOL_PRINTERDATA_KEY
) &&
9355 strequal(r
->in
.value_name
, "ChangeId")) {
9356 *r
->out
.type
= REG_DWORD
;
9358 if (r
->in
.offered
>= *r
->out
.needed
) {
9359 uint32_t changeid
= 0;
9361 result
= winreg_printer_get_changeid(tmp_ctx
, b
,
9364 if (!W_ERROR_IS_OK(result
)) {
9368 SIVAL(r
->out
.data
, 0, changeid
);
9374 result
= winreg_get_printer_dataex(tmp_ctx
, b
,
9381 if (!W_ERROR_IS_OK(result
)) {
9385 *r
->out
.needed
= val_size
;
9386 *r
->out
.type
= val_type
;
9388 if (r
->in
.offered
>= *r
->out
.needed
) {
9389 memcpy(r
->out
.data
, val_data
, val_size
);
9393 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9395 if (W_ERROR_IS_OK(result
)) {
9396 result
= SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9399 talloc_free(tmp_ctx
);
9403 /****************************************************************
9404 _spoolss_SetPrinterDataEx
9405 ****************************************************************/
9407 WERROR
_spoolss_SetPrinterDataEx(struct pipes_struct
*p
,
9408 struct spoolss_SetPrinterDataEx
*r
)
9410 struct spoolss_PrinterInfo2
*pinfo2
= NULL
;
9412 WERROR result
= WERR_OK
;
9413 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9415 struct dcerpc_binding_handle
*b
;
9416 TALLOC_CTX
*tmp_ctx
;
9418 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9420 /* From MSDN documentation of SetPrinterDataEx: pass request to
9421 SetPrinterData if key is "PrinterDriverData" */
9424 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9425 OUR_HANDLE(r
->in
.handle
)));
9429 if (Printer
->printer_type
== SPLHND_SERVER
) {
9430 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9431 "Not implemented for server handles yet\n"));
9432 return WERR_INVALID_PARAM
;
9435 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9440 * Access check : NT returns "access denied" if you make a
9441 * SetPrinterData call without the necessary privildge.
9442 * we were originally returning OK if nothing changed
9443 * which made Win2k issue **a lot** of SetPrinterData
9444 * when connecting to a printer --jerry
9447 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9448 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9449 "change denied by handle access permissions\n"));
9450 return WERR_ACCESS_DENIED
;
9453 tmp_ctx
= talloc_new(p
->mem_ctx
);
9458 result
= winreg_printer_binding_handle(tmp_ctx
,
9459 get_session_info_system(),
9462 if (!W_ERROR_IS_OK(result
)) {
9466 result
= winreg_get_printer(tmp_ctx
, b
,
9467 lp_servicename(snum
),
9469 if (!W_ERROR_IS_OK(result
)) {
9473 /* check for OID in valuename */
9475 oid_string
= strchr(r
->in
.value_name
, ',');
9481 /* save the registry data */
9483 result
= winreg_set_printer_dataex(tmp_ctx
, b
,
9491 if (W_ERROR_IS_OK(result
)) {
9492 /* save the OID if one was specified */
9494 char *str
= talloc_asprintf(tmp_ctx
, "%s\\%s",
9495 r
->in
.key_name
, SPOOL_OID_KEY
);
9497 result
= WERR_NOMEM
;
9502 * I'm not checking the status here on purpose. Don't know
9503 * if this is right, but I'm returning the status from the
9504 * previous set_printer_dataex() call. I have no idea if
9505 * this is right. --jerry
9507 winreg_set_printer_dataex(tmp_ctx
, b
,
9512 (uint8_t *) oid_string
,
9513 strlen(oid_string
) + 1);
9516 result
= winreg_printer_update_changeid(tmp_ctx
, b
,
9517 lp_const_servicename(snum
));
9522 talloc_free(tmp_ctx
);
9526 /****************************************************************
9527 _spoolss_DeletePrinterDataEx
9528 ****************************************************************/
9530 WERROR
_spoolss_DeletePrinterDataEx(struct pipes_struct
*p
,
9531 struct spoolss_DeletePrinterDataEx
*r
)
9533 const char *printer
;
9535 WERROR status
= WERR_OK
;
9536 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9538 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9541 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9542 "Invalid handle (%s:%u:%u).\n",
9543 OUR_HANDLE(r
->in
.handle
)));
9547 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9548 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9549 "printer properties change denied by handle\n"));
9550 return WERR_ACCESS_DENIED
;
9553 if (!r
->in
.value_name
|| !r
->in
.key_name
) {
9557 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9560 printer
= lp_const_servicename(snum
);
9562 status
= winreg_delete_printer_dataex_internal(p
->mem_ctx
,
9563 get_session_info_system(),
9568 if (W_ERROR_IS_OK(status
)) {
9569 status
= winreg_printer_update_changeid_internal(p
->mem_ctx
,
9570 get_session_info_system(),
9578 /****************************************************************
9579 _spoolss_EnumPrinterKey
9580 ****************************************************************/
9582 WERROR
_spoolss_EnumPrinterKey(struct pipes_struct
*p
,
9583 struct spoolss_EnumPrinterKey
*r
)
9586 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9588 WERROR result
= WERR_BADFILE
;
9589 const char **array
= NULL
;
9592 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9595 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9596 OUR_HANDLE(r
->in
.handle
)));
9600 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9604 result
= winreg_enum_printer_key_internal(p
->mem_ctx
,
9605 get_session_info_system(),
9607 lp_const_servicename(snum
),
9611 if (!W_ERROR_IS_OK(result
)) {
9615 if (!push_reg_multi_sz(p
->mem_ctx
, &blob
, array
)) {
9616 result
= WERR_NOMEM
;
9620 *r
->out
._ndr_size
= r
->in
.offered
/ 2;
9621 *r
->out
.needed
= blob
.length
;
9623 if (r
->in
.offered
< *r
->out
.needed
) {
9624 result
= WERR_MORE_DATA
;
9627 r
->out
.key_buffer
->string_array
= array
;
9631 if (!W_ERROR_IS_OK(result
)) {
9633 if (!W_ERROR_EQUAL(result
, WERR_MORE_DATA
)) {
9641 /****************************************************************
9642 _spoolss_DeletePrinterKey
9643 ****************************************************************/
9645 WERROR
_spoolss_DeletePrinterKey(struct pipes_struct
*p
,
9646 struct spoolss_DeletePrinterKey
*r
)
9648 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9651 const char *printer
;
9652 struct dcerpc_binding_handle
*b
;
9653 TALLOC_CTX
*tmp_ctx
;
9655 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9658 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9659 OUR_HANDLE(r
->in
.handle
)));
9663 /* if keyname == NULL, return error */
9664 if ( !r
->in
.key_name
)
9665 return WERR_INVALID_PARAM
;
9667 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9671 if (Printer
->access_granted
!= PRINTER_ACCESS_ADMINISTER
) {
9672 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9673 "printer properties change denied by handle\n"));
9674 return WERR_ACCESS_DENIED
;
9677 printer
= lp_const_servicename(snum
);
9679 tmp_ctx
= talloc_new(p
->mem_ctx
);
9684 status
= winreg_printer_binding_handle(tmp_ctx
,
9685 get_session_info_system(),
9688 if (!W_ERROR_IS_OK(status
)) {
9692 /* delete the key and all subkeys */
9693 status
= winreg_delete_printer_key(tmp_ctx
, b
,
9696 if (W_ERROR_IS_OK(status
)) {
9697 status
= winreg_printer_update_changeid(tmp_ctx
, b
,
9702 talloc_free(tmp_ctx
);
9706 /****************************************************************
9707 _spoolss_EnumPrinterDataEx
9708 ****************************************************************/
9710 WERROR
_spoolss_EnumPrinterDataEx(struct pipes_struct
*p
,
9711 struct spoolss_EnumPrinterDataEx
*r
)
9714 struct spoolss_PrinterEnumValues
*info
= NULL
;
9715 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
9719 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9723 *r
->out
.info
= NULL
;
9726 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9727 OUR_HANDLE(r
->in
.handle
)));
9732 * first check for a keyname of NULL or "". Win2k seems to send
9733 * this a lot and we should send back WERR_INVALID_PARAM
9734 * no need to spend time looking up the printer in this case.
9738 if (!strlen(r
->in
.key_name
)) {
9739 result
= WERR_INVALID_PARAM
;
9743 if (!get_printer_snum(p
, r
->in
.handle
, &snum
, NULL
)) {
9747 /* now look for a match on the key name */
9748 result
= winreg_enum_printer_dataex_internal(p
->mem_ctx
,
9749 get_session_info_system(),
9751 lp_const_servicename(snum
),
9755 if (!W_ERROR_IS_OK(result
)) {
9759 #if 0 /* FIXME - gd */
9760 /* housekeeping information in the reply */
9762 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9763 * the hand marshalled container size is a multiple
9764 * of 4 bytes for RPC alignment.
9768 needed
+= 4-(needed
% 4);
9771 *r
->out
.count
= count
;
9772 *r
->out
.info
= info
;
9775 if (!W_ERROR_IS_OK(result
)) {
9779 *r
->out
.needed
= SPOOLSS_BUFFER_ARRAY(p
->mem_ctx
,
9780 spoolss_EnumPrinterDataEx
,
9783 *r
->out
.info
= SPOOLSS_BUFFER_OK(*r
->out
.info
, NULL
);
9784 *r
->out
.count
= SPOOLSS_BUFFER_OK(*r
->out
.count
, *r
->out
.count
);
9786 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_MORE_DATA
);
9789 /****************************************************************************
9790 ****************************************************************************/
9792 static WERROR
getprintprocessordirectory_level_1(TALLOC_CTX
*mem_ctx
,
9793 const char *servername
,
9794 const char *environment
,
9795 struct spoolss_PrintProcessorDirectoryInfo1
*r
)
9800 werr
= compose_spoolss_server_path(mem_ctx
,
9803 SPOOLSS_PRTPROCS_PATH
,
9805 if (!W_ERROR_IS_OK(werr
)) {
9809 DEBUG(4,("print processor directory: [%s]\n", path
));
9811 r
->directory_name
= path
;
9816 /****************************************************************
9817 _spoolss_GetPrintProcessorDirectory
9818 ****************************************************************/
9820 WERROR
_spoolss_GetPrintProcessorDirectory(struct pipes_struct
*p
,
9821 struct spoolss_GetPrintProcessorDirectory
*r
)
9824 char *prnproc_share
= NULL
;
9825 bool prnproc_share_exists
= false;
9828 /* that's an [in out] buffer */
9830 if (!r
->in
.buffer
&& (r
->in
.offered
!= 0)) {
9831 return WERR_INVALID_PARAM
;
9834 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9839 /* r->in.level is ignored */
9841 /* We always should reply with a local print processor directory so that
9842 * users are not forced to have a [prnproc$] share on the Samba spoolss
9843 * server, if users decide to do so, lets announce it though - Guenther */
9845 snum
= find_service(talloc_tos(), "prnproc$", &prnproc_share
);
9846 if (!prnproc_share
) {
9850 prnproc_share_exists
= true;
9853 result
= getprintprocessordirectory_level_1(p
->mem_ctx
,
9854 prnproc_share_exists
? r
->in
.server
: NULL
,
9856 &r
->out
.info
->info1
);
9857 if (!W_ERROR_IS_OK(result
)) {
9858 TALLOC_FREE(r
->out
.info
);
9862 *r
->out
.needed
= SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo
,
9863 r
->out
.info
, r
->in
.level
);
9864 r
->out
.info
= SPOOLSS_BUFFER_OK(r
->out
.info
, NULL
);
9866 return SPOOLSS_BUFFER_OK(WERR_OK
, WERR_INSUFFICIENT_BUFFER
);
9869 /*******************************************************************
9870 ********************************************************************/
9872 static bool push_monitorui_buf(TALLOC_CTX
*mem_ctx
, DATA_BLOB
*buf
,
9873 const char *dllname
)
9875 enum ndr_err_code ndr_err
;
9876 struct spoolss_MonitorUi ui
;
9878 ui
.dll_name
= dllname
;
9880 ndr_err
= ndr_push_struct_blob(buf
, mem_ctx
, &ui
,
9881 (ndr_push_flags_fn_t
)ndr_push_spoolss_MonitorUi
);
9882 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9883 NDR_PRINT_DEBUG(spoolss_MonitorUi
, &ui
);
9885 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9888 /*******************************************************************
9889 Streams the monitor UI DLL name in UNICODE
9890 *******************************************************************/
9892 static WERROR
xcvtcp_monitorui(TALLOC_CTX
*mem_ctx
,
9893 struct security_token
*token
, DATA_BLOB
*in
,
9894 DATA_BLOB
*out
, uint32_t *needed
)
9896 const char *dllname
= "tcpmonui.dll";
9898 *needed
= (strlen(dllname
)+1) * 2;
9900 if (out
->length
< *needed
) {
9901 return WERR_INSUFFICIENT_BUFFER
;
9904 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
9911 /*******************************************************************
9912 ********************************************************************/
9914 static bool pull_port_data_1(TALLOC_CTX
*mem_ctx
,
9915 struct spoolss_PortData1
*port1
,
9916 const DATA_BLOB
*buf
)
9918 enum ndr_err_code ndr_err
;
9919 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port1
,
9920 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData1
);
9921 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9922 NDR_PRINT_DEBUG(spoolss_PortData1
, port1
);
9924 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9927 /*******************************************************************
9928 ********************************************************************/
9930 static bool pull_port_data_2(TALLOC_CTX
*mem_ctx
,
9931 struct spoolss_PortData2
*port2
,
9932 const DATA_BLOB
*buf
)
9934 enum ndr_err_code ndr_err
;
9935 ndr_err
= ndr_pull_struct_blob(buf
, mem_ctx
, port2
,
9936 (ndr_pull_flags_fn_t
)ndr_pull_spoolss_PortData2
);
9937 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err
) && (DEBUGLEVEL
>= 10)) {
9938 NDR_PRINT_DEBUG(spoolss_PortData2
, port2
);
9940 return NDR_ERR_CODE_IS_SUCCESS(ndr_err
);
9943 /*******************************************************************
9944 Create a new TCP/IP port
9945 *******************************************************************/
9947 static WERROR
xcvtcp_addport(TALLOC_CTX
*mem_ctx
,
9948 struct security_token
*token
, DATA_BLOB
*in
,
9949 DATA_BLOB
*out
, uint32_t *needed
)
9951 struct spoolss_PortData1 port1
;
9952 struct spoolss_PortData2 port2
;
9953 char *device_uri
= NULL
;
9956 const char *portname
;
9957 const char *hostaddress
;
9959 uint32_t port_number
;
9962 /* peek for spoolss_PortData version */
9964 if (!in
|| (in
->length
< (128 + 4))) {
9965 return WERR_GENERAL_FAILURE
;
9968 version
= IVAL(in
->data
, 128);
9974 if (!pull_port_data_1(mem_ctx
, &port1
, in
)) {
9978 portname
= port1
.portname
;
9979 hostaddress
= port1
.hostaddress
;
9980 queue
= port1
.queue
;
9981 protocol
= port1
.protocol
;
9982 port_number
= port1
.port_number
;
9988 if (!pull_port_data_2(mem_ctx
, &port2
, in
)) {
9992 portname
= port2
.portname
;
9993 hostaddress
= port2
.hostaddress
;
9994 queue
= port2
.queue
;
9995 protocol
= port2
.protocol
;
9996 port_number
= port2
.port_number
;
10000 DEBUG(1,("xcvtcp_addport: "
10001 "unknown version of port_data: %d\n", version
));
10002 return WERR_UNKNOWN_PORT
;
10005 /* create the device URI and call the add_port_hook() */
10007 switch (protocol
) {
10008 case PROTOCOL_RAWTCP_TYPE
:
10009 device_uri
= talloc_asprintf(mem_ctx
,
10010 "socket://%s:%d/", hostaddress
,
10014 case PROTOCOL_LPR_TYPE
:
10015 device_uri
= talloc_asprintf(mem_ctx
,
10016 "lpr://%s/%s", hostaddress
, queue
);
10020 return WERR_UNKNOWN_PORT
;
10027 return add_port_hook(mem_ctx
, token
, portname
, device_uri
);
10030 /*******************************************************************
10031 *******************************************************************/
10033 struct xcv_api_table xcvtcp_cmds
[] = {
10034 { "MonitorUI", xcvtcp_monitorui
},
10035 { "AddPort", xcvtcp_addport
},
10039 static WERROR
process_xcvtcp_command(TALLOC_CTX
*mem_ctx
,
10040 struct security_token
*token
, const char *command
,
10047 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command
));
10049 for ( i
=0; xcvtcp_cmds
[i
].name
; i
++ ) {
10050 if ( strcmp( command
, xcvtcp_cmds
[i
].name
) == 0 )
10051 return xcvtcp_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
10054 return WERR_BADFUNC
;
10057 /*******************************************************************
10058 *******************************************************************/
10059 #if 0 /* don't support management using the "Local Port" monitor */
10061 static WERROR
xcvlocal_monitorui(TALLOC_CTX
*mem_ctx
,
10062 struct security_token
*token
, DATA_BLOB
*in
,
10063 DATA_BLOB
*out
, uint32_t *needed
)
10065 const char *dllname
= "localui.dll";
10067 *needed
= (strlen(dllname
)+1) * 2;
10069 if (out
->length
< *needed
) {
10070 return WERR_INSUFFICIENT_BUFFER
;
10073 if (!push_monitorui_buf(mem_ctx
, out
, dllname
)) {
10080 /*******************************************************************
10081 *******************************************************************/
10083 struct xcv_api_table xcvlocal_cmds
[] = {
10084 { "MonitorUI", xcvlocal_monitorui
},
10088 struct xcv_api_table xcvlocal_cmds
[] = {
10095 /*******************************************************************
10096 *******************************************************************/
10098 static WERROR
process_xcvlocal_command(TALLOC_CTX
*mem_ctx
,
10099 struct security_token
*token
, const char *command
,
10100 DATA_BLOB
*inbuf
, DATA_BLOB
*outbuf
,
10105 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command
));
10107 for ( i
=0; xcvlocal_cmds
[i
].name
; i
++ ) {
10108 if ( strcmp( command
, xcvlocal_cmds
[i
].name
) == 0 )
10109 return xcvlocal_cmds
[i
].fn(mem_ctx
, token
, inbuf
, outbuf
, needed
);
10111 return WERR_BADFUNC
;
10114 /****************************************************************
10116 ****************************************************************/
10118 WERROR
_spoolss_XcvData(struct pipes_struct
*p
,
10119 struct spoolss_XcvData
*r
)
10121 struct printer_handle
*Printer
= find_printer_index_by_hnd(p
, r
->in
.handle
);
10122 DATA_BLOB out_data
= data_blob_null
;
10126 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10127 OUR_HANDLE(r
->in
.handle
)));
10128 return WERR_BADFID
;
10131 /* Has to be a handle to the TCP/IP port monitor */
10133 if ( !(Printer
->printer_type
& (SPLHND_PORTMON_LOCAL
|SPLHND_PORTMON_TCP
)) ) {
10134 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10135 return WERR_BADFID
;
10138 /* requires administrative access to the server */
10140 if ( !(Printer
->access_granted
& SERVER_ACCESS_ADMINISTER
) ) {
10141 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10142 return WERR_ACCESS_DENIED
;
10145 /* Allocate the outgoing buffer */
10147 if (r
->in
.out_data_size
) {
10148 out_data
= data_blob_talloc_zero(p
->mem_ctx
, r
->in
.out_data_size
);
10149 if (out_data
.data
== NULL
) {
10154 switch ( Printer
->printer_type
) {
10155 case SPLHND_PORTMON_TCP
:
10156 werror
= process_xcvtcp_command(p
->mem_ctx
,
10157 p
->session_info
->security_token
,
10158 r
->in
.function_name
,
10159 &r
->in
.in_data
, &out_data
,
10162 case SPLHND_PORTMON_LOCAL
:
10163 werror
= process_xcvlocal_command(p
->mem_ctx
,
10164 p
->session_info
->security_token
,
10165 r
->in
.function_name
,
10166 &r
->in
.in_data
, &out_data
,
10170 werror
= WERR_INVALID_PRINT_MONITOR
;
10173 if (!W_ERROR_IS_OK(werror
)) {
10177 *r
->out
.status_code
= 0;
10179 if (r
->out
.out_data
&& out_data
.data
&& r
->in
.out_data_size
&& out_data
.length
) {
10180 memcpy(r
->out
.out_data
, out_data
.data
,
10181 MIN(r
->in
.out_data_size
, out_data
.length
));
10187 /****************************************************************
10188 _spoolss_AddPrintProcessor
10189 ****************************************************************/
10191 WERROR
_spoolss_AddPrintProcessor(struct pipes_struct
*p
,
10192 struct spoolss_AddPrintProcessor
*r
)
10194 /* for now, just indicate success and ignore the add. We'll
10195 automatically set the winprint processor for printer
10196 entries later. Used to debug the LexMark Optra S 1855 PCL
10202 /****************************************************************
10204 ****************************************************************/
10206 WERROR
_spoolss_AddPort(struct pipes_struct
*p
,
10207 struct spoolss_AddPort
*r
)
10209 /* do what w2k3 does */
10211 return WERR_NOT_SUPPORTED
;
10214 /****************************************************************
10215 _spoolss_GetPrinterDriver
10216 ****************************************************************/
10218 WERROR
_spoolss_GetPrinterDriver(struct pipes_struct
*p
,
10219 struct spoolss_GetPrinterDriver
*r
)
10221 p
->rng_fault_state
= true;
10222 return WERR_NOT_SUPPORTED
;
10225 /****************************************************************
10226 _spoolss_ReadPrinter
10227 ****************************************************************/
10229 WERROR
_spoolss_ReadPrinter(struct pipes_struct
*p
,
10230 struct spoolss_ReadPrinter
*r
)
10232 p
->rng_fault_state
= true;
10233 return WERR_NOT_SUPPORTED
;
10236 /****************************************************************
10237 _spoolss_WaitForPrinterChange
10238 ****************************************************************/
10240 WERROR
_spoolss_WaitForPrinterChange(struct pipes_struct
*p
,
10241 struct spoolss_WaitForPrinterChange
*r
)
10243 p
->rng_fault_state
= true;
10244 return WERR_NOT_SUPPORTED
;
10247 /****************************************************************
10248 _spoolss_ConfigurePort
10249 ****************************************************************/
10251 WERROR
_spoolss_ConfigurePort(struct pipes_struct
*p
,
10252 struct spoolss_ConfigurePort
*r
)
10254 p
->rng_fault_state
= true;
10255 return WERR_NOT_SUPPORTED
;
10258 /****************************************************************
10259 _spoolss_DeletePort
10260 ****************************************************************/
10262 WERROR
_spoolss_DeletePort(struct pipes_struct
*p
,
10263 struct spoolss_DeletePort
*r
)
10265 p
->rng_fault_state
= true;
10266 return WERR_NOT_SUPPORTED
;
10269 /****************************************************************
10270 _spoolss_CreatePrinterIC
10271 ****************************************************************/
10273 WERROR
_spoolss_CreatePrinterIC(struct pipes_struct
*p
,
10274 struct spoolss_CreatePrinterIC
*r
)
10276 p
->rng_fault_state
= true;
10277 return WERR_NOT_SUPPORTED
;
10280 /****************************************************************
10281 _spoolss_PlayGDIScriptOnPrinterIC
10282 ****************************************************************/
10284 WERROR
_spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct
*p
,
10285 struct spoolss_PlayGDIScriptOnPrinterIC
*r
)
10287 p
->rng_fault_state
= true;
10288 return WERR_NOT_SUPPORTED
;
10291 /****************************************************************
10292 _spoolss_DeletePrinterIC
10293 ****************************************************************/
10295 WERROR
_spoolss_DeletePrinterIC(struct pipes_struct
*p
,
10296 struct spoolss_DeletePrinterIC
*r
)
10298 p
->rng_fault_state
= true;
10299 return WERR_NOT_SUPPORTED
;
10302 /****************************************************************
10303 _spoolss_AddPrinterConnection
10304 ****************************************************************/
10306 WERROR
_spoolss_AddPrinterConnection(struct pipes_struct
*p
,
10307 struct spoolss_AddPrinterConnection
*r
)
10309 p
->rng_fault_state
= true;
10310 return WERR_NOT_SUPPORTED
;
10313 /****************************************************************
10314 _spoolss_DeletePrinterConnection
10315 ****************************************************************/
10317 WERROR
_spoolss_DeletePrinterConnection(struct pipes_struct
*p
,
10318 struct spoolss_DeletePrinterConnection
*r
)
10320 p
->rng_fault_state
= true;
10321 return WERR_NOT_SUPPORTED
;
10324 /****************************************************************
10325 _spoolss_PrinterMessageBox
10326 ****************************************************************/
10328 WERROR
_spoolss_PrinterMessageBox(struct pipes_struct
*p
,
10329 struct spoolss_PrinterMessageBox
*r
)
10331 p
->rng_fault_state
= true;
10332 return WERR_NOT_SUPPORTED
;
10335 /****************************************************************
10336 _spoolss_AddMonitor
10337 ****************************************************************/
10339 WERROR
_spoolss_AddMonitor(struct pipes_struct
*p
,
10340 struct spoolss_AddMonitor
*r
)
10342 p
->rng_fault_state
= true;
10343 return WERR_NOT_SUPPORTED
;
10346 /****************************************************************
10347 _spoolss_DeleteMonitor
10348 ****************************************************************/
10350 WERROR
_spoolss_DeleteMonitor(struct pipes_struct
*p
,
10351 struct spoolss_DeleteMonitor
*r
)
10353 p
->rng_fault_state
= true;
10354 return WERR_NOT_SUPPORTED
;
10357 /****************************************************************
10358 _spoolss_DeletePrintProcessor
10359 ****************************************************************/
10361 WERROR
_spoolss_DeletePrintProcessor(struct pipes_struct
*p
,
10362 struct spoolss_DeletePrintProcessor
*r
)
10364 p
->rng_fault_state
= true;
10365 return WERR_NOT_SUPPORTED
;
10368 /****************************************************************
10369 _spoolss_AddPrintProvidor
10370 ****************************************************************/
10372 WERROR
_spoolss_AddPrintProvidor(struct pipes_struct
*p
,
10373 struct spoolss_AddPrintProvidor
*r
)
10375 p
->rng_fault_state
= true;
10376 return WERR_NOT_SUPPORTED
;
10379 /****************************************************************
10380 _spoolss_DeletePrintProvidor
10381 ****************************************************************/
10383 WERROR
_spoolss_DeletePrintProvidor(struct pipes_struct
*p
,
10384 struct spoolss_DeletePrintProvidor
*r
)
10386 p
->rng_fault_state
= true;
10387 return WERR_NOT_SUPPORTED
;
10390 /****************************************************************
10391 _spoolss_FindFirstPrinterChangeNotification
10392 ****************************************************************/
10394 WERROR
_spoolss_FindFirstPrinterChangeNotification(struct pipes_struct
*p
,
10395 struct spoolss_FindFirstPrinterChangeNotification
*r
)
10397 p
->rng_fault_state
= true;
10398 return WERR_NOT_SUPPORTED
;
10401 /****************************************************************
10402 _spoolss_FindNextPrinterChangeNotification
10403 ****************************************************************/
10405 WERROR
_spoolss_FindNextPrinterChangeNotification(struct pipes_struct
*p
,
10406 struct spoolss_FindNextPrinterChangeNotification
*r
)
10408 p
->rng_fault_state
= true;
10409 return WERR_NOT_SUPPORTED
;
10412 /****************************************************************
10413 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10414 ****************************************************************/
10416 WERROR
_spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct
*p
,
10417 struct spoolss_RouterFindFirstPrinterChangeNotificationOld
*r
)
10419 p
->rng_fault_state
= true;
10420 return WERR_NOT_SUPPORTED
;
10423 /****************************************************************
10424 _spoolss_ReplyOpenPrinter
10425 ****************************************************************/
10427 WERROR
_spoolss_ReplyOpenPrinter(struct pipes_struct
*p
,
10428 struct spoolss_ReplyOpenPrinter
*r
)
10430 p
->rng_fault_state
= true;
10431 return WERR_NOT_SUPPORTED
;
10434 /****************************************************************
10435 _spoolss_RouterReplyPrinter
10436 ****************************************************************/
10438 WERROR
_spoolss_RouterReplyPrinter(struct pipes_struct
*p
,
10439 struct spoolss_RouterReplyPrinter
*r
)
10441 p
->rng_fault_state
= true;
10442 return WERR_NOT_SUPPORTED
;
10445 /****************************************************************
10446 _spoolss_ReplyClosePrinter
10447 ****************************************************************/
10449 WERROR
_spoolss_ReplyClosePrinter(struct pipes_struct
*p
,
10450 struct spoolss_ReplyClosePrinter
*r
)
10452 p
->rng_fault_state
= true;
10453 return WERR_NOT_SUPPORTED
;
10456 /****************************************************************
10458 ****************************************************************/
10460 WERROR
_spoolss_AddPortEx(struct pipes_struct
*p
,
10461 struct spoolss_AddPortEx
*r
)
10463 p
->rng_fault_state
= true;
10464 return WERR_NOT_SUPPORTED
;
10467 /****************************************************************
10468 _spoolss_RouterFindFirstPrinterChangeNotification
10469 ****************************************************************/
10471 WERROR
_spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct
*p
,
10472 struct spoolss_RouterFindFirstPrinterChangeNotification
*r
)
10474 p
->rng_fault_state
= true;
10475 return WERR_NOT_SUPPORTED
;
10478 /****************************************************************
10479 _spoolss_SpoolerInit
10480 ****************************************************************/
10482 WERROR
_spoolss_SpoolerInit(struct pipes_struct
*p
,
10483 struct spoolss_SpoolerInit
*r
)
10485 p
->rng_fault_state
= true;
10486 return WERR_NOT_SUPPORTED
;
10489 /****************************************************************
10490 _spoolss_ResetPrinterEx
10491 ****************************************************************/
10493 WERROR
_spoolss_ResetPrinterEx(struct pipes_struct
*p
,
10494 struct spoolss_ResetPrinterEx
*r
)
10496 p
->rng_fault_state
= true;
10497 return WERR_NOT_SUPPORTED
;
10500 /****************************************************************
10501 _spoolss_RouterReplyPrinterEx
10502 ****************************************************************/
10504 WERROR
_spoolss_RouterReplyPrinterEx(struct pipes_struct
*p
,
10505 struct spoolss_RouterReplyPrinterEx
*r
)
10507 p
->rng_fault_state
= true;
10508 return WERR_NOT_SUPPORTED
;
10511 /****************************************************************
10513 ****************************************************************/
10515 WERROR
_spoolss_44(struct pipes_struct
*p
,
10516 struct spoolss_44
*r
)
10518 p
->rng_fault_state
= true;
10519 return WERR_NOT_SUPPORTED
;
10522 /****************************************************************
10524 ****************************************************************/
10526 WERROR
_spoolss_SetPort(struct pipes_struct
*p
,
10527 struct spoolss_SetPort
*r
)
10529 p
->rng_fault_state
= true;
10530 return WERR_NOT_SUPPORTED
;
10533 /****************************************************************
10535 ****************************************************************/
10537 WERROR
_spoolss_4a(struct pipes_struct
*p
,
10538 struct spoolss_4a
*r
)
10540 p
->rng_fault_state
= true;
10541 return WERR_NOT_SUPPORTED
;
10544 /****************************************************************
10546 ****************************************************************/
10548 WERROR
_spoolss_4b(struct pipes_struct
*p
,
10549 struct spoolss_4b
*r
)
10551 p
->rng_fault_state
= true;
10552 return WERR_NOT_SUPPORTED
;
10555 /****************************************************************
10557 ****************************************************************/
10559 WERROR
_spoolss_4c(struct pipes_struct
*p
,
10560 struct spoolss_4c
*r
)
10562 p
->rng_fault_state
= true;
10563 return WERR_NOT_SUPPORTED
;
10566 /****************************************************************
10568 ****************************************************************/
10570 WERROR
_spoolss_53(struct pipes_struct
*p
,
10571 struct spoolss_53
*r
)
10573 p
->rng_fault_state
= true;
10574 return WERR_NOT_SUPPORTED
;
10577 /****************************************************************
10578 _spoolss_AddPerMachineConnection
10579 ****************************************************************/
10581 WERROR
_spoolss_AddPerMachineConnection(struct pipes_struct
*p
,
10582 struct spoolss_AddPerMachineConnection
*r
)
10584 p
->rng_fault_state
= true;
10585 return WERR_NOT_SUPPORTED
;
10588 /****************************************************************
10589 _spoolss_DeletePerMachineConnection
10590 ****************************************************************/
10592 WERROR
_spoolss_DeletePerMachineConnection(struct pipes_struct
*p
,
10593 struct spoolss_DeletePerMachineConnection
*r
)
10595 p
->rng_fault_state
= true;
10596 return WERR_NOT_SUPPORTED
;
10599 /****************************************************************
10600 _spoolss_EnumPerMachineConnections
10601 ****************************************************************/
10603 WERROR
_spoolss_EnumPerMachineConnections(struct pipes_struct
*p
,
10604 struct spoolss_EnumPerMachineConnections
*r
)
10606 p
->rng_fault_state
= true;
10607 return WERR_NOT_SUPPORTED
;
10610 /****************************************************************
10612 ****************************************************************/
10614 WERROR
_spoolss_5a(struct pipes_struct
*p
,
10615 struct spoolss_5a
*r
)
10617 p
->rng_fault_state
= true;
10618 return WERR_NOT_SUPPORTED
;
10621 /****************************************************************
10623 ****************************************************************/
10625 WERROR
_spoolss_5b(struct pipes_struct
*p
,
10626 struct spoolss_5b
*r
)
10628 p
->rng_fault_state
= true;
10629 return WERR_NOT_SUPPORTED
;
10632 /****************************************************************
10634 ****************************************************************/
10636 WERROR
_spoolss_5c(struct pipes_struct
*p
,
10637 struct spoolss_5c
*r
)
10639 p
->rng_fault_state
= true;
10640 return WERR_NOT_SUPPORTED
;
10643 /****************************************************************
10645 ****************************************************************/
10647 WERROR
_spoolss_5d(struct pipes_struct
*p
,
10648 struct spoolss_5d
*r
)
10650 p
->rng_fault_state
= true;
10651 return WERR_NOT_SUPPORTED
;
10654 /****************************************************************
10656 ****************************************************************/
10658 WERROR
_spoolss_5e(struct pipes_struct
*p
,
10659 struct spoolss_5e
*r
)
10661 p
->rng_fault_state
= true;
10662 return WERR_NOT_SUPPORTED
;
10665 /****************************************************************
10667 ****************************************************************/
10669 WERROR
_spoolss_5f(struct pipes_struct
*p
,
10670 struct spoolss_5f
*r
)
10672 p
->rng_fault_state
= true;
10673 return WERR_NOT_SUPPORTED
;
10676 /****************************************************************
10678 ****************************************************************/
10680 WERROR
_spoolss_60(struct pipes_struct
*p
,
10681 struct spoolss_60
*r
)
10683 p
->rng_fault_state
= true;
10684 return WERR_NOT_SUPPORTED
;
10687 /****************************************************************
10689 ****************************************************************/
10691 WERROR
_spoolss_61(struct pipes_struct
*p
,
10692 struct spoolss_61
*r
)
10694 p
->rng_fault_state
= true;
10695 return WERR_NOT_SUPPORTED
;
10698 /****************************************************************
10700 ****************************************************************/
10702 WERROR
_spoolss_62(struct pipes_struct
*p
,
10703 struct spoolss_62
*r
)
10705 p
->rng_fault_state
= true;
10706 return WERR_NOT_SUPPORTED
;
10709 /****************************************************************
10711 ****************************************************************/
10713 WERROR
_spoolss_63(struct pipes_struct
*p
,
10714 struct spoolss_63
*r
)
10716 p
->rng_fault_state
= true;
10717 return WERR_NOT_SUPPORTED
;
10720 /****************************************************************
10722 ****************************************************************/
10724 WERROR
_spoolss_64(struct pipes_struct
*p
,
10725 struct spoolss_64
*r
)
10727 p
->rng_fault_state
= true;
10728 return WERR_NOT_SUPPORTED
;
10731 /****************************************************************
10733 ****************************************************************/
10735 WERROR
_spoolss_65(struct pipes_struct
*p
,
10736 struct spoolss_65
*r
)
10738 p
->rng_fault_state
= true;
10739 return WERR_NOT_SUPPORTED
;
10742 /****************************************************************
10743 _spoolss_GetCorePrinterDrivers
10744 ****************************************************************/
10746 WERROR
_spoolss_GetCorePrinterDrivers(struct pipes_struct
*p
,
10747 struct spoolss_GetCorePrinterDrivers
*r
)
10749 p
->rng_fault_state
= true;
10750 return WERR_NOT_SUPPORTED
;
10753 /****************************************************************
10755 ****************************************************************/
10757 WERROR
_spoolss_67(struct pipes_struct
*p
,
10758 struct spoolss_67
*r
)
10760 p
->rng_fault_state
= true;
10761 return WERR_NOT_SUPPORTED
;
10764 /****************************************************************
10765 _spoolss_GetPrinterDriverPackagePath
10766 ****************************************************************/
10768 WERROR
_spoolss_GetPrinterDriverPackagePath(struct pipes_struct
*p
,
10769 struct spoolss_GetPrinterDriverPackagePath
*r
)
10771 p
->rng_fault_state
= true;
10772 return WERR_NOT_SUPPORTED
;
10775 /****************************************************************
10777 ****************************************************************/
10779 WERROR
_spoolss_69(struct pipes_struct
*p
,
10780 struct spoolss_69
*r
)
10782 p
->rng_fault_state
= true;
10783 return WERR_NOT_SUPPORTED
;
10786 /****************************************************************
10788 ****************************************************************/
10790 WERROR
_spoolss_6a(struct pipes_struct
*p
,
10791 struct spoolss_6a
*r
)
10793 p
->rng_fault_state
= true;
10794 return WERR_NOT_SUPPORTED
;
10797 /****************************************************************
10799 ****************************************************************/
10801 WERROR
_spoolss_6b(struct pipes_struct
*p
,
10802 struct spoolss_6b
*r
)
10804 p
->rng_fault_state
= true;
10805 return WERR_NOT_SUPPORTED
;
10808 /****************************************************************
10810 ****************************************************************/
10812 WERROR
_spoolss_6c(struct pipes_struct
*p
,
10813 struct spoolss_6c
*r
)
10815 p
->rng_fault_state
= true;
10816 return WERR_NOT_SUPPORTED
;
10819 /****************************************************************
10821 ****************************************************************/
10823 WERROR
_spoolss_6d(struct pipes_struct
*p
,
10824 struct spoolss_6d
*r
)
10826 p
->rng_fault_state
= true;
10827 return WERR_NOT_SUPPORTED
;