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. */
31 #include "lib/util/util_file.h"
32 #include "libsmb/namequery.h"
34 #include "nt_printing.h"
35 #include "srv_spoolss_util.h"
36 #include "librpc/gen_ndr/ndr_spoolss.h"
37 #include "librpc/gen_ndr/ndr_spoolss_scompat.h"
38 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
39 #include "rpc_client/init_spoolss.h"
40 #include "rpc_client/cli_pipe.h"
41 #include "../libcli/security/security.h"
42 #include "librpc/gen_ndr/ndr_security.h"
44 #include "include/printing.h"
46 #include "../librpc/gen_ndr/netlogon.h"
48 #include "printing/notify.h"
50 #include "../libcli/registry/util_reg.h"
51 #include "smbd/smbd.h"
52 #include "smbd/globals.h"
55 #include "rpc_server/spoolss/srv_spoolss_nt.h"
57 #include "libsmb/libsmb.h"
58 #include "printing/printer_list.h"
59 #include "../lib/tsocket/tsocket.h"
60 #include "rpc_client/cli_winreg_spoolss.h"
61 #include "../libcli/smb/smbXcli_base.h"
62 #include "rpc_server/spoolss/srv_spoolss_handle.h"
63 #include "lib/gencache.h"
64 #include "rpc_server/rpc_server.h"
65 #include "librpc/rpc/dcesrv_core.h"
66 #include "printing/nt_printing_migrate_internal.h"
67 #include "lib/util/string_wrappers.h"
68 #include "lib/global_contexts.h"
70 /* macros stolen from s4 spoolss server */
71 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
72 ((info)?ndr_size_##fn(info, level, 0):0)
74 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
75 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
77 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
78 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
80 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
83 #define DBGC_CLASS DBGC_RPC_SRV
85 #ifndef MAX_OPEN_PRINTER_EXS
86 #define MAX_OPEN_PRINTER_EXS 50
89 #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
90 #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
91 #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
92 #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
94 static struct printer_handle *printers_list;
96 struct printer_session_counter {
97 struct printer_session_counter *next;
98 struct printer_session_counter *prev;
104 static struct printer_session_counter *counter_list;
106 struct notify_back_channel {
107 struct notify_back_channel *prev, *next;
109 /* associated client */
110 struct sockaddr_storage client_address;
112 /* print notify back-channel pipe handle*/
113 struct rpc_pipe_client *cli_pipe;
114 struct cli_state *cli;
115 uint32_t active_connections;
118 static struct notify_back_channel *back_channels;
120 /* Map generic permissions to printer object specific permissions */
122 const struct standard_mapping printer_std_mapping = {
129 /* Map generic permissions to print server object specific permissions */
131 const struct standard_mapping printserver_std_mapping = {
138 /* API table for Xcv Monitor functions */
140 struct xcv_api_table {
142 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
145 static void prune_printername_cache(void);
147 /********************************************************************
148 * Canonicalize servername.
149 ********************************************************************/
151 static const char *canon_servername(const char *servername)
153 const char *pservername = servername;
155 if (servername == NULL) {
159 while (*pservername == '\\') {
165 /* translate between internal status numbers and NT status numbers */
166 static int nt_printj_status(int v)
172 return JOB_STATUS_PAUSED;
174 return JOB_STATUS_SPOOLING;
176 return JOB_STATUS_PRINTING;
178 return JOB_STATUS_ERROR;
180 return JOB_STATUS_DELETING;
182 return JOB_STATUS_OFFLINE;
184 return JOB_STATUS_PAPEROUT;
186 return JOB_STATUS_PRINTED;
188 return JOB_STATUS_DELETED;
190 return JOB_STATUS_BLOCKED_DEVQ;
191 case LPQ_USER_INTERVENTION:
192 return JOB_STATUS_USER_INTERVENTION;
197 static int nt_printq_status(int v)
201 return PRINTER_STATUS_PAUSED;
210 /***************************************************************************
211 Disconnect from the client
212 ****************************************************************************/
214 static void srv_spoolss_replycloseprinter(int snum,
215 struct printer_handle *prn_hnd)
221 * Tell the specific printing tdb we no longer want messages for this printer
222 * by deregistering our PID.
225 if (!print_notify_deregister_pid(snum)) {
226 DEBUG(0, ("Failed to register our pid for printer %s\n",
227 lp_const_servicename(snum)));
230 /* weird if the test succeeds !!! */
231 if (prn_hnd->notify.cli_chan == NULL ||
232 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
233 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
234 prn_hnd->notify.cli_chan->active_connections == 0) {
235 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
236 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
237 TALLOC_FREE(prn_hnd->notify.cli_chan);
241 status = dcerpc_spoolss_ReplyClosePrinter(
242 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
244 &prn_hnd->notify.cli_hnd,
246 if (!NT_STATUS_IS_OK(status)) {
247 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
249 result = ntstatus_to_werror(status);
250 } else if (!W_ERROR_IS_OK(result)) {
251 DEBUG(0, ("reply_close_printer failed [%s].\n",
252 win_errstr(result)));
255 /* if it's the last connection, deconnect the IPC$ share */
256 if (prn_hnd->notify.cli_chan->active_connections == 1) {
258 cli_shutdown(prn_hnd->notify.cli_chan->cli);
259 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
260 TALLOC_FREE(prn_hnd->notify.cli_chan);
262 if (prn_hnd->notify.msg_ctx != NULL) {
263 messaging_deregister(prn_hnd->notify.msg_ctx,
264 MSG_PRINTER_NOTIFY2, NULL);
268 if (prn_hnd->notify.cli_chan) {
269 prn_hnd->notify.cli_chan->active_connections--;
270 prn_hnd->notify.cli_chan = NULL;
274 /****************************************************************************
275 Functions to free a printer entry datastruct.
276 ****************************************************************************/
278 static int printer_entry_destructor(struct printer_handle *Printer)
280 if (Printer->notify.cli_chan != NULL &&
281 Printer->notify.cli_chan->active_connections > 0) {
284 switch(Printer->printer_type) {
286 srv_spoolss_replycloseprinter(snum, Printer);
290 snum = print_queue_snum(Printer->sharename);
292 srv_spoolss_replycloseprinter(snum, Printer);
300 Printer->notify.flags=0;
301 Printer->notify.options=0;
302 Printer->notify.localmachine[0]='\0';
303 Printer->notify.printerlocal=0;
304 TALLOC_FREE(Printer->notify.option);
305 TALLOC_FREE(Printer->devmode);
307 /* Remove from the internal list. */
308 DLIST_REMOVE(printers_list, Printer);
312 /****************************************************************************
313 find printer index by handle
314 ****************************************************************************/
316 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
317 struct policy_handle *hnd)
319 struct printer_handle *find_printer = NULL;
322 find_printer = find_policy_by_hnd(p,
325 struct printer_handle,
327 if (!NT_STATUS_IS_OK(status)) {
328 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: %s\n",
336 /****************************************************************************
337 Close printer index by handle.
338 ****************************************************************************/
340 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
342 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
345 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
350 close_policy_hnd(p, hnd);
355 /****************************************************************************
356 Delete a printer given a handle.
357 ****************************************************************************/
359 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
360 const char *sharename,
361 struct messaging_context *msg_ctx)
363 const struct loadparm_substitution *lp_sub =
364 loadparm_s3_global_substitution();
365 char *cmd = lp_deleteprinter_command(talloc_tos(), lp_sub);
366 char *command = NULL;
368 bool is_print_op = false;
370 /* can't fail if we don't try */
375 command = talloc_asprintf(ctx,
379 return WERR_NOT_ENOUGH_MEMORY;
382 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
384 DEBUG(10,("Running [%s]\n", command));
386 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
391 ret = smbrun(command, NULL, NULL);
393 /* Tell everyone we updated smb.conf. */
394 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
400 /********** END SePrintOperatorPrivlege BLOCK **********/
402 DEBUGADD(10,("returned [%d]\n", ret));
404 TALLOC_FREE(command);
407 return WERR_INVALID_HANDLE; /* What to return here? */
412 /****************************************************************************
413 Delete a printer given a handle.
414 ****************************************************************************/
416 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
418 struct dcesrv_call_state *dce_call = p->dce_call;
419 struct auth_session_info *session_info =
420 dcesrv_call_session_info(dce_call);
421 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
425 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
427 return WERR_INVALID_HANDLE;
431 * It turns out that Windows allows delete printer on a handle
432 * opened by an admin user, then used on a pipe handle created
433 * by an anonymous user..... but they're working on security.... riiight !
437 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
438 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
439 return WERR_ACCESS_DENIED;
442 /* this does not need a become root since the access check has been
443 done on the handle already */
445 result = winreg_delete_printer_key_internal(p->mem_ctx,
446 get_session_info_system(),
450 if (!W_ERROR_IS_OK(result)) {
451 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
452 return WERR_INVALID_HANDLE;
455 result = delete_printer_hook(p->mem_ctx, session_info->security_token,
456 Printer->sharename, p->msg_ctx);
457 if (!W_ERROR_IS_OK(result)) {
460 prune_printername_cache();
464 /****************************************************************************
465 Return the snum of a printer corresponding to an handle.
466 ****************************************************************************/
468 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
469 int *number, struct share_params **params)
471 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
474 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
479 switch (Printer->printer_type) {
481 DEBUG(4,("short name:%s\n", Printer->sharename));
482 *number = print_queue_snum(Printer->sharename);
483 return (*number != -1);
491 /****************************************************************************
492 Set printer handle type.
493 Check if it's \\server or \\server\printer
494 ****************************************************************************/
496 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
498 DEBUG(3,("Setting printer type=%s\n", handlename));
500 /* it's a print server */
501 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
502 DEBUGADD(4,("Printer is a print server\n"));
503 Printer->printer_type = SPLHND_SERVER;
505 /* it's a printer (set_printer_hnd_name() will handle port monitors */
507 DEBUGADD(4,("Printer is a printer\n"));
508 Printer->printer_type = SPLHND_PRINTER;
514 static void prune_printername_cache_fn(const char *key, const char *value,
515 time_t timeout, void *private_data)
520 static void prune_printername_cache(void)
522 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
525 /****************************************************************************
526 Set printer handle name.. Accept names like \\server, \\server\printer,
527 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
528 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
529 XcvDataPort() interface.
530 ****************************************************************************/
532 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
533 const struct auth_session_info *session_info,
534 struct messaging_context *msg_ctx,
535 struct printer_handle *Printer,
536 const char *handlename)
539 int n_services=lp_numservices();
541 const char *printername;
542 const char *servername = NULL;
545 struct spoolss_PrinterInfo2 *info2 = NULL;
550 * Hopefully nobody names his printers like this. Maybe \ or ,
551 * are illegal in printer names even?
553 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
557 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
558 (unsigned long)strlen(handlename)));
560 aprinter = discard_const_p(char, handlename);
561 if ( *handlename == '\\' ) {
562 servername = canon_servername(handlename);
563 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
567 if (!is_myname_or_ipaddr(servername)) {
568 return WERR_INVALID_PRINTER_NAME;
570 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
571 if (Printer->servername == NULL) {
572 return WERR_NOT_ENOUGH_MEMORY;
576 if (Printer->printer_type == SPLHND_SERVER) {
580 if (Printer->printer_type != SPLHND_PRINTER) {
581 return WERR_INVALID_HANDLE;
584 DEBUGADD(5, ("searching for [%s]\n", aprinter));
586 p = strchr(aprinter, ',');
593 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
595 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
601 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
604 /* check for the Port Monitor Interface */
605 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
606 Printer->printer_type = SPLHND_PORTMON_TCP;
607 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
610 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
611 Printer->printer_type = SPLHND_PORTMON_LOCAL;
612 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
616 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
617 if (cache_key == NULL) {
618 return WERR_NOT_ENOUGH_MEMORY;
622 * With hundreds of printers, the "for" loop iterating all
623 * shares can be quite expensive, as it is done on every
624 * OpenPrinter. The loop maps "aprinter" to "sname", the
625 * result of which we cache in gencache.
627 if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
628 found = (strcmp(tmp, printer_not_found) != 0);
630 DEBUG(4, ("Printer %s not found\n", aprinter));
632 return WERR_INVALID_PRINTER_NAME;
638 /* Search all sharenames first as this is easier than pulling
639 the printer_info_2 off of disk. Don't use find_service() since
640 that calls out to map_username() */
642 /* do another loop to look for printernames */
643 for (snum = 0; !found && snum < n_services; snum++) {
644 const char *printer = lp_const_servicename(snum);
646 /* no point going on if this is not a printer */
647 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
651 /* ignore [printers] share */
652 if (strequal(printer, "printers")) {
656 fstrcpy(sname, printer);
657 if (strequal(aprinter, printer)) {
662 /* no point looking up the printer object if
663 we aren't allowing printername != sharename */
664 if (lp_force_printername(snum)) {
668 result = winreg_get_printer_internal(mem_ctx,
673 if ( !W_ERROR_IS_OK(result) ) {
674 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
675 sname, win_errstr(result)));
679 printername = strrchr(info2->printername, '\\');
680 if (printername == NULL) {
681 printername = info2->printername;
686 if (strequal(printername, aprinter)) {
691 DEBUGADD(10, ("printername: %s\n", printername));
697 gencache_set(cache_key, printer_not_found,
699 TALLOC_FREE(cache_key);
700 DEBUGADD(4,("Printer not found\n"));
701 return WERR_INVALID_PRINTER_NAME;
704 gencache_set(cache_key, sname, time(NULL) + 300);
705 TALLOC_FREE(cache_key);
707 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
709 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
714 /****************************************************************************
715 Find first available printer slot. creates a printer handle for you.
716 ****************************************************************************/
718 static WERROR open_printer_hnd(struct pipes_struct *p,
719 struct policy_handle *hnd,
721 uint32_t access_granted)
723 struct printer_handle *new_printer;
726 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
728 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
729 if (new_printer == NULL) {
730 return WERR_NOT_ENOUGH_MEMORY;
732 talloc_set_destructor(new_printer, printer_entry_destructor);
734 /* This also steals the printer_handle on the policy_handle */
735 if (!create_policy_hnd(p, hnd, 0, new_printer)) {
736 TALLOC_FREE(new_printer);
737 return WERR_INVALID_HANDLE;
740 /* Add to the internal list. */
741 DLIST_ADD(printers_list, new_printer);
743 new_printer->notify.option=NULL;
745 if (!set_printer_hnd_printertype(new_printer, name)) {
746 close_printer_handle(p, hnd);
747 return WERR_INVALID_HANDLE;
750 result = set_printer_hnd_name(p->mem_ctx,
751 get_session_info_system(),
754 if (!W_ERROR_IS_OK(result)) {
755 close_printer_handle(p, hnd);
759 new_printer->access_granted = access_granted;
761 DBG_INFO("%d printer handles active\n", (int)num_pipe_handles());
766 /***************************************************************************
767 check to see if the client notify handle is monitoring the notification
768 given by (notify_type, notify_field).
769 **************************************************************************/
771 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
772 uint16_t notify_field)
777 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
778 uint16_t notify_field)
780 struct spoolss_NotifyOption *option = p->notify.option;
784 * Flags should always be zero when the change notify
785 * is registered by the client's spooler. A user Win32 app
786 * might use the flags though instead of the NOTIFY_OPTION_INFO
795 return is_monitoring_event_flags(
796 p->notify.flags, notify_type, notify_field);
798 for (i = 0; i < option->count; i++) {
800 /* Check match for notify_type */
802 if (option->types[i].type != notify_type)
805 /* Check match for field */
807 for (j = 0; j < option->types[i].count; j++) {
808 if (option->types[i].fields[j].field == notify_field) {
814 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
815 p->servername, p->sharename, notify_type, notify_field));
820 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
821 _data->data.integer[0] = _integer; \
822 _data->data.integer[1] = 0;
825 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
826 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
827 if (!_data->data.string.string) {\
828 _data->data.string.size = 0; \
830 _data->data.string.size = strlen_m_term(_p) * 2;
832 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
833 _data->data.devmode.devmode = _devmode;
835 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
840 struct spoolss_Time st;
844 if (!init_systemtime(&st, t)) {
848 p = talloc_array(mem_ctx, char, len);
854 * Systemtime must be linearized as a set of UINT16's.
855 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
858 SSVAL(p, 0, st.year);
859 SSVAL(p, 2, st.month);
860 SSVAL(p, 4, st.day_of_week);
862 SSVAL(p, 8, st.hour);
863 SSVAL(p, 10, st.minute);
864 SSVAL(p, 12, st.second);
865 SSVAL(p, 14, st.millisecond);
871 /* Convert a notification message to a struct spoolss_Notify */
873 static void notify_one_value(struct spoolss_notify_msg *msg,
874 struct spoolss_Notify *data,
877 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
880 static void notify_string(struct spoolss_notify_msg *msg,
881 struct spoolss_Notify *data,
884 /* The length of the message includes the trailing \0 */
886 data->data.string.size = msg->len * 2;
887 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
888 if (!data->data.string.string) {
889 data->data.string.size = 0;
894 static void notify_system_time(struct spoolss_notify_msg *msg,
895 struct spoolss_Notify *data,
898 data->data.string.string = NULL;
899 data->data.string.size = 0;
901 if (msg->len != sizeof(time_t)) {
902 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
907 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
908 &data->data.string.string,
909 &data->data.string.size);
912 struct notify2_message_table {
914 void (*fn)(struct spoolss_notify_msg *msg,
915 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
918 static struct notify2_message_table printer_notify_table[] = {
919 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
920 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
921 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
922 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
923 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
924 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
925 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
926 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
927 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
928 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
929 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
930 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
931 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
932 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
933 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
934 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
935 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
936 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
937 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
940 static struct notify2_message_table job_notify_table[] = {
941 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
942 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
943 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
944 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
945 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
946 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
947 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
948 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
949 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
950 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
951 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
952 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
953 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
954 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
955 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
956 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
957 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
958 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
959 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
960 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
961 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
962 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
963 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
964 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
968 /***********************************************************************
969 Allocate talloc context for container object
970 **********************************************************************/
972 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
977 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
982 /***********************************************************************
983 release all allocated memory and zero out structure
984 **********************************************************************/
986 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
992 talloc_destroy(ctr->ctx);
999 /***********************************************************************
1000 **********************************************************************/
1002 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1010 /***********************************************************************
1011 **********************************************************************/
1013 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1015 if ( !ctr || !ctr->msg_groups )
1018 if ( idx >= ctr->num_groups )
1021 return &ctr->msg_groups[idx];
1025 /***********************************************************************
1026 How many groups of change messages do we have ?
1027 **********************************************************************/
1029 static uint32_t notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1034 return ctr->num_groups;
1037 /***********************************************************************
1038 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1039 **********************************************************************/
1041 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1043 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1044 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1045 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1046 uint32_t i, new_slot;
1051 /* loop over all groups looking for a matching printer name */
1053 for ( i=0; i<ctr->num_groups; i++ ) {
1054 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1058 /* add a new group? */
1060 if ( i == ctr->num_groups ) {
1063 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1064 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1067 ctr->msg_groups = groups;
1069 /* clear the new entry and set the printer name */
1071 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1072 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1075 /* add the change messages; 'i' is the correct index now regardless */
1077 msg_grp = &ctr->msg_groups[i];
1079 msg_grp->num_msgs++;
1081 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1082 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1085 msg_grp->msgs = msg_list;
1087 new_slot = msg_grp->num_msgs-1;
1088 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1090 /* need to allocate own copy of data */
1092 if ( msg->len != 0 )
1093 msg_grp->msgs[new_slot].notify.data = (char *)
1094 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1096 return ctr->num_groups;
1099 static void construct_info_data(struct spoolss_Notify *info_data,
1100 enum spoolss_NotifyType type,
1101 uint16_t field, int id);
1103 /***********************************************************************
1104 Send a change notification message on all handles which have a call
1106 **********************************************************************/
1108 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1109 struct printer_handle *prn_hnd,
1110 SPOOLSS_NOTIFY_MSG *messages,
1112 struct spoolss_Notify **_notifies,
1115 struct spoolss_Notify *notifies;
1116 SPOOLSS_NOTIFY_MSG *msg;
1121 notifies = talloc_zero_array(mem_ctx,
1122 struct spoolss_Notify, num_msgs);
1127 for (i = 0; i < num_msgs; i++) {
1131 /* Are we monitoring this event? */
1133 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1137 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1138 "for printer [%s]\n",
1139 msg->type, msg->field, prn_hnd->sharename));
1142 * if the is a printer notification handle and not a job
1143 * notification type, then set the id to 0.
1144 * Otherwise just use what was specified in the message.
1146 * When registering change notification on a print server
1147 * handle we always need to send back the id (snum) matching
1148 * the printer for which the change took place.
1149 * For change notify registered on a printer handle,
1150 * this does not matter and the id should be 0.
1155 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1156 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1162 /* Convert unix jobid to smb jobid */
1164 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1165 id = sysjob_to_jobid(msg->id);
1168 DEBUG(3, ("no such unix jobid %d\n",
1174 construct_info_data(¬ifies[count],
1175 msg->type, msg->field, id);
1178 case PRINTER_NOTIFY_TYPE:
1179 if (printer_notify_table[msg->field].fn) {
1180 printer_notify_table[msg->field].fn(msg,
1181 ¬ifies[count], mem_ctx);
1185 case JOB_NOTIFY_TYPE:
1186 if (job_notify_table[msg->field].fn) {
1187 job_notify_table[msg->field].fn(msg,
1188 ¬ifies[count], mem_ctx);
1193 DEBUG(5, ("Unknown notification type %d\n",
1201 *_notifies = notifies;
1207 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1208 struct printer_handle *prn_hnd,
1209 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1211 struct spoolss_Notify *notifies;
1213 union spoolss_ReplyPrinterInfo info;
1214 struct spoolss_NotifyInfo info0;
1215 uint32_t reply_result;
1220 /* Is there notification on this handle? */
1221 if (prn_hnd->notify.cli_chan == NULL ||
1222 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1223 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1224 prn_hnd->notify.cli_chan->active_connections == 0) {
1228 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1229 prn_hnd->servername, prn_hnd->sharename));
1231 /* For this printer? Print servers always receive notifications. */
1232 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1233 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1237 DEBUG(10,("Our printer\n"));
1239 /* build the array of change notifications */
1240 ret = build_notify2_messages(mem_ctx, prn_hnd,
1242 msg_group->num_msgs,
1248 info0.version = 0x2;
1249 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1250 info0.count = count;
1251 info0.notifies = notifies;
1253 info.info0 = &info0;
1255 status = dcerpc_spoolss_RouterReplyPrinterEx(
1256 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1258 &prn_hnd->notify.cli_hnd,
1259 prn_hnd->notify.change, /* color */
1260 prn_hnd->notify.flags,
1262 0, /* reply_type, must be 0 */
1264 if (!NT_STATUS_IS_OK(status)) {
1265 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1267 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1268 nt_errstr(status)));
1269 werr = ntstatus_to_werror(status);
1270 } else if (!W_ERROR_IS_OK(werr)) {
1271 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1273 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1276 switch (reply_result) {
1279 case PRINTER_NOTIFY_INFO_DISCARDED:
1280 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1281 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1290 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1292 struct printer_handle *p;
1293 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1294 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1298 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1302 if (!msg_group->msgs) {
1303 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1307 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1309 /* loop over all printers */
1311 for (p = printers_list; p; p = p->next) {
1312 ret = send_notify2_printer(mem_ctx, p, msg_group);
1319 DEBUG(8,("send_notify2_changes: Exit...\n"));
1323 /***********************************************************************
1324 **********************************************************************/
1326 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1329 uint32_t tv_sec, tv_usec;
1332 /* Unpack message */
1334 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1337 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1339 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1342 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1343 &msg->notify.value[0], &msg->notify.value[1]);
1345 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1346 &msg->len, &msg->notify.data);
1348 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1349 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1351 tv->tv_sec = tv_sec;
1352 tv->tv_usec = tv_usec;
1355 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1356 msg->notify.value[1]));
1358 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1363 /********************************************************************
1364 Receive a notify2 message list
1365 ********************************************************************/
1367 static void receive_notify2_message_list(struct messaging_context *msg,
1370 struct server_id server_id,
1373 size_t msg_count, i, num_groups;
1374 char *buf = (char *)data->data;
1377 SPOOLSS_NOTIFY_MSG notify;
1378 SPOOLSS_NOTIFY_MSG_CTR messages;
1380 if (data->length < 4) {
1381 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1385 msg_count = IVAL(buf, 0);
1388 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1390 if (msg_count == 0) {
1391 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1395 /* initialize the container */
1397 ZERO_STRUCT( messages );
1398 notify_msg_ctr_init( &messages );
1401 * build message groups for each printer identified
1402 * in a change_notify msg. Remember that a PCN message
1403 * includes the handle returned for the srv_spoolss_replyopenprinter()
1404 * call. Therefore messages are grouped according to printer handle.
1407 for ( i=0; i<msg_count; i++ ) {
1408 struct timeval msg_tv;
1410 if (msg_ptr + 4 - buf > data->length) {
1411 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1415 msg_len = IVAL(msg_ptr,0);
1418 if (msg_ptr + msg_len - buf > data->length) {
1419 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1423 /* unpack messages */
1425 ZERO_STRUCT( notify );
1426 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1429 /* add to correct list in container */
1431 notify_msg_ctr_addmsg( &messages, ¬ify );
1433 /* free memory that might have been allocated by notify2_unpack_msg() */
1435 if ( notify.len != 0 )
1436 SAFE_FREE( notify.notify.data );
1439 /* process each group of messages */
1441 num_groups = notify_msg_ctr_numgroups( &messages );
1442 for ( i=0; i<num_groups; i++ )
1443 send_notify2_changes( &messages, i );
1448 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1449 (uint32_t)msg_count ));
1451 notify_msg_ctr_destroy( &messages );
1456 /********************************************************************
1457 Send a message to ourself about new driver being installed
1458 so we can upgrade the information for each printer bound to this
1460 ********************************************************************/
1462 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1463 struct messaging_context *msg_ctx)
1465 int len = strlen(drivername);
1470 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1473 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1474 MSG_PRINTER_DRVUPGRADE,
1475 (const uint8_t *)drivername, len+1);
1480 void srv_spoolss_cleanup(void)
1482 struct printer_session_counter *session_counter;
1484 for (session_counter = counter_list;
1485 session_counter != NULL;
1486 session_counter = counter_list) {
1487 DLIST_REMOVE(counter_list, session_counter);
1488 TALLOC_FREE(session_counter);
1492 /**********************************************************************
1493 callback to receive a MSG_PRINTER_DRVUPGRADE message and iterate
1494 over all printers, upgrading ones as necessary
1495 This is now *ONLY* called inside the background lpq updater. JRA.
1496 **********************************************************************/
1498 void do_drv_upgrade_printer(struct messaging_context *msg,
1501 struct server_id server_id,
1504 TALLOC_CTX *tmp_ctx;
1505 const struct auth_session_info *session_info = get_session_info_system();
1506 struct spoolss_PrinterInfo2 *pinfo2;
1508 const char *drivername;
1510 int n_services = lp_numservices();
1511 struct dcerpc_binding_handle *b = NULL;
1513 tmp_ctx = talloc_new(NULL);
1514 if (!tmp_ctx) return;
1516 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1518 DEBUG(0, ("do_drv_upgrade_printer: Out of memory ?!\n"));
1522 DEBUG(10, ("do_drv_upgrade_printer: "
1523 "Got message for new driver [%s]\n", drivername));
1525 /* Iterate the printer list */
1527 for (snum = 0; snum < n_services; snum++) {
1528 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1532 /* ignore [printers] share */
1533 if (strequal(lp_const_servicename(snum), "printers")) {
1538 result = winreg_printer_binding_handle(tmp_ctx,
1542 if (!W_ERROR_IS_OK(result)) {
1547 result = winreg_get_printer(tmp_ctx, b,
1548 lp_const_servicename(snum),
1551 if (!W_ERROR_IS_OK(result)) {
1555 if (!pinfo2->drivername) {
1559 if (strcmp(drivername, pinfo2->drivername) != 0) {
1563 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1565 /* all we care about currently is the change_id */
1566 result = winreg_printer_update_changeid(tmp_ctx, b,
1567 pinfo2->printername);
1569 if (!W_ERROR_IS_OK(result)) {
1570 DEBUG(3, ("do_drv_upgrade_printer: "
1571 "Failed to update changeid [%s]\n",
1572 win_errstr(result)));
1578 talloc_free(tmp_ctx);
1581 /********************************************************************
1582 Update the cache for all printq's with a registered client
1584 ********************************************************************/
1586 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1588 struct printer_handle *printer = printers_list;
1591 /* loop through all printers and update the cache where
1592 a client is connected */
1594 if ((printer->printer_type == SPLHND_PRINTER) &&
1595 ((printer->notify.cli_chan != NULL) &&
1596 (printer->notify.cli_chan->active_connections > 0))) {
1597 snum = print_queue_snum(printer->sharename);
1598 print_queue_status(msg_ctx, snum, NULL, NULL);
1601 printer = printer->next;
1607 /****************************************************************
1608 _spoolss_OpenPrinter
1609 ****************************************************************/
1611 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1612 struct spoolss_OpenPrinter *r)
1614 struct spoolss_OpenPrinterEx e;
1615 struct spoolss_UserLevel1 level1;
1618 ZERO_STRUCT(level1);
1620 e.in.printername = r->in.printername;
1621 e.in.datatype = r->in.datatype;
1622 e.in.devmode_ctr = r->in.devmode_ctr;
1623 e.in.access_mask = r->in.access_mask;
1624 e.in.userlevel_ctr.level = 1;
1625 e.in.userlevel_ctr.user_info.level1 = &level1;
1627 e.out.handle = r->out.handle;
1629 werr = _spoolss_OpenPrinterEx(p, &e);
1631 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1632 /* OpenPrinterEx returns this for a bad
1633 * printer name. We must return WERR_INVALID_PRINTER_NAME
1636 werr = WERR_INVALID_PRINTER_NAME;
1642 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1643 struct spoolss_DeviceMode *orig,
1644 struct spoolss_DeviceMode **dest)
1646 struct spoolss_DeviceMode *dm;
1648 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1650 return WERR_NOT_ENOUGH_MEMORY;
1653 /* copy all values, then duplicate strings and structs */
1656 dm->devicename = talloc_strdup(dm, orig->devicename);
1657 if (!dm->devicename) {
1658 return WERR_NOT_ENOUGH_MEMORY;
1660 dm->formname = talloc_strdup(dm, orig->formname);
1661 if (!dm->formname) {
1662 return WERR_NOT_ENOUGH_MEMORY;
1664 if (orig->driverextra_data.data) {
1665 dm->driverextra_data.data =
1666 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1667 orig->driverextra_data.length);
1668 if (!dm->driverextra_data.data) {
1669 return WERR_NOT_ENOUGH_MEMORY;
1677 /****************************************************************
1678 _spoolss_OpenPrinterEx
1679 ****************************************************************/
1681 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1682 struct spoolss_OpenPrinterEx *r)
1684 struct dcesrv_call_state *dce_call = p->dce_call;
1685 struct dcesrv_connection *dcesrv_conn = dce_call->conn;
1686 const struct tsocket_address *remote_address =
1687 dcesrv_connection_get_remote_address(dcesrv_conn);
1688 struct auth_session_info *session_info =
1689 dcesrv_call_session_info(dce_call);
1693 struct printer_handle *Printer=NULL;
1697 if (!r->in.printername) {
1698 return WERR_INVALID_PARAMETER;
1701 if (!*r->in.printername) {
1702 return WERR_INVALID_PARAMETER;
1705 if (r->in.userlevel_ctr.level > 3) {
1706 return WERR_INVALID_PARAMETER;
1708 if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1709 (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1710 (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1711 return WERR_INVALID_PARAMETER;
1715 * The printcap printer share inventory is updated on client
1716 * enumeration. For clients that do not perform enumeration prior to
1717 * access, such as cupssmbadd, we reinitialise the printer share
1718 * inventory on open as well.
1721 delete_and_reload_printers();
1724 /* some sanity check because you can open a printer or a print server */
1725 /* aka: \\server\printer or \\server */
1727 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1729 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1730 if (!W_ERROR_IS_OK(result)) {
1731 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1732 "for printer %s\n", r->in.printername));
1733 ZERO_STRUCTP(r->out.handle);
1737 Printer = find_printer_index_by_hnd(p, r->out.handle);
1739 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1740 "handle we created for printer %s\n", r->in.printername));
1741 close_printer_handle(p, r->out.handle);
1742 ZERO_STRUCTP(r->out.handle);
1743 return WERR_INVALID_PARAMETER;
1747 * First case: the user is opening the print server:
1749 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1750 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1752 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1753 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1754 * or if the user is listed in the smb.conf printer admin parameter.
1756 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1757 * client view printer folder, but does not show the MSAPW.
1759 * Note: this test needs code to check access rights here too. Jeremy
1760 * could you look at this?
1762 * Second case: the user is opening a printer:
1763 * NT doesn't let us connect to a printer if the connecting user
1764 * doesn't have print permission.
1766 * Third case: user is opening a Port Monitor
1767 * access checks same as opening a handle to the print server.
1770 switch (Printer->printer_type )
1773 case SPLHND_PORTMON_TCP:
1774 case SPLHND_PORTMON_LOCAL:
1775 /* Printserver handles use global struct... */
1779 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1780 r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1781 r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1784 /* Map standard access rights to object specific access rights */
1786 se_map_standard(&r->in.access_mask,
1787 &printserver_std_mapping);
1789 /* Deny any object specific bits that don't apply to print
1790 servers (i.e printer and job specific bits) */
1792 r->in.access_mask &= SEC_MASK_SPECIFIC;
1794 if (r->in.access_mask &
1795 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1796 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1797 close_printer_handle(p, r->out.handle);
1798 ZERO_STRUCTP(r->out.handle);
1799 return WERR_ACCESS_DENIED;
1802 /* Allow admin access */
1804 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1806 if (!lp_show_add_printer_wizard()) {
1807 close_printer_handle(p, r->out.handle);
1808 ZERO_STRUCTP(r->out.handle);
1809 return WERR_ACCESS_DENIED;
1812 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1813 and not a printer admin, then fail */
1815 if ((session_info->unix_token->uid != sec_initial_uid()) &&
1816 !security_token_has_privilege(
1817 session_info->security_token,
1818 SEC_PRIV_PRINT_OPERATOR) &&
1819 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1820 session_info->security_token)) {
1821 close_printer_handle(p, r->out.handle);
1822 ZERO_STRUCTP(r->out.handle);
1823 DEBUG(3,("access DENIED as user is not root, "
1824 "has no printoperator privilege and is "
1825 "not a member of the printoperator builtin group\n"));
1826 return WERR_ACCESS_DENIED;
1829 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1833 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1836 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1837 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1841 case SPLHND_PRINTER:
1842 /* NT doesn't let us connect to a printer if the connecting user
1843 doesn't have print permission. */
1845 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1846 close_printer_handle(p, r->out.handle);
1847 ZERO_STRUCTP(r->out.handle);
1848 return WERR_INVALID_HANDLE;
1851 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1852 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1855 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1857 /* map an empty access mask to the minimum access mask */
1858 if (r->in.access_mask == 0x0)
1859 r->in.access_mask = PRINTER_ACCESS_USE;
1862 * If we are not serving the printer driver for this printer,
1863 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1864 * will keep NT clients happy --jerry
1867 if (lp_use_client_driver(snum)
1868 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1870 r->in.access_mask = PRINTER_ACCESS_USE;
1873 /* check smb.conf parameters and the the sec_desc */
1874 raddr = tsocket_address_inet_addr_string(remote_address,
1876 if (raddr == NULL) {
1877 return WERR_NOT_ENOUGH_MEMORY;
1880 rc = get_remote_hostname(remote_address,
1884 return WERR_NOT_ENOUGH_MEMORY;
1886 if (strequal(rhost, "UNKNOWN")) {
1890 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1892 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1893 ZERO_STRUCTP(r->out.handle);
1894 return WERR_ACCESS_DENIED;
1897 if (!user_ok_token(session_info->unix_info->unix_name,
1898 session_info->info->domain_name,
1899 session_info->security_token, snum) ||
1900 !W_ERROR_IS_OK(print_access_check(session_info,
1903 r->in.access_mask))) {
1904 DEBUG(3, ("access DENIED for printer open\n"));
1905 close_printer_handle(p, r->out.handle);
1906 ZERO_STRUCTP(r->out.handle);
1907 return WERR_ACCESS_DENIED;
1910 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912 close_printer_handle(p, r->out.handle);
1913 ZERO_STRUCTP(r->out.handle);
1914 return WERR_ACCESS_DENIED;
1917 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1920 r->in.access_mask = PRINTER_ACCESS_USE;
1922 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1925 winreg_create_printer_internal(p->mem_ctx,
1926 get_session_info_system(),
1928 lp_const_servicename(snum));
1933 /* sanity check to prevent programmer error */
1934 ZERO_STRUCTP(r->out.handle);
1935 return WERR_INVALID_HANDLE;
1938 Printer->access_granted = r->in.access_mask;
1941 * If the client sent a devmode in the OpenPrinter() call, then
1942 * save it here in case we get a job submission on this handle
1945 if ((Printer->printer_type != SPLHND_SERVER)
1946 && (r->in.devmode_ctr.devmode != NULL)) {
1947 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1954 /****************************************************************
1955 _spoolss_ClosePrinter
1956 ****************************************************************/
1958 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1959 struct spoolss_ClosePrinter *r)
1961 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1963 if (Printer && Printer->document_started) {
1964 struct spoolss_EndDocPrinter e;
1966 e.in.handle = r->in.handle;
1968 _spoolss_EndDocPrinter(p, &e);
1971 if (!close_printer_handle(p, r->in.handle))
1972 return WERR_INVALID_HANDLE;
1974 /* clear the returned printer handle. Observed behavior
1975 from Win2k server. Don't think this really matters.
1976 Previous code just copied the value of the closed
1979 ZERO_STRUCTP(r->out.handle);
1984 /****************************************************************
1985 _spoolss_DeletePrinter
1986 ****************************************************************/
1988 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1989 struct spoolss_DeletePrinter *r)
1991 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1995 if (Printer && Printer->document_started) {
1996 struct spoolss_EndDocPrinter e;
1998 e.in.handle = r->in.handle;
2000 _spoolss_EndDocPrinter(p, &e);
2003 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2004 winreg_delete_printer_key_internal(p->mem_ctx,
2005 get_session_info_system(),
2007 lp_const_servicename(snum),
2011 result = delete_printer_handle(p, r->in.handle);
2016 /*******************************************************************
2017 * static function to lookup the version id corresponding to an
2018 * long architecture string
2019 ******************************************************************/
2021 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2022 SPOOLSS_DRIVER_VERSION_NT35,
2023 SPOOLSS_DRIVER_VERSION_NT4,
2024 SPOOLSS_DRIVER_VERSION_200X,
2027 static int get_version_id(const char *arch)
2031 for (i=0; archi_table[i].long_archi != NULL; i++)
2033 if (strcmp(arch, archi_table[i].long_archi) == 0)
2034 return (archi_table[i].version);
2040 /****************************************************************
2041 _spoolss_DeletePrinterDriver
2042 ****************************************************************/
2044 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2045 struct spoolss_DeletePrinterDriver *r)
2048 struct dcesrv_call_state *dce_call = p->dce_call;
2049 struct auth_session_info *session_info =
2050 dcesrv_call_session_info(dce_call);
2051 struct spoolss_DriverInfo8 *info = NULL;
2054 struct dcerpc_binding_handle *b;
2055 TALLOC_CTX *tmp_ctx = NULL;
2059 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2060 and not a printer admin, then fail */
2062 if ((session_info->unix_token->uid != sec_initial_uid()) &&
2063 !security_token_has_privilege(session_info->security_token,
2064 SEC_PRIV_PRINT_OPERATOR)) {
2065 return WERR_ACCESS_DENIED;
2068 if (r->in.architecture == NULL || r->in.driver == NULL) {
2069 return WERR_INVALID_ENVIRONMENT;
2072 /* check that we have a valid driver name first */
2074 if ((version = get_version_id(r->in.architecture)) == -1) {
2075 return WERR_INVALID_ENVIRONMENT;
2078 tmp_ctx = talloc_new(p->mem_ctx);
2080 return WERR_NOT_ENOUGH_MEMORY;
2083 status = winreg_printer_binding_handle(tmp_ctx,
2084 get_session_info_system(),
2087 if (!W_ERROR_IS_OK(status)) {
2091 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2092 status = winreg_get_driver(tmp_ctx, b,
2093 r->in.architecture, r->in.driver,
2094 drv_cversion[i], &info);
2095 if (!W_ERROR_IS_OK(status)) {
2096 DEBUG(5, ("skipping del of driver with version %d\n",
2102 if (printer_driver_in_use(tmp_ctx, b, info)) {
2103 status = WERR_PRINTER_DRIVER_IN_USE;
2107 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2108 if (!W_ERROR_IS_OK(status)) {
2109 DEBUG(0, ("failed del of driver with version %d\n",
2114 if (found == false) {
2115 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2116 status = WERR_UNKNOWN_PRINTER_DRIVER;
2122 talloc_free(tmp_ctx);
2127 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2128 struct pipes_struct *p,
2129 struct spoolss_DeletePrinterDriverEx *r,
2130 struct dcerpc_binding_handle *b,
2131 struct spoolss_DriverInfo8 *info)
2133 struct dcesrv_call_state *dce_call = p->dce_call;
2134 struct auth_session_info *session_info =
2135 dcesrv_call_session_info(dce_call);
2139 if (printer_driver_in_use(mem_ctx, b, info)) {
2140 status = WERR_PRINTER_DRIVER_IN_USE;
2145 * we have a couple of cases to consider.
2146 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2147 * then the delete should fail if **any** files overlap with
2149 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2150 * non-overlapping files
2151 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2152 * are set, then do not delete any files
2153 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2156 delete_files = r->in.delete_flags
2157 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2161 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2162 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2163 status = WERR_PRINTER_DRIVER_IN_USE;
2167 * printer_driver_files_in_use() has trimmed overlapping files
2168 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2173 status = winreg_del_driver(mem_ctx, b, info, info->version);
2174 if (!W_ERROR_IS_OK(status)) {
2179 * now delete any associated files if delete_files is
2180 * true. Even if this part fails, we return success
2181 * because the driver does not exist any more
2184 delete_driver_files(session_info, info);
2191 /****************************************************************
2192 _spoolss_DeletePrinterDriverEx
2193 ****************************************************************/
2195 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2196 struct spoolss_DeletePrinterDriverEx *r)
2198 struct dcesrv_call_state *dce_call = p->dce_call;
2199 struct auth_session_info *session_info =
2200 dcesrv_call_session_info(dce_call);
2201 struct spoolss_DriverInfo8 *info = NULL;
2203 struct dcerpc_binding_handle *b;
2204 TALLOC_CTX *tmp_ctx = NULL;
2208 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2209 and not a printer admin, then fail */
2211 if ((session_info->unix_token->uid != sec_initial_uid()) &&
2212 !security_token_has_privilege(session_info->security_token,
2213 SEC_PRIV_PRINT_OPERATOR)) {
2214 return WERR_ACCESS_DENIED;
2217 if (r->in.architecture == NULL || r->in.driver == NULL) {
2218 return WERR_INVALID_ENVIRONMENT;
2221 /* check that we have a valid driver name first */
2222 if (get_version_id(r->in.architecture) == -1) {
2223 /* this is what NT returns */
2224 return WERR_INVALID_ENVIRONMENT;
2227 tmp_ctx = talloc_new(p->mem_ctx);
2229 return WERR_NOT_ENOUGH_MEMORY;
2232 status = winreg_printer_binding_handle(tmp_ctx,
2233 get_session_info_system(),
2236 if (!W_ERROR_IS_OK(status)) {
2240 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2241 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2242 && (drv_cversion[i] != r->in.version)) {
2246 /* check if a driver with this version exists before delete */
2247 status = winreg_get_driver(tmp_ctx, b,
2248 r->in.architecture, r->in.driver,
2249 drv_cversion[i], &info);
2250 if (!W_ERROR_IS_OK(status)) {
2251 DEBUG(5, ("skipping del of driver with version %d\n",
2257 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2258 if (!W_ERROR_IS_OK(status)) {
2259 DEBUG(0, ("failed to delete driver with version %d\n",
2264 if (found == false) {
2265 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2266 status = WERR_UNKNOWN_PRINTER_DRIVER;
2272 talloc_free(tmp_ctx);
2277 /********************************************************************
2278 GetPrinterData on a printer server Handle.
2279 ********************************************************************/
2281 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2283 enum winreg_Type *type,
2284 union spoolss_PrinterData *data)
2286 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2288 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2290 SIVAL(&data->value, 0, 0x00);
2294 if (!strcasecmp_m(value, "BeepEnabled")) {
2296 SIVAL(&data->value, 0, 0x00);
2300 if (!strcasecmp_m(value, "EventLog")) {
2302 /* formally was 0x1b */
2303 SIVAL(&data->value, 0, 0x00);
2307 if (!strcasecmp_m(value, "NetPopup")) {
2309 SIVAL(&data->value, 0, 0x00);
2313 if (!strcasecmp_m(value, "MajorVersion")) {
2316 /* Windows NT 4.0 seems to not allow uploading of drivers
2317 to a server that reports 0x3 as the MajorVersion.
2318 need to investigate more how Win2k gets around this .
2321 if (RA_WINNT == get_remote_arch()) {
2322 SIVAL(&data->value, 0, 0x02);
2324 SIVAL(&data->value, 0, 0x03);
2330 if (!strcasecmp_m(value, "MinorVersion")) {
2332 SIVAL(&data->value, 0, 0x00);
2337 * uint32_t size = 0x114
2338 * uint32_t major = 5
2339 * uint32_t minor = [0|1]
2340 * uint32_t build = [2195|2600]
2341 * extra unicode string = e.g. "Service Pack 3"
2343 if (!strcasecmp_m(value, "OSVersion")) {
2345 enum ndr_err_code ndr_err;
2346 struct spoolss_OSVersion os;
2349 * Set the default OSVersion to:
2351 * Windows Server 2003R2 SP2 (5.2.3790)
2353 * used to be Windows 2000 (5.0.2195)
2355 os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2356 "spoolss", "os_major",
2357 GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2358 os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2359 "spoolss", "os_minor",
2360 GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2361 os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2362 "spoolss", "os_build",
2363 GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2364 os.extra_string = ""; /* leave extra string empty */
2366 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2367 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2368 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2369 return WERR_GEN_FAILURE;
2372 if (DEBUGLEVEL >= 10) {
2373 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2377 data->binary = blob;
2383 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2386 data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2387 W_ERROR_HAVE_NO_MEMORY(data->string);
2392 if (!strcasecmp_m(value, "Architecture")) {
2394 data->string = talloc_strdup(mem_ctx,
2395 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2396 W_ERROR_HAVE_NO_MEMORY(data->string);
2401 if (!strcasecmp_m(value, "DsPresent")) {
2404 /* only show the publish check box if we are a
2405 member of a AD domain */
2407 if (lp_security() == SEC_ADS) {
2408 SIVAL(&data->value, 0, 0x01);
2410 SIVAL(&data->value, 0, 0x00);
2415 if (!strcasecmp_m(value, "DNSMachineName")) {
2416 const char *hostname = get_mydnsfullname();
2419 return WERR_FILE_NOT_FOUND;
2423 data->string = talloc_strdup(mem_ctx, hostname);
2424 W_ERROR_HAVE_NO_MEMORY(data->string);
2431 return WERR_INVALID_PARAMETER;
2434 /****************************************************************
2435 _spoolss_GetPrinterData
2436 ****************************************************************/
2438 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2439 struct spoolss_GetPrinterData *r)
2441 struct spoolss_GetPrinterDataEx r2;
2443 r2.in.handle = r->in.handle;
2444 r2.in.key_name = "PrinterDriverData";
2445 r2.in.value_name = r->in.value_name;
2446 r2.in.offered = r->in.offered;
2447 r2.out.type = r->out.type;
2448 r2.out.data = r->out.data;
2449 r2.out.needed = r->out.needed;
2451 return _spoolss_GetPrinterDataEx(p, &r2);
2454 /*********************************************************
2455 Connect to the client machine.
2456 **********************************************************/
2458 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2459 struct sockaddr_storage *client_ss, const char *remote_machine)
2462 struct sockaddr_storage rm_addr;
2463 char addr[INET6_ADDRSTRLEN];
2464 struct cli_credentials *anon_creds = NULL;
2466 if ( is_zero_addr(client_ss) ) {
2467 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2469 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2470 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2473 print_sockaddr(addr, sizeof(addr), &rm_addr);
2475 rm_addr = *client_ss;
2476 print_sockaddr(addr, sizeof(addr), &rm_addr);
2477 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2481 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2482 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2487 anon_creds = cli_credentials_init_anon(NULL);
2488 if (anon_creds == NULL) {
2489 DBG_ERR("cli_credentials_init_anon() failed\n");
2493 /* setup the connection */
2494 ret = cli_full_connection_creds( pp_cli, lp_netbios_name(), remote_machine,
2495 &rm_addr, 0, "IPC$", "IPC",
2497 CLI_FULL_CONNECTION_IPC);
2498 TALLOC_FREE(anon_creds);
2499 if ( !NT_STATUS_IS_OK( ret ) ) {
2500 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2505 if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
2506 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2507 cli_shutdown(*pp_cli);
2512 * Ok - we have an anonymous connection to the IPC$ share.
2513 * Now start the NT Domain stuff :-).
2516 ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2517 if (!NT_STATUS_IS_OK(ret)) {
2518 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2519 remote_machine, nt_errstr(ret)));
2520 cli_shutdown(*pp_cli);
2527 /***************************************************************************
2528 Connect to the client.
2529 ****************************************************************************/
2531 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2532 uint32_t localprinter,
2533 enum winreg_Type type,
2534 struct policy_handle *handle,
2535 struct notify_back_channel **_chan,
2536 struct sockaddr_storage *client_ss,
2537 struct messaging_context *msg_ctx)
2541 struct notify_back_channel *chan;
2543 for (chan = back_channels; chan; chan = chan->next) {
2544 if (memcmp(&chan->client_address, client_ss,
2545 sizeof(struct sockaddr_storage)) == 0) {
2551 * If it's the first connection, contact the client
2552 * and connect to the IPC$ share anonymously
2555 fstring unix_printer;
2557 /* the +2 is to strip the leading 2 backslashes */
2558 fstrcpy(unix_printer, printer + 2);
2560 chan = talloc_zero(NULL, struct notify_back_channel);
2564 chan->client_address = *client_ss;
2566 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2571 DLIST_ADD(back_channels, chan);
2573 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2574 receive_notify2_message_list);
2577 if (chan->cli_pipe == NULL ||
2578 chan->cli_pipe->binding_handle == NULL) {
2579 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2580 "NULL %s for printer %s\n",
2581 chan->cli_pipe == NULL ?
2582 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2588 * Tell the specific printing tdb we want messages for this printer
2589 * by registering our PID.
2592 if (!print_notify_register_pid(snum)) {
2593 DEBUG(0, ("Failed to register our pid for printer %s\n",
2597 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2606 if (!NT_STATUS_IS_OK(status)) {
2607 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2608 result = ntstatus_to_werror(status);
2609 } else if (!W_ERROR_IS_OK(result)) {
2610 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2613 chan->active_connections++;
2616 return (W_ERROR_IS_OK(result));
2619 /****************************************************************
2620 ****************************************************************/
2622 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2623 const struct spoolss_NotifyOption *r)
2625 struct spoolss_NotifyOption *option;
2632 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2639 if (!option->count) {
2643 option->types = talloc_zero_array(option,
2644 struct spoolss_NotifyOptionType, option->count);
2645 if (!option->types) {
2646 talloc_free(option);
2650 for (i=0; i < option->count; i++) {
2651 option->types[i] = r->types[i];
2653 if (option->types[i].count) {
2654 option->types[i].fields = talloc_zero_array(option,
2655 union spoolss_Field, option->types[i].count);
2656 if (!option->types[i].fields) {
2657 talloc_free(option);
2660 for (k=0; k<option->types[i].count; k++) {
2661 option->types[i].fields[k] =
2662 r->types[i].fields[k];
2670 /****************************************************************
2671 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2673 * before replying OK: status=0 a rpc call is made to the workstation
2674 * asking ReplyOpenPrinter
2676 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2677 * called from api_spoolss_rffpcnex
2678 ****************************************************************/
2680 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2681 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2683 struct dcesrv_call_state *dce_call = p->dce_call;
2684 struct dcesrv_connection *dcesrv_conn = dce_call->conn;
2685 const struct tsocket_address *remote_address =
2686 dcesrv_connection_get_remote_address(dcesrv_conn);
2688 struct spoolss_NotifyOption *option = r->in.notify_options;
2689 struct sockaddr_storage client_ss;
2692 /* store the notify value in the printer struct */
2694 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2697 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2698 "Invalid handle (%s:%u:%u).\n",
2699 OUR_HANDLE(r->in.handle)));
2700 return WERR_INVALID_HANDLE;
2703 Printer->notify.flags = r->in.flags;
2704 Printer->notify.options = r->in.options;
2705 Printer->notify.printerlocal = r->in.printer_local;
2706 Printer->notify.msg_ctx = p->msg_ctx;
2708 TALLOC_FREE(Printer->notify.option);
2709 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2711 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2713 /* Connect to the client machine and send a ReplyOpenPrinter */
2715 if ( Printer->printer_type == SPLHND_SERVER)
2717 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2718 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2719 return WERR_INVALID_HANDLE;
2721 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2722 "remote_address is %s\n",
2723 tsocket_address_string(remote_address, p->mem_ctx)));
2725 if (!lp_print_notify_backchannel(snum)) {
2726 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2727 "backchannel disabled\n"));
2728 return WERR_RPC_S_SERVER_UNAVAILABLE;
2731 client_len = tsocket_address_bsd_sockaddr(remote_address,
2732 (struct sockaddr *) &client_ss,
2733 sizeof(struct sockaddr_storage));
2734 if (client_len < 0) {
2735 return WERR_NOT_ENOUGH_MEMORY;
2738 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2739 Printer->notify.printerlocal, REG_SZ,
2740 &Printer->notify.cli_hnd,
2741 &Printer->notify.cli_chan,
2742 &client_ss, p->msg_ctx)) {
2743 return WERR_RPC_S_SERVER_UNAVAILABLE;
2749 /*******************************************************************
2750 * fill a notify_info_data with the servername
2751 ********************************************************************/
2753 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2755 struct spoolss_Notify *data,
2756 print_queue_struct *queue,
2757 struct spoolss_PrinterInfo2 *pinfo2,
2758 TALLOC_CTX *mem_ctx)
2760 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2763 /*******************************************************************
2764 * fill a notify_info_data with the printername (not including the servername).
2765 ********************************************************************/
2767 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2769 struct spoolss_Notify *data,
2770 print_queue_struct *queue,
2771 struct spoolss_PrinterInfo2 *pinfo2,
2772 TALLOC_CTX *mem_ctx)
2774 /* the notify name should not contain the \\server\ part */
2775 const char *p = strrchr(pinfo2->printername, '\\');
2778 p = pinfo2->printername;
2783 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2786 /*******************************************************************
2787 * fill a notify_info_data with the servicename
2788 ********************************************************************/
2790 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2792 struct spoolss_Notify *data,
2793 print_queue_struct *queue,
2794 struct spoolss_PrinterInfo2 *pinfo2,
2795 TALLOC_CTX *mem_ctx)
2797 const struct loadparm_substitution *lp_sub =
2798 loadparm_s3_global_substitution();
2800 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), lp_sub, snum));
2803 /*******************************************************************
2804 * fill a notify_info_data with the port name
2805 ********************************************************************/
2807 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2809 struct spoolss_Notify *data,
2810 print_queue_struct *queue,
2811 struct spoolss_PrinterInfo2 *pinfo2,
2812 TALLOC_CTX *mem_ctx)
2814 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2817 /*******************************************************************
2818 * fill a notify_info_data with the printername
2819 * but it doesn't exist, have to see what to do
2820 ********************************************************************/
2822 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2824 struct spoolss_Notify *data,
2825 print_queue_struct *queue,
2826 struct spoolss_PrinterInfo2 *pinfo2,
2827 TALLOC_CTX *mem_ctx)
2829 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2832 /*******************************************************************
2833 * fill a notify_info_data with the comment
2834 ********************************************************************/
2836 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2838 struct spoolss_Notify *data,
2839 print_queue_struct *queue,
2840 struct spoolss_PrinterInfo2 *pinfo2,
2841 TALLOC_CTX *mem_ctx)
2843 const struct loadparm_substitution *lp_sub =
2844 loadparm_s3_global_substitution();
2847 if (*pinfo2->comment == '\0') {
2848 p = lp_comment(talloc_tos(), lp_sub, snum);
2850 p = pinfo2->comment;
2853 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2856 /*******************************************************************
2857 * fill a notify_info_data with the comment
2858 * location = "Room 1, floor 2, building 3"
2859 ********************************************************************/
2861 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2863 struct spoolss_Notify *data,
2864 print_queue_struct *queue,
2865 struct spoolss_PrinterInfo2 *pinfo2,
2866 TALLOC_CTX *mem_ctx)
2868 const char *loc = pinfo2->location;
2871 status = printer_list_get_printer(mem_ctx,
2876 if (NT_STATUS_IS_OK(status)) {
2878 loc = pinfo2->location;
2882 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2885 /*******************************************************************
2886 * fill a notify_info_data with the device mode
2887 * jfm:xxxx don't to it for know but that's a real problem !!!
2888 ********************************************************************/
2890 static void spoolss_notify_devmode(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 /* for a dummy implementation we have to zero the fields */
2898 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2901 /*******************************************************************
2902 * fill a notify_info_data with the separator file name
2903 ********************************************************************/
2905 static void spoolss_notify_sepfile(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->sepfile);
2915 /*******************************************************************
2916 * fill a notify_info_data with the print processor
2917 * jfm:xxxx return always winprint to indicate we don't do anything to it
2918 ********************************************************************/
2920 static void spoolss_notify_print_processor(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->printprocessor);
2930 /*******************************************************************
2931 * fill a notify_info_data with the print processor options
2932 * jfm:xxxx send an empty string
2933 ********************************************************************/
2935 static void spoolss_notify_parameters(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->parameters);
2945 /*******************************************************************
2946 * fill a notify_info_data with the data type
2947 * jfm:xxxx always send RAW as data type
2948 ********************************************************************/
2950 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2952 struct spoolss_Notify *data,
2953 print_queue_struct *queue,
2954 struct spoolss_PrinterInfo2 *pinfo2,
2955 TALLOC_CTX *mem_ctx)
2957 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2960 /*******************************************************************
2961 * fill a notify_info_data with the security descriptor
2962 * jfm:xxxx send an null pointer to say no security desc
2963 * have to implement security before !
2964 ********************************************************************/
2966 static void spoolss_notify_security_desc(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 if (pinfo2->secdesc == NULL) {
2974 data->data.sd.sd = NULL;
2976 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2979 data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2983 /*******************************************************************
2984 * fill a notify_info_data with the attributes
2985 * jfm:xxxx a samba printer is always shared
2986 ********************************************************************/
2988 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2990 struct spoolss_Notify *data,
2991 print_queue_struct *queue,
2992 struct spoolss_PrinterInfo2 *pinfo2,
2993 TALLOC_CTX *mem_ctx)
2995 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2998 /*******************************************************************
2999 * fill a notify_info_data with the priority
3000 ********************************************************************/
3002 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3004 struct spoolss_Notify *data,
3005 print_queue_struct *queue,
3006 struct spoolss_PrinterInfo2 *pinfo2,
3007 TALLOC_CTX *mem_ctx)
3009 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3012 /*******************************************************************
3013 * fill a notify_info_data with the default priority
3014 ********************************************************************/
3016 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3018 struct spoolss_Notify *data,
3019 print_queue_struct *queue,
3020 struct spoolss_PrinterInfo2 *pinfo2,
3021 TALLOC_CTX *mem_ctx)
3023 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3026 /*******************************************************************
3027 * fill a notify_info_data with the start time
3028 ********************************************************************/
3030 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3032 struct spoolss_Notify *data,
3033 print_queue_struct *queue,
3034 struct spoolss_PrinterInfo2 *pinfo2,
3035 TALLOC_CTX *mem_ctx)
3037 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3040 /*******************************************************************
3041 * fill a notify_info_data with the until time
3042 ********************************************************************/
3044 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3046 struct spoolss_Notify *data,
3047 print_queue_struct *queue,
3048 struct spoolss_PrinterInfo2 *pinfo2,
3049 TALLOC_CTX *mem_ctx)
3051 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3054 /*******************************************************************
3055 * fill a notify_info_data with the status
3056 ********************************************************************/
3058 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3060 struct spoolss_Notify *data,
3061 print_queue_struct *queue,
3062 struct spoolss_PrinterInfo2 *pinfo2,
3063 TALLOC_CTX *mem_ctx)
3065 print_status_struct status;
3067 print_queue_length(msg_ctx, snum, &status);
3068 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3071 /*******************************************************************
3072 * fill a notify_info_data with the number of jobs queued
3073 ********************************************************************/
3075 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3077 struct spoolss_Notify *data,
3078 print_queue_struct *queue,
3079 struct spoolss_PrinterInfo2 *pinfo2,
3080 TALLOC_CTX *mem_ctx)
3082 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3083 data, print_queue_length(msg_ctx, snum, NULL));
3086 /*******************************************************************
3087 * fill a notify_info_data with the average ppm
3088 ********************************************************************/
3090 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3092 struct spoolss_Notify *data,
3093 print_queue_struct *queue,
3094 struct spoolss_PrinterInfo2 *pinfo2,
3095 TALLOC_CTX *mem_ctx)
3097 /* always respond 8 pages per minutes */
3098 /* a little hard ! */
3099 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3102 /*******************************************************************
3103 * fill a notify_info_data with username
3104 ********************************************************************/
3106 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3108 struct spoolss_Notify *data,
3109 print_queue_struct *queue,
3110 struct spoolss_PrinterInfo2 *pinfo2,
3111 TALLOC_CTX *mem_ctx)
3113 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3116 /*******************************************************************
3117 * fill a notify_info_data with job status
3118 ********************************************************************/
3120 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3122 struct spoolss_Notify *data,
3123 print_queue_struct *queue,
3124 struct spoolss_PrinterInfo2 *pinfo2,
3125 TALLOC_CTX *mem_ctx)
3127 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3130 /*******************************************************************
3131 * fill a notify_info_data with job name
3132 ********************************************************************/
3134 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3136 struct spoolss_Notify *data,
3137 print_queue_struct *queue,
3138 struct spoolss_PrinterInfo2 *pinfo2,
3139 TALLOC_CTX *mem_ctx)
3141 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3144 /*******************************************************************
3145 * fill a notify_info_data with job status
3146 ********************************************************************/
3148 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3150 struct spoolss_Notify *data,
3151 print_queue_struct *queue,
3152 struct spoolss_PrinterInfo2 *pinfo2,
3153 TALLOC_CTX *mem_ctx)
3156 * Now we're returning job status codes we just return a "" here. JRA.
3161 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3164 switch (queue->status) {
3169 p = ""; /* NT provides the paused string */
3178 #endif /* NO LONGER NEEDED. */
3180 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3183 /*******************************************************************
3184 * fill a notify_info_data with job time
3185 ********************************************************************/
3187 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3189 struct spoolss_Notify *data,
3190 print_queue_struct *queue,
3191 struct spoolss_PrinterInfo2 *pinfo2,
3192 TALLOC_CTX *mem_ctx)
3194 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3197 /*******************************************************************
3198 * fill a notify_info_data with job size
3199 ********************************************************************/
3201 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3203 struct spoolss_Notify *data,
3204 print_queue_struct *queue,
3205 struct spoolss_PrinterInfo2 *pinfo2,
3206 TALLOC_CTX *mem_ctx)
3208 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3211 /*******************************************************************
3212 * fill a notify_info_data with page info
3213 ********************************************************************/
3214 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3216 struct spoolss_Notify *data,
3217 print_queue_struct *queue,
3218 struct spoolss_PrinterInfo2 *pinfo2,
3219 TALLOC_CTX *mem_ctx)
3221 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3224 /*******************************************************************
3225 * fill a notify_info_data with pages printed info.
3226 ********************************************************************/
3227 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3229 struct spoolss_Notify *data,
3230 print_queue_struct *queue,
3231 struct spoolss_PrinterInfo2 *pinfo2,
3232 TALLOC_CTX *mem_ctx)
3234 /* Add code when back-end tracks this */
3235 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3238 /*******************************************************************
3239 Fill a notify_info_data with job position.
3240 ********************************************************************/
3242 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3244 struct spoolss_Notify *data,
3245 print_queue_struct *queue,
3246 struct spoolss_PrinterInfo2 *pinfo2,
3247 TALLOC_CTX *mem_ctx)
3249 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3252 /*******************************************************************
3253 Fill a notify_info_data with submitted time.
3254 ********************************************************************/
3256 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3258 struct spoolss_Notify *data,
3259 print_queue_struct *queue,
3260 struct spoolss_PrinterInfo2 *pinfo2,
3261 TALLOC_CTX *mem_ctx)
3263 data->data.string.string = NULL;
3264 data->data.string.size = 0;
3266 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3267 &data->data.string.string,
3268 &data->data.string.size);
3272 struct s_notify_info_data_table
3274 enum spoolss_NotifyType type;
3277 enum spoolss_NotifyTable variable_type;
3278 void (*fn) (struct messaging_context *msg_ctx,
3279 int snum, struct spoolss_Notify *data,
3280 print_queue_struct *queue,
3281 struct spoolss_PrinterInfo2 *pinfo2,
3282 TALLOC_CTX *mem_ctx);
3285 /* A table describing the various print notification constants and
3286 whether the notification data is a pointer to a variable sized
3287 buffer, a one value uint32_t or a two value uint32_t. */
3289 static const struct s_notify_info_data_table notify_info_data_table[] =
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3298 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3299 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3300 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3301 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3302 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3303 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3304 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3305 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3306 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3307 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3308 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3309 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3310 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3311 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3312 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3313 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3314 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3315 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3316 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3321 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3322 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3323 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3324 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3325 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3326 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3327 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3328 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3329 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3330 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3331 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3332 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3333 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3334 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3335 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3336 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3337 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3338 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3339 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3342 /*******************************************************************
3343 Return the variable_type of info_data structure.
3344 ********************************************************************/
3346 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3351 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3352 if ( (notify_info_data_table[i].type == type) &&
3353 (notify_info_data_table[i].field == field) ) {
3354 return notify_info_data_table[i].variable_type;
3358 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3360 return (enum spoolss_NotifyTable) 0;
3363 /****************************************************************************
3364 ****************************************************************************/
3366 static bool search_notify(enum spoolss_NotifyType type,
3372 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3373 if (notify_info_data_table[i].type == type &&
3374 notify_info_data_table[i].field == field &&
3375 notify_info_data_table[i].fn != NULL) {
3384 /****************************************************************************
3385 ****************************************************************************/
3387 static void construct_info_data(struct spoolss_Notify *info_data,
3388 enum spoolss_NotifyType type,
3389 uint16_t field, int id)
3391 info_data->type = type;
3392 info_data->field.field = field;
3393 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3394 info_data->job_id = id;
3397 /*******************************************************************
3399 * fill a notify_info struct with info asked
3401 ********************************************************************/
3403 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3404 struct printer_handle *print_hnd,
3405 struct spoolss_NotifyInfo *info,
3406 struct spoolss_PrinterInfo2 *pinfo2,
3408 const struct spoolss_NotifyOptionType *option_type,
3410 TALLOC_CTX *mem_ctx)
3412 const struct loadparm_substitution *lp_sub =
3413 loadparm_s3_global_substitution();
3415 enum spoolss_NotifyType type;
3418 struct spoolss_Notify *current_data;
3420 type = option_type->type;
3422 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3423 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3424 option_type->count, lp_servicename(talloc_tos(), lp_sub, snum)));
3426 for(field_num=0; field_num < option_type->count; field_num++) {
3427 field = option_type->fields[field_num].field;
3429 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3431 if (!search_notify(type, field, &j) )
3434 info->notifies = talloc_realloc(info, info->notifies,
3435 struct spoolss_Notify,
3437 if (info->notifies == NULL) {
3438 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3442 current_data = &info->notifies[info->count];
3444 construct_info_data(current_data, type, field, id);
3446 DEBUG(10, ("construct_notify_printer_info: "
3447 "calling [%s] snum=%d printername=[%s])\n",
3448 notify_info_data_table[j].name, snum,
3449 pinfo2->printername));
3451 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3452 NULL, pinfo2, mem_ctx);
3460 /*******************************************************************
3462 * fill a notify_info struct with info asked
3464 ********************************************************************/
3466 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3467 print_queue_struct *queue,
3468 struct spoolss_NotifyInfo *info,
3469 struct spoolss_PrinterInfo2 *pinfo2,
3471 const struct spoolss_NotifyOptionType *option_type,
3473 TALLOC_CTX *mem_ctx)
3476 enum spoolss_NotifyType type;
3478 struct spoolss_Notify *current_data;
3480 DEBUG(4,("construct_notify_jobs_info\n"));
3482 type = option_type->type;
3484 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3485 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3486 option_type->count));
3488 for(field_num=0; field_num<option_type->count; field_num++) {
3489 field = option_type->fields[field_num].field;
3491 if (!search_notify(type, field, &j) )
3494 info->notifies = talloc_realloc(info, info->notifies,
3495 struct spoolss_Notify,
3497 if (info->notifies == NULL) {
3498 DEBUG(2,("construct_notify_jobs_info: failed to enlarge buffer info->data!\n"));
3502 current_data=&(info->notifies[info->count]);
3504 construct_info_data(current_data, type, field, id);
3505 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3506 queue, pinfo2, mem_ctx);
3514 * JFM: The enumeration is not that simple, it's even non obvious.
3516 * let's take an example: I want to monitor the PRINTER SERVER for
3517 * the printer's name and the number of jobs currently queued.
3518 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3519 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3521 * I have 3 printers on the back of my server.
3523 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3526 * 1 printer 1 name 1
3527 * 2 printer 1 cjob 1
3528 * 3 printer 2 name 2
3529 * 4 printer 2 cjob 2
3530 * 5 printer 3 name 3
3531 * 6 printer 3 name 3
3533 * that's the print server case, the printer case is even worse.
3536 /*******************************************************************
3538 * enumerate all printers on the printserver
3539 * fill a notify_info struct with info asked
3541 ********************************************************************/
3543 static WERROR printserver_notify_info(struct pipes_struct *p,
3544 struct policy_handle *hnd,
3545 struct spoolss_NotifyInfo *info,
3546 TALLOC_CTX *mem_ctx)
3548 const struct loadparm_substitution *lp_sub =
3549 loadparm_s3_global_substitution();
3551 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3552 int n_services=lp_numservices();
3554 struct spoolss_NotifyOption *option;
3555 struct spoolss_NotifyOptionType option_type;
3556 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3559 DEBUG(4,("printserver_notify_info\n"));
3562 return WERR_INVALID_HANDLE;
3564 option = Printer->notify.option;
3567 info->notifies = NULL;
3570 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3571 sending a ffpcn() request first */
3574 return WERR_INVALID_HANDLE;
3576 for (i=0; i<option->count; i++) {
3577 option_type = option->types[i];
3579 if (option_type.type != PRINTER_NOTIFY_TYPE)
3582 for (snum = 0; snum < n_services; snum++) {
3583 if (!lp_browseable(snum) ||
3584 !lp_snum_ok(snum) ||
3585 !lp_printable(snum)) {
3586 continue; /* skip */
3589 /* Maybe we should use the SYSTEM session_info here... */
3590 result = winreg_get_printer_internal(mem_ctx,
3591 get_session_info_system(),
3593 lp_servicename(talloc_tos(), lp_sub, snum),
3595 if (!W_ERROR_IS_OK(result)) {
3596 DEBUG(4, ("printserver_notify_info: "
3597 "Failed to get printer [%s]\n",
3598 lp_servicename(talloc_tos(), lp_sub, snum)));
3603 construct_notify_printer_info(p->msg_ctx,
3609 TALLOC_FREE(pinfo2);
3615 * Debugging information, don't delete.
3618 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3619 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3620 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3622 for (i=0; i<info->count; i++) {
3623 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3624 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3625 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3632 /*******************************************************************
3634 * fill a notify_info struct with info asked
3636 ********************************************************************/
3638 static WERROR printer_notify_info(struct pipes_struct *p,
3639 struct policy_handle *hnd,
3640 struct spoolss_NotifyInfo *info,
3641 TALLOC_CTX *mem_ctx)
3643 const struct loadparm_substitution *lp_sub =
3644 loadparm_s3_global_substitution();
3646 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3649 struct spoolss_NotifyOption *option;
3650 struct spoolss_NotifyOptionType option_type;
3652 print_queue_struct *queue=NULL;
3653 print_status_struct status;
3654 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3656 struct tdb_print_db *pdb;
3658 DEBUG(4,("printer_notify_info\n"));
3661 return WERR_INVALID_HANDLE;
3663 option = Printer->notify.option;
3667 info->notifies = NULL;
3670 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3671 sending a ffpcn() request first */
3674 return WERR_INVALID_HANDLE;
3676 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3677 return WERR_INVALID_HANDLE;
3680 pdb = get_print_db_byname(Printer->sharename);
3682 return WERR_INVALID_HANDLE;
3685 /* Maybe we should use the SYSTEM session_info here... */
3686 result = winreg_get_printer_internal(mem_ctx,
3687 get_session_info_system(),
3689 lp_servicename(talloc_tos(), lp_sub, snum), &pinfo2);
3690 if (!W_ERROR_IS_OK(result)) {
3691 result = WERR_INVALID_HANDLE;
3696 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3697 * correct servername.
3699 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3700 if (pinfo2->servername == NULL) {
3701 result = WERR_NOT_ENOUGH_MEMORY;
3705 for (i = 0; i < option->count; i++) {
3706 option_type = option->types[i];
3708 switch (option_type.type) {
3709 case PRINTER_NOTIFY_TYPE:
3710 if (construct_notify_printer_info(p->msg_ctx,
3719 case JOB_NOTIFY_TYPE:
3721 count = print_queue_status(p->msg_ctx, snum, &queue,
3724 for (j = 0; j < count; j++) {
3726 jobid = sysjob_to_jobid_pdb(pdb,
3728 if (jobid == (uint32_t)-1) {
3729 DEBUG(2, ("ignoring untracked job %d\n",
3733 /* FIXME check return value */
3734 construct_notify_jobs_info(p->msg_ctx,
3748 * Debugging information, don't delete.
3751 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3752 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3753 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3755 for (i=0; i<info->count; i++) {
3756 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3757 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3758 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3762 talloc_free(pinfo2);
3765 release_print_db(pdb);
3769 /****************************************************************
3770 _spoolss_RouterRefreshPrinterChangeNotify
3771 ****************************************************************/
3773 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3774 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3776 struct spoolss_NotifyInfo *info;
3778 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3779 WERROR result = WERR_INVALID_HANDLE;
3781 /* we always have a spoolss_NotifyInfo struct */
3782 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3784 result = WERR_NOT_ENOUGH_MEMORY;
3788 *r->out.info = info;
3791 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3792 "Invalid handle (%s:%u:%u).\n",
3793 OUR_HANDLE(r->in.handle)));
3797 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3800 * We are now using the change value, and
3801 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3802 * I don't have a global notification system, I'm sending back all the
3803 * information even when _NOTHING_ has changed.
3806 /* We need to keep track of the change value to send back in
3807 RRPCN replies otherwise our updates are ignored. */
3809 Printer->notify.fnpcn = true;
3811 if (Printer->notify.cli_chan != NULL &&
3812 Printer->notify.cli_chan->active_connections > 0) {
3813 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3814 "Saving change value in request [%x]\n",
3816 Printer->notify.change = r->in.change_low;
3819 /* just ignore the spoolss_NotifyOption */
3821 switch (Printer->printer_type) {
3823 result = printserver_notify_info(p, r->in.handle,
3827 case SPLHND_PRINTER:
3828 result = printer_notify_info(p, r->in.handle,
3833 Printer->notify.fnpcn = false;
3839 /********************************************************************
3840 ********************************************************************/
3842 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3843 const char *servername,
3844 const char *printername,
3845 const char **printername_p)
3847 /* FIXME: add lp_force_printername() */
3849 if (servername == NULL) {
3850 *printername_p = talloc_strdup(mem_ctx, printername);
3851 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3855 if (servername[0] == '\\' && servername[1] == '\\') {
3859 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3860 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3865 /********************************************************************
3866 ********************************************************************/
3868 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3869 const char *printername)
3875 dm->devicename = talloc_strndup(dm, printername,
3876 MIN(strlen(printername), 31));
3879 /********************************************************************
3880 * construct_printer_info_0
3881 * fill a printer_info_0 struct
3882 ********************************************************************/
3884 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3885 const struct auth_session_info *session_info,
3886 struct messaging_context *msg_ctx,
3887 struct spoolss_PrinterInfo2 *info2,
3888 const char *servername,
3889 struct spoolss_PrinterInfo0 *r,
3893 struct printer_session_counter *session_counter;
3894 struct timeval setuptime;
3895 print_status_struct status;
3897 int os_major, os_minor, os_build;
3898 const char *architecture;
3899 uint32_t processor_architecture, processor_type;
3901 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3902 if (!W_ERROR_IS_OK(result)) {
3907 r->servername = talloc_strdup(mem_ctx, servername);
3908 W_ERROR_HAVE_NO_MEMORY(r->servername);
3910 r->servername = NULL;
3913 count = print_queue_length(msg_ctx, snum, &status);
3915 /* check if we already have a counter for this printer */
3916 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3917 if (session_counter->snum == snum)
3921 /* it's the first time, add it to the list */
3922 if (session_counter == NULL) {
3923 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3924 W_ERROR_HAVE_NO_MEMORY(session_counter);
3925 session_counter->snum = snum;
3926 session_counter->counter = 0;
3927 DLIST_ADD(counter_list, session_counter);
3931 session_counter->counter++;
3937 get_startup_time(&setuptime);
3938 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3941 * the global_counter should be stored in a TDB as it's common to all the clients
3942 * and should be zeroed on samba startup
3944 r->global_counter = session_counter->counter;
3947 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3948 os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3949 "spoolss", "os_major",
3950 GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3951 os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3952 "spoolss", "os_minor",
3953 GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3954 os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3955 "spoolss", "os_build",
3956 GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3958 SCVAL(&r->version, 0, os_major);
3959 SCVAL(&r->version, 1, os_minor);
3960 SSVAL(&r->version, 2, os_build);
3962 architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3965 GLOBAL_SPOOLSS_ARCHITECTURE);
3967 if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3968 processor_architecture = PROCESSOR_ARCHITECTURE_AMD64;
3969 processor_type = PROCESSOR_AMD_X8664;
3970 } else if (strequal(architecture, SPOOLSS_ARCHITECTURE_ARM64)) {
3971 processor_architecture = PROCESSOR_ARCHITECTURE_ARM64;
3972 processor_type = PROCESSOR_ARM820;
3974 processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3975 processor_type = PROCESSOR_INTEL_PENTIUM;
3978 r->free_build = SPOOLSS_RELEASE_BUILD;
3980 r->max_spooling = 0;
3981 r->session_counter = session_counter->counter;
3982 r->num_error_out_of_paper = 0x0;
3983 r->num_error_not_ready = 0x0; /* number of print failure */
3985 r->number_of_processors = 0x1;
3986 r->processor_type = processor_type;
3987 r->high_part_total_bytes = 0x0;
3989 /* ChangeID in milliseconds*/
3990 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3991 info2->sharename, &r->change_id);
3993 r->last_error = WERR_OK;
3994 r->status = nt_printq_status(status.status);
3995 r->enumerate_network_printers = 0x0;
3996 r->c_setprinter = 0x0;
3997 r->processor_architecture = processor_architecture;
3998 r->processor_level = 0x6; /* 6 ???*/
4007 /********************************************************************
4008 * construct_printer_info1
4009 * fill a spoolss_PrinterInfo1 struct
4010 ********************************************************************/
4012 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
4013 const struct spoolss_PrinterInfo2 *info2,
4015 const char *servername,
4016 struct spoolss_PrinterInfo1 *r,
4019 const struct loadparm_substitution *lp_sub =
4020 loadparm_s3_global_substitution();
4025 if (info2->comment == NULL || info2->comment[0] == '\0') {
4026 r->comment = lp_comment(mem_ctx, lp_sub, snum);
4028 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4030 W_ERROR_HAVE_NO_MEMORY(r->comment);
4032 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4033 if (!W_ERROR_IS_OK(result)) {
4037 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4041 W_ERROR_HAVE_NO_MEMORY(r->description);
4046 /********************************************************************
4047 * construct_printer_info2
4048 * fill a spoolss_PrinterInfo2 struct
4049 ********************************************************************/
4051 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4052 struct messaging_context *msg_ctx,
4053 const struct spoolss_PrinterInfo2 *info2,
4054 const char *servername,
4055 struct spoolss_PrinterInfo2 *r,
4058 const struct loadparm_substitution *lp_sub =
4059 loadparm_s3_global_substitution();
4061 print_status_struct status;
4064 count = print_queue_length(msg_ctx, snum, &status);
4067 r->servername = talloc_strdup(mem_ctx, servername);
4068 W_ERROR_HAVE_NO_MEMORY(r->servername);
4070 r->servername = NULL;
4073 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4074 if (!W_ERROR_IS_OK(result)) {
4078 r->sharename = lp_servicename(mem_ctx, lp_sub, snum);
4079 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4080 r->portname = talloc_strdup(mem_ctx, info2->portname);
4081 W_ERROR_HAVE_NO_MEMORY(r->portname);
4082 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4083 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4085 if (info2->comment[0] == '\0') {
4086 r->comment = lp_comment(mem_ctx, lp_sub, snum);
4088 r->comment = talloc_strdup(mem_ctx, info2->comment);
4090 W_ERROR_HAVE_NO_MEMORY(r->comment);
4092 r->location = talloc_strdup(mem_ctx, info2->location);
4093 if (info2->location[0] == '\0') {
4094 const char *loc = NULL;
4097 nt_status = printer_list_get_printer(mem_ctx,
4102 if (NT_STATUS_IS_OK(nt_status)) {
4104 r->location = talloc_strdup(mem_ctx, loc);
4108 W_ERROR_HAVE_NO_MEMORY(r->location);
4110 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4111 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4112 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4113 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4114 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4115 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4116 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4117 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4119 r->attributes = info2->attributes;
4121 r->priority = info2->priority;
4122 r->defaultpriority = info2->defaultpriority;
4123 r->starttime = info2->starttime;
4124 r->untiltime = info2->untiltime;
4125 r->status = nt_printq_status(status.status);
4127 r->averageppm = info2->averageppm;
4129 if (info2->devmode != NULL) {
4130 result = copy_devicemode(mem_ctx,
4133 if (!W_ERROR_IS_OK(result)) {
4136 } else if (lp_default_devmode(snum)) {
4137 result = spoolss_create_default_devmode(mem_ctx,
4140 if (!W_ERROR_IS_OK(result)) {
4145 DEBUG(8,("Returning NULL Devicemode!\n"));
4148 compose_devicemode_devicename(r->devmode, r->printername);
4152 if (info2->secdesc != NULL) {
4153 /* don't use talloc_steal() here unless you do a deep steal of all
4154 the SEC_DESC members */
4156 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4157 if (r->secdesc == NULL) {
4158 return WERR_NOT_ENOUGH_MEMORY;
4165 /********************************************************************
4166 * construct_printer_info3
4167 * fill a spoolss_PrinterInfo3 struct
4168 ********************************************************************/
4170 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4171 const struct spoolss_PrinterInfo2 *info2,
4172 const char *servername,
4173 struct spoolss_PrinterInfo3 *r,
4176 /* These are the components of the SD we are returning. */
4178 if (info2->secdesc != NULL) {
4179 /* don't use talloc_steal() here unless you do a deep steal of all
4180 the SEC_DESC members */
4182 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4183 if (r->secdesc == NULL) {
4184 return WERR_NOT_ENOUGH_MEMORY;
4191 /********************************************************************
4192 * construct_printer_info4
4193 * fill a spoolss_PrinterInfo4 struct
4194 ********************************************************************/
4196 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4197 const struct spoolss_PrinterInfo2 *info2,
4198 const char *servername,
4199 struct spoolss_PrinterInfo4 *r,
4204 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4205 if (!W_ERROR_IS_OK(result)) {
4210 r->servername = talloc_strdup(mem_ctx, servername);
4211 W_ERROR_HAVE_NO_MEMORY(r->servername);
4213 r->servername = NULL;
4216 r->attributes = info2->attributes;
4221 /********************************************************************
4222 * construct_printer_info5
4223 * fill a spoolss_PrinterInfo5 struct
4224 ********************************************************************/
4226 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4227 const struct spoolss_PrinterInfo2 *info2,
4228 const char *servername,
4229 struct spoolss_PrinterInfo5 *r,
4234 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4235 if (!W_ERROR_IS_OK(result)) {
4239 r->portname = talloc_strdup(mem_ctx, info2->portname);
4240 W_ERROR_HAVE_NO_MEMORY(r->portname);
4242 r->attributes = info2->attributes;
4245 * These two are not used by NT+ according to MSDN. However the values
4246 * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4248 r->device_not_selected_timeout = 0xafc8; /* 45 sec */
4249 r->transmission_retry_timeout = 0xafc8; /* 45 sec */
4254 /********************************************************************
4255 * construct_printer_info_6
4256 * fill a spoolss_PrinterInfo6 struct
4257 ********************************************************************/
4259 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4260 struct messaging_context *msg_ctx,
4261 const struct spoolss_PrinterInfo2 *info2,
4262 const char *servername,
4263 struct spoolss_PrinterInfo6 *r,
4266 print_status_struct status;
4268 print_queue_length(msg_ctx, snum, &status);
4270 r->status = nt_printq_status(status.status);
4275 /********************************************************************
4276 * construct_printer_info7
4277 * fill a spoolss_PrinterInfo7 struct
4278 ********************************************************************/
4280 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4281 struct messaging_context *msg_ctx,
4282 const char *servername,
4283 struct spoolss_PrinterInfo7 *r,
4286 const struct loadparm_substitution *lp_sub =
4287 loadparm_s3_global_substitution();
4288 const struct auth_session_info *session_info;
4289 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4292 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4293 if (tmp_ctx == NULL) {
4294 return WERR_NOT_ENOUGH_MEMORY;
4297 session_info = get_session_info_system();
4298 SMB_ASSERT(session_info != NULL);
4300 printer = lp_servicename(tmp_ctx, lp_sub, snum);
4301 if (printer == NULL) {
4302 DEBUG(0, ("invalid printer snum %d\n", snum));
4303 werr = WERR_INVALID_PARAMETER;
4307 if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4308 servername, printer, &pinfo2)) {
4311 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4313 if (!W_ERROR_IS_OK(werr)) {
4315 * If we do not have a GUID entry in the registry, then
4316 * try to retrieve it from AD and store it now.
4318 werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4320 if (!W_ERROR_IS_OK(werr)) {
4321 DBG_NOTICE("Failed to retrieve GUID for "
4322 "printer [%s] from AD - %s\n",
4325 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4327 * If we did not find it in AD, then it
4328 * is unpublished and we should reflect
4329 * this in the registry and return
4332 DBG_WARNING("Unpublish printer [%s]\n",
4334 nt_printer_publish(tmp_ctx,
4339 r->guid = talloc_strdup(mem_ctx, "");
4340 r->action = DSPRINT_UNPUBLISH;
4342 if (r->guid == NULL) {
4343 werr = WERR_NOT_ENOUGH_MEMORY;
4351 werr = nt_printer_guid_store(msg_ctx, printer, guid);
4352 if (!W_ERROR_IS_OK(werr)) {
4353 DEBUG(3, ("failed to store printer %s guid\n",
4358 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4359 guidstr = GUID_string2(mem_ctx, &guid);
4360 if (guidstr == NULL) {
4361 werr = WERR_NOT_ENOUGH_MEMORY;
4364 /* Convert GUID string to uppercase otherwise printers
4366 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4367 r->action = DSPRINT_PUBLISH;
4369 TALLOC_FREE(guidstr);
4371 r->guid = talloc_strdup(mem_ctx, "");
4372 r->action = DSPRINT_UNPUBLISH;
4374 if (r->guid == NULL) {
4375 werr = WERR_NOT_ENOUGH_MEMORY;
4381 talloc_free(tmp_ctx);
4385 /********************************************************************
4386 * construct_printer_info8
4387 * fill a spoolss_PrinterInfo8 struct
4388 ********************************************************************/
4390 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4391 const struct spoolss_PrinterInfo2 *info2,
4392 const char *servername,
4393 struct spoolss_DeviceModeInfo *r,
4397 const char *printername;
4399 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4400 if (!W_ERROR_IS_OK(result)) {
4404 if (info2->devmode != NULL) {
4405 result = copy_devicemode(mem_ctx,
4408 if (!W_ERROR_IS_OK(result)) {
4411 } else if (lp_default_devmode(snum)) {
4412 result = spoolss_create_default_devmode(mem_ctx,
4415 if (!W_ERROR_IS_OK(result)) {
4420 DEBUG(8,("Returning NULL Devicemode!\n"));
4423 compose_devicemode_devicename(r->devmode, printername);
4428 /********************************************************************
4429 Spoolss_enumprinters.
4430 ********************************************************************/
4432 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4433 const struct auth_session_info *session_info,
4434 struct messaging_context *msg_ctx,
4435 const char *servername,
4438 union spoolss_PrinterInfo **info_p,
4443 union spoolss_PrinterInfo *info = NULL;
4445 WERROR result = WERR_OK;
4446 struct dcerpc_binding_handle *b = NULL;
4447 TALLOC_CTX *tmp_ctx = NULL;
4449 tmp_ctx = talloc_new(mem_ctx);
4451 return WERR_NOT_ENOUGH_MEMORY;
4455 * printer shares are updated on client enumeration. The background
4456 * printer process updates printer_list.tdb at regular intervals.
4459 delete_and_reload_printers();
4462 n_services = lp_numservices();
4466 for (snum = 0; snum < n_services; snum++) {
4468 const char *printer;
4469 struct spoolss_PrinterInfo2 *info2;
4471 if (!snum_is_shared_printer(snum)) {
4475 printer = lp_const_servicename(snum);
4477 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4481 result = winreg_printer_binding_handle(tmp_ctx,
4485 if (!W_ERROR_IS_OK(result)) {
4490 result = winreg_create_printer(tmp_ctx, b,
4492 if (!W_ERROR_IS_OK(result)) {
4496 info = talloc_realloc(tmp_ctx, info,
4497 union spoolss_PrinterInfo,
4500 result = WERR_NOT_ENOUGH_MEMORY;
4504 result = winreg_get_printer(tmp_ctx, b,
4506 if (!W_ERROR_IS_OK(result)) {
4512 result = construct_printer_info0(info, session_info,
4515 &info[count].info0, snum);
4518 result = construct_printer_info1(info, info2, flags,
4520 &info[count].info1, snum);
4523 result = construct_printer_info2(info, msg_ctx, info2,
4525 &info[count].info2, snum);
4528 result = construct_printer_info4(info, info2,
4530 &info[count].info4, snum);
4533 result = construct_printer_info5(info, info2,
4535 &info[count].info5, snum);
4539 result = WERR_INVALID_LEVEL;
4543 if (!W_ERROR_IS_OK(result)) {
4551 if (W_ERROR_IS_OK(result)) {
4552 *info_p = talloc_move(mem_ctx, &info);
4556 talloc_free(tmp_ctx);
4561 /********************************************************************
4562 * handle enumeration of printers at level 0
4563 ********************************************************************/
4565 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4566 const struct auth_session_info *session_info,
4567 struct messaging_context *msg_ctx,
4569 const char *servername,
4570 union spoolss_PrinterInfo **info,
4573 DEBUG(4,("enum_all_printers_info_0\n"));
4575 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4576 servername, 0, flags, info, count);
4580 /********************************************************************
4581 ********************************************************************/
4583 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4584 const struct auth_session_info *session_info,
4585 struct messaging_context *msg_ctx,
4586 const char *servername,
4588 union spoolss_PrinterInfo **info,
4591 DEBUG(4,("enum_all_printers_info_1\n"));
4593 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4594 servername, 1, flags, info, count);
4597 /********************************************************************
4598 enum_all_printers_info_1_local.
4599 *********************************************************************/
4601 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4602 const struct auth_session_info *session_info,
4603 struct messaging_context *msg_ctx,
4604 const char *servername,
4605 union spoolss_PrinterInfo **info,
4608 DEBUG(4,("enum_all_printers_info_1_local\n"));
4610 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4611 servername, PRINTER_ENUM_ICON8, info, count);
4614 /********************************************************************
4615 enum_all_printers_info_1_name.
4616 *********************************************************************/
4618 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4619 const struct auth_session_info *session_info,
4620 struct messaging_context *msg_ctx,
4621 const char *servername,
4622 union spoolss_PrinterInfo **info,
4625 const char *s = servername;
4627 DEBUG(4,("enum_all_printers_info_1_name\n"));
4629 if (servername != NULL &&
4630 (servername[0] == '\\') && (servername[1] == '\\')) {
4634 if (!is_myname_or_ipaddr(s)) {
4635 return WERR_INVALID_NAME;
4638 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4639 servername, PRINTER_ENUM_ICON8, info, count);
4642 /********************************************************************
4643 enum_all_printers_info_1_network.
4644 *********************************************************************/
4646 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4647 const struct auth_session_info *session_info,
4648 struct messaging_context *msg_ctx,
4649 const char *servername,
4650 union spoolss_PrinterInfo **info,
4653 const char *s = servername;
4655 DEBUG(4,("enum_all_printers_info_1_network\n"));
4657 /* If we respond to a enum_printers level 1 on our name with flags
4658 set to PRINTER_ENUM_REMOTE with a list of printers then these
4659 printers incorrectly appear in the APW browse list.
4660 Specifically the printers for the server appear at the workgroup
4661 level where all the other servers in the domain are
4662 listed. Windows responds to this call with a
4663 WERR_CAN_NOT_COMPLETE so we should do the same. */
4665 if (servername != NULL &&
4666 (servername[0] == '\\') && (servername[1] == '\\')) {
4670 if (is_myname_or_ipaddr(s)) {
4671 return WERR_CAN_NOT_COMPLETE;
4674 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4675 servername, PRINTER_ENUM_NAME, info, count);
4678 /********************************************************************
4679 * api_spoolss_enumprinters
4681 * called from api_spoolss_enumprinters (see this to understand)
4682 ********************************************************************/
4684 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4685 const struct auth_session_info *session_info,
4686 struct messaging_context *msg_ctx,
4687 const char *servername,
4688 union spoolss_PrinterInfo **info,
4691 DEBUG(4,("enum_all_printers_info_2\n"));
4693 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4694 servername, 2, 0, info, count);
4697 /********************************************************************
4698 * handle enumeration of printers at level 1
4699 ********************************************************************/
4701 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4702 const struct auth_session_info *session_info,
4703 struct messaging_context *msg_ctx,
4705 const char *servername,
4706 union spoolss_PrinterInfo **info,
4709 /* Not all the flags are equals */
4711 if (flags & PRINTER_ENUM_LOCAL) {
4712 return enum_all_printers_info_1_local(mem_ctx, session_info,
4713 msg_ctx, servername, info, count);
4716 if (flags & PRINTER_ENUM_NAME) {
4717 return enum_all_printers_info_1_name(mem_ctx, session_info,
4718 msg_ctx, servername, info,
4722 if (flags & PRINTER_ENUM_NETWORK) {
4723 return enum_all_printers_info_1_network(mem_ctx, session_info,
4724 msg_ctx, servername, info,
4728 return WERR_OK; /* NT4sp5 does that */
4731 /********************************************************************
4732 * handle enumeration of printers at level 2
4733 ********************************************************************/
4735 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4736 const struct auth_session_info *session_info,
4737 struct messaging_context *msg_ctx,
4739 const char *servername,
4740 union spoolss_PrinterInfo **info,
4743 if (flags & PRINTER_ENUM_LOCAL) {
4745 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4750 if (flags & PRINTER_ENUM_NAME) {
4751 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4752 return WERR_INVALID_NAME;
4755 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4760 if (flags & PRINTER_ENUM_REMOTE) {
4761 return WERR_INVALID_LEVEL;
4767 /********************************************************************
4768 * handle enumeration of printers at level 4
4769 ********************************************************************/
4771 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4772 const struct auth_session_info *session_info,
4773 struct messaging_context *msg_ctx,
4775 const char *servername,
4776 union spoolss_PrinterInfo **info,
4779 DEBUG(4,("enum_all_printers_info_4\n"));
4781 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4782 servername, 4, flags, info, count);
4786 /********************************************************************
4787 * handle enumeration of printers at level 5
4788 ********************************************************************/
4790 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4791 const struct auth_session_info *session_info,
4792 struct messaging_context *msg_ctx,
4794 const char *servername,
4795 union spoolss_PrinterInfo **info,
4798 DEBUG(4,("enum_all_printers_info_5\n"));
4800 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4801 servername, 5, flags, info, count);
4804 /****************************************************************
4805 _spoolss_EnumPrinters
4806 ****************************************************************/
4808 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4809 struct spoolss_EnumPrinters *r)
4811 const struct auth_session_info *session_info = get_session_info_system();
4814 /* that's an [in out] buffer */
4816 if (!r->in.buffer && (r->in.offered != 0)) {
4817 return WERR_INVALID_PARAMETER;
4820 DEBUG(4,("_spoolss_EnumPrinters\n"));
4824 *r->out.info = NULL;
4828 * flags==PRINTER_ENUM_NAME
4829 * if name=="" then enumerates all printers
4830 * if name!="" then enumerate the printer
4831 * flags==PRINTER_ENUM_REMOTE
4832 * name is NULL, enumerate printers
4833 * Level 2: name!="" enumerates printers, name can't be NULL
4834 * Level 3: doesn't exist
4835 * Level 4: does a local registry lookup
4836 * Level 5: same as Level 2
4839 if (r->in.server && r->in.server[0] == '\0') {
4840 r->in.server = NULL;
4843 switch (r->in.level) {
4845 result = enumprinters_level0(p->mem_ctx, session_info,
4846 p->msg_ctx, r->in.flags,
4848 r->out.info, r->out.count);
4851 result = enumprinters_level1(p->mem_ctx, session_info,
4852 p->msg_ctx, r->in.flags,
4854 r->out.info, r->out.count);
4857 result = enumprinters_level2(p->mem_ctx, session_info,
4858 p->msg_ctx, r->in.flags,
4860 r->out.info, r->out.count);
4863 result = enumprinters_level4(p->mem_ctx, session_info,
4864 p->msg_ctx, r->in.flags,
4866 r->out.info, r->out.count);
4869 result = enumprinters_level5(p->mem_ctx, session_info,
4870 p->msg_ctx, r->in.flags,
4872 r->out.info, r->out.count);
4875 return WERR_INVALID_LEVEL;
4878 if (!W_ERROR_IS_OK(result)) {
4882 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4883 spoolss_EnumPrinters,
4884 *r->out.info, r->in.level,
4886 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4887 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4889 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4892 /****************************************************************
4894 ****************************************************************/
4896 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4897 struct spoolss_GetPrinter *r)
4899 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4900 struct spoolss_PrinterInfo2 *info2 = NULL;
4901 WERROR result = WERR_OK;
4904 /* that's an [in out] buffer */
4906 if (!r->in.buffer && (r->in.offered != 0)) {
4907 result = WERR_INVALID_PARAMETER;
4913 if (Printer == NULL) {
4914 result = WERR_INVALID_HANDLE;
4918 if (Printer->printer_type == SPLHND_SERVER) {
4920 struct dcerpc_binding_handle *b;
4922 if (r->in.level != 3) {
4923 result = WERR_INVALID_LEVEL;
4927 result = winreg_printer_binding_handle(p->mem_ctx,
4928 get_session_info_system(),
4931 if (!W_ERROR_IS_OK(result)) {
4935 result = winreg_get_printserver_secdesc(p->mem_ctx,
4937 &r->out.info->info3.secdesc);
4938 if (!W_ERROR_IS_OK(result)) {
4945 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4946 result = WERR_INVALID_HANDLE;
4950 result = winreg_get_printer_internal(p->mem_ctx,
4951 get_session_info_system(),
4953 lp_const_servicename(snum),
4955 if (!W_ERROR_IS_OK(result)) {
4959 switch (r->in.level) {
4961 result = construct_printer_info0(p->mem_ctx,
4962 get_session_info_system(),
4965 Printer->servername,
4966 &r->out.info->info0,
4970 result = construct_printer_info1(p->mem_ctx, info2,
4972 Printer->servername,
4973 &r->out.info->info1, snum);
4976 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4977 Printer->servername,
4978 &r->out.info->info2, snum);
4981 result = construct_printer_info3(p->mem_ctx, info2,
4982 Printer->servername,
4983 &r->out.info->info3, snum);
4986 result = construct_printer_info4(p->mem_ctx, info2,
4987 Printer->servername,
4988 &r->out.info->info4, snum);
4991 result = construct_printer_info5(p->mem_ctx, info2,
4992 Printer->servername,
4993 &r->out.info->info5, snum);
4996 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4997 Printer->servername,
4998 &r->out.info->info6, snum);
5001 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
5002 Printer->servername,
5003 &r->out.info->info7, snum);
5006 result = construct_printer_info8(p->mem_ctx, info2,
5007 Printer->servername,
5008 &r->out.info->info8, snum);
5011 result = WERR_INVALID_LEVEL;
5016 if (!W_ERROR_IS_OK(result)) {
5017 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
5018 r->in.level, win_errstr(result)));
5022 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
5023 r->out.info, r->in.level);
5024 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5026 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5029 TALLOC_FREE(r->out.info);
5033 /********************************************************************
5034 ********************************************************************/
5036 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
5038 if (in && strlen(in)) { \
5039 out = talloc_strdup(mem_ctx, in); \
5041 out = talloc_strdup(mem_ctx, ""); \
5043 W_ERROR_HAVE_NO_MEMORY(out); \
5046 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
5048 if (in && strlen(in)) { \
5049 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
5051 out = talloc_strdup(mem_ctx, ""); \
5053 W_ERROR_HAVE_NO_MEMORY(out); \
5056 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
5057 const char **string_array,
5058 const char ***presult,
5059 const char *cservername,
5064 size_t num_strings = 0;
5065 const char **array = NULL;
5067 if (string_array == NULL) {
5068 return WERR_INVALID_PARAMETER;
5071 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5072 const char *str = NULL;
5074 if (cservername == NULL || arch == NULL) {
5075 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5077 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5080 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5082 return WERR_NOT_ENOUGH_MEMORY;
5087 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5088 &array, &num_strings);
5091 if (presult != NULL) {
5100 /********************************************************************
5101 * fill a spoolss_DriverInfo1 struct
5102 ********************************************************************/
5104 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5105 struct spoolss_DriverInfo1 *r,
5106 const struct spoolss_DriverInfo8 *driver,
5107 const char *servername)
5109 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5110 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5115 /********************************************************************
5116 * fill a spoolss_DriverInfo2 struct
5117 ********************************************************************/
5119 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5120 struct spoolss_DriverInfo2 *r,
5121 const struct spoolss_DriverInfo8 *driver,
5122 const char *servername)
5125 const char *cservername = canon_servername(servername);
5127 r->version = driver->version;
5129 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5130 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5131 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5132 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5134 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5135 driver->architecture,
5137 driver->driver_path,
5140 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5141 driver->architecture,
5146 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5147 driver->architecture,
5149 driver->config_file,
5155 /********************************************************************
5156 * fill a spoolss_DriverInfo3 struct
5157 ********************************************************************/
5159 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5160 struct spoolss_DriverInfo3 *r,
5161 const struct spoolss_DriverInfo8 *driver,
5162 const char *servername)
5164 const char *cservername = canon_servername(servername);
5166 r->version = driver->version;
5168 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5169 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5170 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5171 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5173 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5174 driver->architecture,
5176 driver->driver_path,
5179 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5180 driver->architecture,
5185 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5186 driver->architecture,
5188 driver->config_file,
5191 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5192 driver->architecture,
5197 FILL_DRIVER_STRING(mem_ctx,
5198 driver->monitor_name,
5201 FILL_DRIVER_STRING(mem_ctx,
5202 driver->default_datatype,
5203 r->default_datatype);
5205 return string_array_from_driver_info(mem_ctx,
5206 driver->dependent_files,
5207 &r->dependent_files,
5209 driver->architecture,
5213 /********************************************************************
5214 * fill a spoolss_DriverInfo4 struct
5215 ********************************************************************/
5217 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5218 struct spoolss_DriverInfo4 *r,
5219 const struct spoolss_DriverInfo8 *driver,
5220 const char *servername)
5222 const char *cservername = canon_servername(servername);
5225 r->version = driver->version;
5227 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5228 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5229 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5230 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5232 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5233 driver->architecture,
5235 driver->driver_path,
5238 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5239 driver->architecture,
5244 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5245 driver->architecture,
5247 driver->config_file,
5250 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5251 driver->architecture,
5256 result = string_array_from_driver_info(mem_ctx,
5257 driver->dependent_files,
5258 &r->dependent_files,
5260 driver->architecture,
5262 if (!W_ERROR_IS_OK(result)) {
5266 FILL_DRIVER_STRING(mem_ctx,
5267 driver->monitor_name,
5270 FILL_DRIVER_STRING(mem_ctx,
5271 driver->default_datatype,
5272 r->default_datatype);
5275 result = string_array_from_driver_info(mem_ctx,
5276 driver->previous_names,
5283 /********************************************************************
5284 * fill a spoolss_DriverInfo5 struct
5285 ********************************************************************/
5287 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5288 struct spoolss_DriverInfo5 *r,
5289 const struct spoolss_DriverInfo8 *driver,
5290 const char *servername)
5292 const char *cservername = canon_servername(servername);
5294 r->version = driver->version;
5296 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5297 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5298 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5299 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5301 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5302 driver->architecture,
5304 driver->driver_path,
5307 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5308 driver->architecture,
5313 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5314 driver->architecture,
5316 driver->config_file,
5319 r->driver_attributes = 0;
5320 r->config_version = 0;
5321 r->driver_version = 0;
5325 /********************************************************************
5326 * fill a spoolss_DriverInfo6 struct
5327 ********************************************************************/
5329 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5330 struct spoolss_DriverInfo6 *r,
5331 const struct spoolss_DriverInfo8 *driver,
5332 const char *servername)
5334 const char *cservername = canon_servername(servername);
5337 r->version = driver->version;
5339 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5340 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5341 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5342 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5344 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5345 driver->architecture,
5347 driver->driver_path,
5350 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5351 driver->architecture,
5356 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5357 driver->architecture,
5359 driver->config_file,
5362 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5363 driver->architecture,
5368 FILL_DRIVER_STRING(mem_ctx,
5369 driver->monitor_name,
5372 FILL_DRIVER_STRING(mem_ctx,
5373 driver->default_datatype,
5374 r->default_datatype);
5376 result = string_array_from_driver_info(mem_ctx,
5377 driver->dependent_files,
5378 &r->dependent_files,
5380 driver->architecture,
5382 if (!W_ERROR_IS_OK(result)) {
5386 result = string_array_from_driver_info(mem_ctx,
5387 driver->previous_names,
5390 if (!W_ERROR_IS_OK(result)) {
5394 r->driver_date = driver->driver_date;
5395 r->driver_version = driver->driver_version;
5397 FILL_DRIVER_STRING(mem_ctx,
5398 driver->manufacturer_name,
5399 r->manufacturer_name);
5400 FILL_DRIVER_STRING(mem_ctx,
5401 driver->manufacturer_url,
5402 r->manufacturer_url);
5403 FILL_DRIVER_STRING(mem_ctx,
5404 driver->hardware_id,
5406 FILL_DRIVER_STRING(mem_ctx,
5413 /********************************************************************
5414 * fill a spoolss_DriverInfo8 struct
5415 ********************************************************************/
5417 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5418 struct spoolss_DriverInfo8 *r,
5419 const struct spoolss_DriverInfo8 *driver,
5420 const char *servername)
5422 const char *cservername = canon_servername(servername);
5425 r->version = driver->version;
5427 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5428 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5429 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5430 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5432 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5433 driver->architecture,
5435 driver->driver_path,
5438 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5439 driver->architecture,
5444 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5445 driver->architecture,
5447 driver->config_file,
5450 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5451 driver->architecture,
5456 FILL_DRIVER_STRING(mem_ctx,
5457 driver->monitor_name,
5460 FILL_DRIVER_STRING(mem_ctx,
5461 driver->default_datatype,
5462 r->default_datatype);
5464 result = string_array_from_driver_info(mem_ctx,
5465 driver->dependent_files,
5466 &r->dependent_files,
5468 driver->architecture,
5470 if (!W_ERROR_IS_OK(result)) {
5474 result = string_array_from_driver_info(mem_ctx,
5475 driver->previous_names,
5478 if (!W_ERROR_IS_OK(result)) {
5482 r->driver_date = driver->driver_date;
5483 r->driver_version = driver->driver_version;
5485 FILL_DRIVER_STRING(mem_ctx,
5486 driver->manufacturer_name,
5487 r->manufacturer_name);
5488 FILL_DRIVER_STRING(mem_ctx,
5489 driver->manufacturer_url,
5490 r->manufacturer_url);
5491 FILL_DRIVER_STRING(mem_ctx,
5492 driver->hardware_id,
5494 FILL_DRIVER_STRING(mem_ctx,
5498 FILL_DRIVER_STRING(mem_ctx,
5499 driver->print_processor,
5500 r->print_processor);
5501 FILL_DRIVER_STRING(mem_ctx,
5502 driver->vendor_setup,
5505 result = string_array_from_driver_info(mem_ctx,
5506 driver->color_profiles,
5509 if (!W_ERROR_IS_OK(result)) {
5513 FILL_DRIVER_STRING(mem_ctx,
5517 r->printer_driver_attributes = driver->printer_driver_attributes;
5519 result = string_array_from_driver_info(mem_ctx,
5520 driver->core_driver_dependencies,
5521 &r->core_driver_dependencies,
5523 if (!W_ERROR_IS_OK(result)) {
5527 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5528 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5533 #if 0 /* disabled until marshalling issues are resolved - gd */
5534 /********************************************************************
5535 ********************************************************************/
5537 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5538 struct spoolss_DriverFileInfo *r,
5539 const char *cservername,
5540 const char *file_name,
5541 enum spoolss_DriverFileType file_type,
5542 uint32_t file_version)
5544 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5545 cservername, file_name);
5546 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5547 r->file_type = file_type;
5548 r->file_version = file_version;
5553 /********************************************************************
5554 ********************************************************************/
5556 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5557 const struct spoolss_DriverInfo8 *driver,
5558 const char *cservername,
5559 struct spoolss_DriverFileInfo **info_p,
5562 struct spoolss_DriverFileInfo *info = NULL;
5570 if (strlen(driver->driver_path)) {
5571 info = talloc_realloc(mem_ctx, info,
5572 struct spoolss_DriverFileInfo,
5574 W_ERROR_HAVE_NO_MEMORY(info);
5575 result = fill_spoolss_DriverFileInfo(info,
5578 driver->driver_path,
5579 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5581 W_ERROR_NOT_OK_RETURN(result);
5585 if (strlen(driver->config_file)) {
5586 info = talloc_realloc(mem_ctx, info,
5587 struct spoolss_DriverFileInfo,
5589 W_ERROR_HAVE_NO_MEMORY(info);
5590 result = fill_spoolss_DriverFileInfo(info,
5593 driver->config_file,
5594 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5596 W_ERROR_NOT_OK_RETURN(result);
5600 if (strlen(driver->data_file)) {
5601 info = talloc_realloc(mem_ctx, info,
5602 struct spoolss_DriverFileInfo,
5604 W_ERROR_HAVE_NO_MEMORY(info);
5605 result = fill_spoolss_DriverFileInfo(info,
5609 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5611 W_ERROR_NOT_OK_RETURN(result);
5615 if (strlen(driver->help_file)) {
5616 info = talloc_realloc(mem_ctx, info,
5617 struct spoolss_DriverFileInfo,
5619 W_ERROR_HAVE_NO_MEMORY(info);
5620 result = fill_spoolss_DriverFileInfo(info,
5624 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5626 W_ERROR_NOT_OK_RETURN(result);
5630 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5631 info = talloc_realloc(mem_ctx, info,
5632 struct spoolss_DriverFileInfo,
5634 W_ERROR_HAVE_NO_MEMORY(info);
5635 result = fill_spoolss_DriverFileInfo(info,
5638 driver->dependent_files[i],
5639 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5641 W_ERROR_NOT_OK_RETURN(result);
5651 /********************************************************************
5652 * fill a spoolss_DriverInfo101 struct
5653 ********************************************************************/
5655 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5656 struct spoolss_DriverInfo101 *r,
5657 const struct spoolss_DriverInfo8 *driver,
5658 const char *servername)
5660 const char *cservername = canon_servername(servername);
5663 r->version = driver->version;
5665 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5666 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5667 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5668 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5670 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5674 if (!W_ERROR_IS_OK(result)) {
5678 FILL_DRIVER_STRING(mem_ctx,
5679 driver->monitor_name,
5682 FILL_DRIVER_STRING(mem_ctx,
5683 driver->default_datatype,
5684 r->default_datatype);
5686 result = string_array_from_driver_info(mem_ctx,
5687 driver->previous_names,
5690 if (!W_ERROR_IS_OK(result)) {
5694 r->driver_date = driver->driver_date;
5695 r->driver_version = driver->driver_version;
5697 FILL_DRIVER_STRING(mem_ctx,
5698 driver->manufacturer_name,
5699 r->manufacturer_name);
5700 FILL_DRIVER_STRING(mem_ctx,
5701 driver->manufacturer_url,
5702 r->manufacturer_url);
5703 FILL_DRIVER_STRING(mem_ctx,
5704 driver->hardware_id,
5706 FILL_DRIVER_STRING(mem_ctx,
5713 /********************************************************************
5714 ********************************************************************/
5716 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5717 const struct auth_session_info *session_info,
5718 struct messaging_context *msg_ctx,
5720 union spoolss_DriverInfo *r,
5722 const char *servername,
5723 const char *architecture,
5726 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5727 struct spoolss_DriverInfo8 *driver;
5729 struct dcerpc_binding_handle *b;
5730 TALLOC_CTX *tmp_ctx = NULL;
5733 return WERR_INVALID_LEVEL;
5736 tmp_ctx = talloc_new(mem_ctx);
5738 return WERR_NOT_ENOUGH_MEMORY;
5741 result = winreg_printer_binding_handle(tmp_ctx,
5745 if (!W_ERROR_IS_OK(result)) {
5749 result = winreg_get_printer(tmp_ctx, b,
5750 lp_const_servicename(snum),
5752 if (!W_ERROR_IS_OK(result)) {
5753 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5754 lp_const_servicename(snum), win_errstr(result));
5755 result = WERR_INVALID_PRINTER_NAME;
5759 if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5760 result = WERR_UNKNOWN_PRINTER_DRIVER;
5764 DBG_INFO("Construct printer driver [%s] for [%s]\n",
5768 result = winreg_get_driver(tmp_ctx, b,
5770 pinfo2->drivername, version, &driver);
5772 DBG_INFO("winreg_get_driver() status: %s\n",
5773 win_errstr(result));
5775 if (!W_ERROR_IS_OK(result)) {
5777 * Is this a W2k client ?
5781 result = WERR_UNKNOWN_PRINTER_DRIVER;
5785 /* Yes - try again with a WinNT driver. */
5787 result = winreg_get_driver(tmp_ctx, b,
5791 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5792 win_errstr(result)));
5793 if (!W_ERROR_IS_OK(result)) {
5794 result = WERR_UNKNOWN_PRINTER_DRIVER;
5799 /* these are allocated on mem_ctx and not tmp_ctx because they are
5800 * the 'return value' and need to outlive this call */
5803 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5806 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5809 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5812 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5815 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5818 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5821 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5823 #if 0 /* disabled until marshalling issues are resolved - gd */
5825 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5829 result = WERR_INVALID_LEVEL;
5834 talloc_free(tmp_ctx);
5838 /****************************************************************
5839 _spoolss_GetPrinterDriver2
5840 ****************************************************************/
5842 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5843 struct spoolss_GetPrinterDriver2 *r)
5845 struct printer_handle *printer;
5847 uint32_t version = r->in.client_major_version;
5851 /* that's an [in out] buffer */
5853 if (!r->in.buffer && (r->in.offered != 0)) {
5854 result = WERR_INVALID_PARAMETER;
5858 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5860 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5861 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5862 result = WERR_INVALID_PRINTER_NAME;
5867 *r->out.server_major_version = 0;
5868 *r->out.server_minor_version = 0;
5870 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5871 result = WERR_INVALID_HANDLE;
5875 if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5876 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5877 "downgrading to v3\n"));
5878 version = SPOOLSS_DRIVER_VERSION_200X;
5881 result = construct_printer_driver_info_level(p->mem_ctx,
5882 get_session_info_system(),
5884 r->in.level, r->out.info,
5885 snum, printer->servername,
5888 if (!W_ERROR_IS_OK(result)) {
5892 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5893 r->out.info, r->in.level);
5894 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5896 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5899 TALLOC_FREE(r->out.info);
5904 /****************************************************************
5905 _spoolss_StartPagePrinter
5906 ****************************************************************/
5908 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5909 struct spoolss_StartPagePrinter *r)
5911 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5914 DEBUG(3,("_spoolss_StartPagePrinter: "
5915 "Error in startpageprinter printer handle\n"));
5916 return WERR_INVALID_HANDLE;
5919 Printer->page_started = true;
5923 /****************************************************************
5924 _spoolss_EndPagePrinter
5925 ****************************************************************/
5927 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5928 struct spoolss_EndPagePrinter *r)
5932 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5935 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5936 OUR_HANDLE(r->in.handle)));
5937 return WERR_INVALID_HANDLE;
5940 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5941 return WERR_INVALID_HANDLE;
5943 Printer->page_started = false;
5944 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5949 /****************************************************************
5950 _spoolss_StartDocPrinter
5951 ****************************************************************/
5953 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5954 struct spoolss_StartDocPrinter *r)
5956 struct dcesrv_call_state *dce_call = p->dce_call;
5957 struct dcesrv_connection *dcesrv_conn = dce_call->conn;
5958 const struct tsocket_address *remote_address =
5959 dcesrv_connection_get_remote_address(dcesrv_conn);
5960 struct auth_session_info *session_info =
5961 dcesrv_call_session_info(dce_call);
5962 struct spoolss_DocumentInfo1 *info_1;
5964 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5970 DEBUG(2,("_spoolss_StartDocPrinter: "
5971 "Invalid handle (%s:%u:%u)\n",
5972 OUR_HANDLE(r->in.handle)));
5973 return WERR_INVALID_HANDLE;
5976 if (Printer->jobid) {
5977 DEBUG(2, ("_spoolss_StartDocPrinter: "
5978 "StartDocPrinter called twice! "
5979 "(existing jobid = %d)\n", Printer->jobid));
5980 return WERR_INVALID_HANDLE;
5983 if (r->in.info_ctr->level != 1) {
5984 return WERR_INVALID_LEVEL;
5987 info_1 = r->in.info_ctr->info.info1;
5990 * a nice thing with NT is it doesn't listen to what you tell it.
5991 * when asked to send _only_ RAW data, it tries to send data
5994 * So I add checks like in NT Server ...
5997 if (info_1->datatype) {
5999 * The v4 driver model used in Windows 8 declares print jobs
6000 * intended to bypass the XPS processing layer by setting
6001 * datatype to "XPS_PASS" instead of "RAW".
6003 if ((strcmp(info_1->datatype, "RAW") != 0)
6004 && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
6006 return WERR_INVALID_DATATYPE;
6010 /* get the share number of the printer */
6011 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6012 return WERR_INVALID_HANDLE;
6015 rc = get_remote_hostname(remote_address,
6019 return WERR_NOT_ENOUGH_MEMORY;
6021 if (strequal(rhost,"UNKNOWN")) {
6022 rhost = tsocket_address_inet_addr_string(remote_address,
6024 if (rhost == NULL) {
6025 return WERR_NOT_ENOUGH_MEMORY;
6029 werr = print_job_start(session_info,
6033 info_1->document_name,
6034 info_1->output_file,
6038 /* An error occurred in print_job_start() so return an appropriate
6041 if (!W_ERROR_IS_OK(werr)) {
6045 Printer->document_started = true;
6046 *r->out.job_id = Printer->jobid;
6051 /****************************************************************
6052 _spoolss_EndDocPrinter
6053 ****************************************************************/
6055 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
6056 struct spoolss_EndDocPrinter *r)
6058 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6063 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
6064 OUR_HANDLE(r->in.handle)));
6065 return WERR_INVALID_HANDLE;
6068 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6069 return WERR_INVALID_HANDLE;
6072 Printer->document_started = false;
6073 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6074 if (!NT_STATUS_IS_OK(status)) {
6075 DEBUG(2, ("_spoolss_EndDocPrinter: "
6076 "print_job_end failed [%s]\n",
6077 nt_errstr(status)));
6081 return ntstatus_to_werror(status);
6084 /****************************************************************
6085 _spoolss_WritePrinter
6086 ****************************************************************/
6088 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6089 struct spoolss_WritePrinter *r)
6091 ssize_t buffer_written;
6093 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6096 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6097 OUR_HANDLE(r->in.handle)));
6098 *r->out.num_written = r->in._data_size;
6099 return WERR_INVALID_HANDLE;
6102 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6103 return WERR_INVALID_HANDLE;
6105 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6106 buffer_written = print_job_write(global_event_context(),p->msg_ctx,
6107 snum, Printer->jobid,
6108 (const char *)r->in.data.data,
6109 (size_t)r->in._data_size);
6110 if (buffer_written == (ssize_t)-1) {
6111 *r->out.num_written = 0;
6112 if (errno == ENOSPC)
6113 return WERR_NO_SPOOL_SPACE;
6115 return WERR_ACCESS_DENIED;
6118 *r->out.num_written = r->in._data_size;
6123 /********************************************************************
6124 * api_spoolss_getprinter
6125 * called from the spoolss dispatcher
6127 ********************************************************************/
6129 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6130 struct pipes_struct *p)
6132 struct dcesrv_call_state *dce_call = p->dce_call;
6133 struct auth_session_info *session_info =
6134 dcesrv_call_session_info(dce_call);
6136 WERROR errcode = WERR_INVALID_FUNCTION;
6137 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6140 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6141 OUR_HANDLE(handle)));
6142 return WERR_INVALID_HANDLE;
6145 if (!get_printer_snum(p, handle, &snum, NULL))
6146 return WERR_INVALID_HANDLE;
6149 case SPOOLSS_PRINTER_CONTROL_PAUSE:
6150 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6152 case SPOOLSS_PRINTER_CONTROL_RESUME:
6153 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6154 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6156 case SPOOLSS_PRINTER_CONTROL_PURGE:
6157 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6160 return WERR_INVALID_LEVEL;
6167 /****************************************************************
6168 _spoolss_AbortPrinter
6169 * From MSDN: "Deletes printer's spool file if printer is configured
6171 ****************************************************************/
6173 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6174 struct spoolss_AbortPrinter *r)
6176 struct dcesrv_call_state *dce_call = p->dce_call;
6177 struct auth_session_info *session_info =
6178 dcesrv_call_session_info(dce_call);
6179 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6181 WERROR errcode = WERR_OK;
6184 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6185 OUR_HANDLE(r->in.handle)));
6186 return WERR_INVALID_HANDLE;
6189 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6190 return WERR_INVALID_HANDLE;
6192 if (!Printer->document_started) {
6193 return WERR_SPL_NO_STARTDOC;
6196 errcode = print_job_delete(session_info,
6204 /********************************************************************
6205 * called by spoolss_api_setprinter
6206 * when updating a printer description
6207 ********************************************************************/
6209 static WERROR update_printer_sec(struct policy_handle *handle,
6210 struct pipes_struct *p,
6211 struct sec_desc_buf *secdesc_ctr)
6213 struct spoolss_security_descriptor *new_secdesc = NULL;
6214 struct spoolss_security_descriptor *old_secdesc = NULL;
6215 const char *printer = NULL;
6218 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6219 struct dcerpc_binding_handle *b;
6220 TALLOC_CTX *tmp_ctx = NULL;
6224 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6225 OUR_HANDLE(handle)));
6227 result = WERR_INVALID_HANDLE;
6231 if (secdesc_ctr == NULL) {
6232 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6233 result = WERR_INVALID_PARAMETER;
6237 switch (Printer->printer_type) {
6240 case SPLHND_PRINTER:
6241 if (!get_printer_snum(p, handle, &snum, NULL)) {
6242 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6243 OUR_HANDLE(handle)));
6244 result = WERR_INVALID_HANDLE;
6247 printer = lp_const_servicename(snum);
6253 /* Check the user has permissions to change the security
6254 descriptor. By experimentation with two NT machines, the user
6255 requires Full Access to the printer to change security
6258 switch (Printer->printer_type) {
6260 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6262 case SPLHND_PRINTER:
6263 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6270 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6271 "(access_granted: 0x%08x)\n", Printer->access_granted));
6272 result = WERR_ACCESS_DENIED;
6276 tmp_ctx = talloc_new(p->mem_ctx);
6278 return WERR_NOT_ENOUGH_MEMORY;
6281 result = winreg_printer_binding_handle(tmp_ctx,
6282 get_session_info_system(),
6285 if (!W_ERROR_IS_OK(result)) {
6289 /* NT seems to like setting the security descriptor even though
6290 nothing may have actually changed. */
6292 if (printer != NULL) {
6293 result = winreg_get_printer_secdesc(tmp_ctx, b,
6297 result = winreg_get_printserver_secdesc(tmp_ctx, b,
6300 if (!W_ERROR_IS_OK(result)) {
6301 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6302 result = WERR_INVALID_HANDLE;
6306 if (DEBUGLEVEL >= 10) {
6307 struct dom_sid_buf buf;
6308 struct security_acl *the_acl;
6311 the_acl = old_secdesc->dacl;
6312 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6313 printer, the_acl->num_aces));
6315 for (i = 0; i < the_acl->num_aces; i++) {
6316 DEBUG(10, ("%s 0x%08x\n",
6318 &the_acl->aces[i].trustee,
6320 the_acl->aces[i].access_mask));
6323 the_acl = secdesc_ctr->sd->dacl;
6326 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6327 printer, the_acl->num_aces));
6329 for (i = 0; i < the_acl->num_aces; i++) {
6330 DEBUG(10, ("%s 0x%08x\n",
6332 &the_acl->aces[i].trustee,
6334 the_acl->aces[i].access_mask));
6337 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6341 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6342 if (new_secdesc == NULL) {
6343 result = WERR_NOT_ENOUGH_MEMORY;
6347 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6352 if (printer != NULL) {
6353 result = winreg_set_printer_secdesc(tmp_ctx, b,
6357 result = winreg_set_printserver_secdesc(tmp_ctx, b,
6362 talloc_free(tmp_ctx);
6366 /********************************************************************
6367 Canonicalize printer info from a client
6368 ********************************************************************/
6370 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6371 struct spoolss_SetPrinterInfo2 *info2,
6374 fstring printername;
6377 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6378 "portname=%s drivername=%s comment=%s location=%s\n",
6379 info2->servername, info2->printername, info2->sharename,
6380 info2->portname, info2->drivername, info2->comment,
6383 /* we force some elements to "correct" values */
6384 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6385 if (info2->servername == NULL) {
6388 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6389 if (info2->sharename == NULL) {
6393 /* check to see if we allow printername != sharename */
6394 if (lp_force_printername(snum)) {
6395 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6396 lp_netbios_name(), info2->sharename);
6398 /* make sure printername is in \\server\printername format */
6399 fstrcpy(printername, info2->printername);
6401 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6402 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6406 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6407 lp_netbios_name(), p);
6409 if (info2->printername == NULL) {
6413 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6414 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6419 /****************************************************************************
6420 ****************************************************************************/
6422 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6424 const struct loadparm_substitution *lp_sub =
6425 loadparm_s3_global_substitution();
6426 char *cmd = lp_addport_command(talloc_tos(), lp_sub);
6427 char *command = NULL;
6429 bool is_print_op = false;
6432 return WERR_ACCESS_DENIED;
6435 command = talloc_asprintf(ctx,
6436 "%s \"%s\" \"%s\"", cmd, portname, uri );
6438 return WERR_NOT_ENOUGH_MEMORY;
6442 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6444 DEBUG(10,("Running [%s]\n", command));
6446 /********* BEGIN SePrintOperatorPrivilege **********/
6451 ret = smbrun(command, NULL, NULL);
6456 /********* END SePrintOperatorPrivilege **********/
6458 DEBUGADD(10,("returned [%d]\n", ret));
6460 TALLOC_FREE(command);
6463 return WERR_ACCESS_DENIED;
6469 /****************************************************************************
6470 ****************************************************************************/
6472 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6476 * As we do not know if we are embedded in the file server process
6477 * or not, we have to pretend that all shares are in use.
6482 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6483 struct spoolss_SetPrinterInfo2 *info2,
6484 const char *remote_machine,
6485 struct messaging_context *msg_ctx)
6487 const struct loadparm_substitution *lp_sub =
6488 loadparm_s3_global_substitution();
6489 char *cmd = lp_addprinter_command(talloc_tos(), lp_sub);
6491 char *command = NULL;
6495 bool is_print_op = false;
6497 if (!remote_machine) {
6501 command = talloc_asprintf(ctx,
6502 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6503 cmd, info2->printername, info2->sharename,
6504 info2->portname, info2->drivername,
6505 info2->location, info2->comment, remote_machine);
6511 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6513 DEBUG(10,("Running [%s]\n", command));
6515 /********* BEGIN SePrintOperatorPrivilege **********/
6520 ret = smbrun(command, &fd, NULL);
6522 /* Tell everyone we updated smb.conf. */
6523 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6529 /********* END SePrintOperatorPrivilege **********/
6531 DEBUGADD(10,("returned [%d]\n", ret));
6533 TALLOC_FREE(command);
6541 /* reload our services immediately */
6543 reload_services(NULL, spoolss_conn_snum_used, false);
6547 /* Get lines and convert them back to dos-codepage */
6548 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6549 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6552 /* Set the portname to what the script says the portname should be. */
6553 /* but don't require anything to be return from the script exit a good error code */
6556 /* Set the portname to what the script says the portname should be. */
6557 info2->portname = talloc_strdup(ctx, qlines[0]);
6558 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6561 TALLOC_FREE(qlines);
6565 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6566 const struct auth_session_info *session_info,
6567 struct messaging_context *msg_ctx,
6569 struct spoolss_SetPrinterInfo2 *printer,
6570 struct spoolss_PrinterInfo2 *old_printer)
6572 bool force_update = (old_printer == NULL);
6573 const char *dnsdomname;
6574 const char *longname;
6575 const char *uncname;
6576 const char *spooling;
6578 WERROR result = WERR_OK;
6579 struct dcerpc_binding_handle *b;
6580 TALLOC_CTX *tmp_ctx;
6583 tmp_ctx = talloc_new(mem_ctx);
6585 return WERR_NOT_ENOUGH_MEMORY;
6588 result = winreg_printer_binding_handle(tmp_ctx,
6592 if (!W_ERROR_IS_OK(result)) {
6596 if (printer->drivername != NULL &&
6598 !strequal(printer->drivername, old_printer->drivername))) {
6599 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6601 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6602 result = WERR_INVALID_DATA;
6605 result = winreg_set_printer_dataex(tmp_ctx, b,
6607 SPOOL_DSSPOOLER_KEY,
6608 SPOOL_REG_DRIVERNAME,
6612 if (!W_ERROR_IS_OK(result)) {
6613 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6617 if (!force_update) {
6618 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6619 printer->drivername));
6621 notify_printer_driver(global_event_context(), msg_ctx,
6622 snum, printer->drivername ?
6623 printer->drivername : "");
6627 if (printer->comment != NULL &&
6629 !strequal(printer->comment, old_printer->comment))) {
6630 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6632 DEBUG(0, ("comment data corrupted\n"));
6633 result = WERR_INVALID_DATA;
6636 result = winreg_set_printer_dataex(tmp_ctx, b,
6638 SPOOL_DSSPOOLER_KEY,
6639 SPOOL_REG_DESCRIPTION,
6643 if (!W_ERROR_IS_OK(result)) {
6644 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6648 if (!force_update) {
6649 notify_printer_comment(global_event_context(), msg_ctx,
6650 snum, printer->comment ?
6651 printer->comment : "");
6655 if (printer->sharename != NULL &&
6657 !strequal(printer->sharename, old_printer->sharename))) {
6658 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6660 DEBUG(0, ("sharename data corrupted\n"));
6661 result = WERR_INVALID_DATA;
6664 result = winreg_set_printer_dataex(tmp_ctx, b,
6666 SPOOL_DSSPOOLER_KEY,
6667 SPOOL_REG_PRINTSHARENAME,
6671 if (!W_ERROR_IS_OK(result)) {
6672 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6676 if (!force_update) {
6677 notify_printer_sharename(global_event_context(),
6679 snum, printer->sharename ?
6680 printer->sharename : "");
6683 /* name change, purge any cache entries for the old */
6684 prune_printername_cache();
6687 if (printer->printername != NULL &&
6689 !strequal(printer->printername, old_printer->printername))) {
6692 p = strrchr(printer->printername, '\\' );
6696 p = printer->printername;
6699 ok = push_reg_sz(tmp_ctx, &buffer, p);
6701 DEBUG(0, ("printername data corrupted\n"));
6702 result = WERR_INVALID_DATA;
6705 result = winreg_set_printer_dataex(tmp_ctx, b,
6707 SPOOL_DSSPOOLER_KEY,
6708 SPOOL_REG_PRINTERNAME,
6712 if (!W_ERROR_IS_OK(result)) {
6713 DBG_ERR("Failed to set %s\n", SPOOL_REG_PRINTERNAME);
6717 if (!force_update) {
6718 notify_printer_printername(global_event_context(),
6719 msg_ctx, snum, p ? p : "");
6722 /* name change, purge any cache entries for the old */
6723 prune_printername_cache();
6726 if (printer->portname != NULL &&
6728 !strequal(printer->portname, old_printer->portname))) {
6729 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6731 DEBUG(0, ("portname data corrupted\n"));
6732 result = WERR_INVALID_DATA;
6735 result = winreg_set_printer_dataex(tmp_ctx, b,
6737 SPOOL_DSSPOOLER_KEY,
6742 if (!W_ERROR_IS_OK(result)) {
6743 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6747 if (!force_update) {
6748 notify_printer_port(global_event_context(),
6749 msg_ctx, snum, printer->portname ?
6750 printer->portname : "");
6754 if (printer->location != NULL &&
6756 !strequal(printer->location, old_printer->location))) {
6757 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6759 DEBUG(0, ("location data corrupted\n"));
6760 result = WERR_INVALID_DATA;
6763 result = winreg_set_printer_dataex(tmp_ctx, b,
6765 SPOOL_DSSPOOLER_KEY,
6770 if (!W_ERROR_IS_OK(result)) {
6771 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6775 if (!force_update) {
6776 notify_printer_location(global_event_context(),
6779 printer->location : "");
6783 if (printer->sepfile != NULL &&
6785 !strequal(printer->sepfile, old_printer->sepfile))) {
6786 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6788 DEBUG(0, ("sepfile data corrupted\n"));
6789 result = WERR_INVALID_DATA;
6792 result = winreg_set_printer_dataex(tmp_ctx, b,
6794 SPOOL_DSSPOOLER_KEY,
6795 SPOOL_REG_PRINTSEPARATORFILE,
6799 if (!W_ERROR_IS_OK(result)) {
6800 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6804 if (!force_update) {
6805 notify_printer_sepfile(global_event_context(),
6808 printer->sepfile : "");
6812 if (printer->starttime != 0 &&
6814 printer->starttime != old_printer->starttime)) {
6815 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6816 SIVAL(buffer.data, 0, printer->starttime);
6817 result = winreg_set_printer_dataex(tmp_ctx, b,
6819 SPOOL_DSSPOOLER_KEY,
6820 SPOOL_REG_PRINTSTARTTIME,
6824 if (!W_ERROR_IS_OK(result)) {
6825 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6830 if (printer->untiltime != 0 &&
6832 printer->untiltime != old_printer->untiltime)) {
6833 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6834 SIVAL(buffer.data, 0, printer->untiltime);
6835 result = winreg_set_printer_dataex(tmp_ctx, b,
6837 SPOOL_DSSPOOLER_KEY,
6838 SPOOL_REG_PRINTENDTIME,
6842 if (!W_ERROR_IS_OK(result)) {
6843 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6848 if (force_update || printer->priority != old_printer->priority) {
6849 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6850 SIVAL(buffer.data, 0, printer->priority);
6851 result = winreg_set_printer_dataex(tmp_ctx, b,
6853 SPOOL_DSSPOOLER_KEY,
6858 if (!W_ERROR_IS_OK(result)) {
6859 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6864 if (force_update || printer->attributes != old_printer->attributes) {
6865 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6866 SIVAL(buffer.data, 0, (printer->attributes &
6867 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6868 result = winreg_set_printer_dataex(tmp_ctx, b,
6870 SPOOL_DSSPOOLER_KEY,
6871 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6875 if (!W_ERROR_IS_OK(result)) {
6876 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6880 switch (printer->attributes & 0x3) {
6882 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6885 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6888 spooling = SPOOL_REGVAL_PRINTDIRECT;
6891 spooling = "unknown";
6893 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6895 DEBUG(0, ("printSpooling data corrupted\n"));
6896 result = WERR_INVALID_DATA;
6899 winreg_set_printer_dataex(tmp_ctx, b,
6901 SPOOL_DSSPOOLER_KEY,
6902 SPOOL_REG_PRINTSPOOLING,
6908 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6910 DEBUG(0, ("shortServerName data corrupted\n"));
6911 result = WERR_INVALID_DATA;
6914 result = winreg_set_printer_dataex(tmp_ctx, b,
6916 SPOOL_DSSPOOLER_KEY,
6917 SPOOL_REG_SHORTSERVERNAME,
6921 if (!W_ERROR_IS_OK(result)) {
6922 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6926 dnsdomname = get_mydnsfullname();
6927 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6928 longname = talloc_strdup(tmp_ctx, dnsdomname);
6930 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6932 if (longname == NULL) {
6933 result = WERR_NOT_ENOUGH_MEMORY;
6937 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6939 DEBUG(0, ("longname data corrupted\n"));
6940 result = WERR_INVALID_DATA;
6943 result = winreg_set_printer_dataex(tmp_ctx, b,
6945 SPOOL_DSSPOOLER_KEY,
6946 SPOOL_REG_SERVERNAME,
6950 if (!W_ERROR_IS_OK(result)) {
6951 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6955 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6956 lp_netbios_name(), printer->sharename);
6957 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6959 DEBUG(0, ("uncName data corrupted\n"));
6960 result = WERR_INVALID_DATA;
6963 result = winreg_set_printer_dataex(tmp_ctx, b,
6965 SPOOL_DSSPOOLER_KEY,
6970 if (!W_ERROR_IS_OK(result)) {
6971 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6976 talloc_free(tmp_ctx);
6980 /********************************************************************
6981 * Called by spoolss_api_setprinter
6982 * when updating a printer description.
6983 ********************************************************************/
6985 static WERROR update_printer(struct pipes_struct *p,
6986 struct policy_handle *handle,
6987 struct spoolss_SetPrinterInfoCtr *info_ctr,
6988 struct spoolss_DeviceMode *devmode)
6990 struct dcesrv_call_state *dce_call = p->dce_call;
6991 struct dcesrv_connection *dcesrv_conn = dce_call->conn;
6992 const struct tsocket_address *remote_address =
6993 dcesrv_connection_get_remote_address(dcesrv_conn);
6994 struct auth_session_info *session_info =
6995 dcesrv_call_session_info(dce_call);
6996 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6997 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6998 struct spoolss_PrinterInfo2 *old_printer;
6999 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7000 const struct loadparm_substitution *lp_sub =
7001 loadparm_s3_global_substitution();
7003 WERROR result = WERR_OK;
7004 TALLOC_CTX *tmp_ctx;
7005 struct dcerpc_binding_handle *b;
7007 DEBUG(8,("update_printer\n"));
7009 tmp_ctx = talloc_new(p->mem_ctx);
7010 if (tmp_ctx == NULL) {
7011 return WERR_NOT_ENOUGH_MEMORY;
7015 result = WERR_INVALID_HANDLE;
7019 if (!get_printer_snum(p, handle, &snum, NULL)) {
7020 result = WERR_INVALID_HANDLE;
7024 result = winreg_printer_binding_handle(tmp_ctx,
7025 get_session_info_system(),
7028 if (!W_ERROR_IS_OK(result)) {
7032 result = winreg_get_printer(tmp_ctx, b,
7033 lp_const_servicename(snum),
7035 if (!W_ERROR_IS_OK(result)) {
7036 result = WERR_INVALID_HANDLE;
7040 /* Do sanity check on the requested changes for Samba */
7041 if (!check_printer_ok(tmp_ctx, printer, snum)) {
7042 result = WERR_INVALID_PARAMETER;
7046 /* FIXME!!! If the driver has changed we really should verify that
7047 it is installed before doing much else --jerry */
7049 /* Check calling user has permission to update printer description */
7050 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7051 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7052 result = WERR_ACCESS_DENIED;
7056 /* Call addprinter hook */
7057 /* Check changes to see if this is really needed */
7059 if (*lp_addprinter_command(talloc_tos(), lp_sub) &&
7060 (!strequal(printer->drivername, old_printer->drivername) ||
7061 !strequal(printer->comment, old_printer->comment) ||
7062 !strequal(printer->portname, old_printer->portname) ||
7063 !strequal(printer->location, old_printer->location)) )
7067 raddr = tsocket_address_inet_addr_string(remote_address,
7069 if (raddr == NULL) {
7070 result = WERR_NOT_ENOUGH_MEMORY;
7074 /* add_printer_hook() will call reload_services() */
7075 if (!add_printer_hook(tmp_ctx, session_info->security_token,
7078 result = WERR_ACCESS_DENIED;
7083 result = update_dsspooler(tmp_ctx,
7084 get_session_info_system(),
7089 if (!W_ERROR_IS_OK(result)) {
7093 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
7095 if (devmode == NULL) {
7096 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7098 result = winreg_update_printer(tmp_ctx, b,
7106 talloc_free(tmp_ctx);
7111 /****************************************************************************
7112 ****************************************************************************/
7113 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7114 struct policy_handle *handle,
7115 struct spoolss_SetPrinterInfo7 *info7)
7118 const struct loadparm_substitution *lp_sub =
7119 loadparm_s3_global_substitution();
7120 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7123 struct printer_handle *Printer;
7125 if ( lp_security() != SEC_ADS ) {
7126 return WERR_INVALID_LEVEL;
7129 Printer = find_printer_index_by_hnd(p, handle);
7131 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7134 return WERR_INVALID_HANDLE;
7136 if (!get_printer_snum(p, handle, &snum, NULL))
7137 return WERR_INVALID_HANDLE;
7139 result = winreg_get_printer_internal(p->mem_ctx,
7140 get_session_info_system(),
7142 lp_servicename(talloc_tos(), lp_sub, snum),
7144 if (!W_ERROR_IS_OK(result)) {
7145 return WERR_INVALID_HANDLE;
7148 nt_printer_publish(pinfo2,
7149 get_session_info_system(),
7154 TALLOC_FREE(pinfo2);
7157 return WERR_INVALID_LEVEL;
7161 /********************************************************************
7162 ********************************************************************/
7164 static WERROR update_printer_devmode(struct pipes_struct *p,
7165 struct policy_handle *handle,
7166 struct spoolss_DeviceMode *devmode)
7169 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7170 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7172 DEBUG(8,("update_printer_devmode\n"));
7175 return WERR_INVALID_HANDLE;
7178 if (!get_printer_snum(p, handle, &snum, NULL)) {
7179 return WERR_INVALID_HANDLE;
7182 /* Check calling user has permission to update printer description */
7183 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7184 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7185 return WERR_ACCESS_DENIED;
7188 return winreg_update_printer_internal(p->mem_ctx,
7189 get_session_info_system(),
7191 lp_const_servicename(snum),
7199 /****************************************************************
7201 ****************************************************************/
7203 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7204 struct spoolss_SetPrinter *r)
7208 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7211 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7212 OUR_HANDLE(r->in.handle)));
7213 return WERR_INVALID_HANDLE;
7216 /* check the level */
7217 switch (r->in.info_ctr->level) {
7219 return control_printer(r->in.handle, r->in.command, p);
7221 result = update_printer(p, r->in.handle,
7223 r->in.devmode_ctr->devmode);
7224 if (!W_ERROR_IS_OK(result))
7226 if (r->in.secdesc_ctr->sd)
7227 result = update_printer_sec(r->in.handle, p,
7231 return update_printer_sec(r->in.handle, p,
7234 struct spoolss_PrinterInfo2 *old_printer;
7235 struct spoolss_SetPrinterInfo2 *set_old_printer;
7236 struct spoolss_SetPrinterInfoCtr *info_ctr;
7237 struct dcerpc_binding_handle *b;
7239 TALLOC_CTX *tmp_ctx;
7241 tmp_ctx = talloc_new(p->mem_ctx);
7242 if (tmp_ctx == NULL) {
7243 return WERR_NOT_ENOUGH_MEMORY;
7246 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7247 TALLOC_FREE(tmp_ctx);
7248 return WERR_INVALID_HANDLE;
7251 result = winreg_printer_binding_handle(tmp_ctx,
7252 get_session_info_system(),
7255 if (!W_ERROR_IS_OK(result)) {
7256 TALLOC_FREE(tmp_ctx);
7260 result = winreg_get_printer(tmp_ctx, b,
7261 lp_const_servicename(snum),
7263 if (!W_ERROR_IS_OK(result)) {
7264 TALLOC_FREE(tmp_ctx);
7265 return WERR_INVALID_HANDLE;
7268 old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7269 if (old_printer->servername == NULL) {
7270 TALLOC_FREE(tmp_ctx);
7271 return WERR_NOT_ENOUGH_MEMORY;
7274 old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7275 if (old_printer->printername == NULL) {
7276 TALLOC_FREE(tmp_ctx);
7277 return WERR_NOT_ENOUGH_MEMORY;
7280 old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7282 set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7283 if (set_old_printer == NULL) {
7284 TALLOC_FREE(tmp_ctx);
7285 return WERR_NOT_ENOUGH_MEMORY;
7288 spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7290 info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7291 if (info_ctr == NULL) {
7292 TALLOC_FREE(tmp_ctx);
7293 return WERR_NOT_ENOUGH_MEMORY;
7296 info_ctr->level = 2;
7297 info_ctr->info.info2 = set_old_printer;
7299 result = update_printer(p, r->in.handle,
7301 r->in.devmode_ctr->devmode);
7303 if (!W_ERROR_IS_OK(result)) {
7304 TALLOC_FREE(tmp_ctx);
7308 if (r->in.secdesc_ctr->sd) {
7309 result = update_printer_sec(r->in.handle, p,
7313 TALLOC_FREE(tmp_ctx);
7317 return publish_or_unpublish_printer(p, r->in.handle,
7318 r->in.info_ctr->info.info7);
7320 return update_printer_devmode(p, r->in.handle,
7321 r->in.devmode_ctr->devmode);
7323 return WERR_INVALID_LEVEL;
7327 /****************************************************************
7328 _spoolss_FindClosePrinterNotify
7329 ****************************************************************/
7331 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7332 struct spoolss_FindClosePrinterNotify *r)
7334 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7337 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7338 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7339 return WERR_INVALID_HANDLE;
7342 if (Printer->notify.cli_chan != NULL &&
7343 Printer->notify.cli_chan->active_connections > 0) {
7346 if (Printer->printer_type == SPLHND_PRINTER) {
7347 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7348 return WERR_INVALID_HANDLE;
7352 srv_spoolss_replycloseprinter(snum, Printer);
7355 Printer->notify.flags=0;
7356 Printer->notify.options=0;
7357 Printer->notify.localmachine[0]='\0';
7358 Printer->notify.printerlocal=0;
7359 TALLOC_FREE(Printer->notify.option);
7364 /****************************************************************
7366 ****************************************************************/
7368 WERROR _spoolss_AddJob(struct pipes_struct *p,
7369 struct spoolss_AddJob *r)
7371 if (!r->in.buffer && (r->in.offered != 0)) {
7372 return WERR_INVALID_PARAMETER;
7375 /* this is what a NT server returns for AddJob. AddJob must fail on
7376 * non-local printers */
7378 if (r->in.level != 1) {
7379 return WERR_INVALID_LEVEL;
7382 return WERR_INVALID_PARAMETER;
7385 /****************************************************************************
7387 ****************************************************************************/
7389 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7390 struct spoolss_JobInfo1 *r,
7391 const print_queue_struct *queue,
7393 int position, int snum,
7394 struct spoolss_PrinterInfo2 *pinfo2)
7396 const struct loadparm_substitution *lp_sub =
7397 loadparm_s3_global_substitution();
7400 t = gmtime(&queue->time);
7404 r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7405 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7406 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7407 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7408 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7409 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7410 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7411 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7412 r->data_type = talloc_strdup(mem_ctx, "RAW");
7413 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7414 r->text_status = talloc_strdup(mem_ctx, "");
7415 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7417 r->status = nt_printj_status(queue->status);
7418 r->priority = queue->priority;
7419 r->position = position;
7420 r->total_pages = queue->page_count;
7421 r->pages_printed = 0; /* ??? */
7423 init_systemtime(&r->submitted, t);
7428 /****************************************************************************
7430 ****************************************************************************/
7432 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7433 struct spoolss_JobInfo2 *r,
7434 const print_queue_struct *queue,
7436 int position, int snum,
7437 struct spoolss_PrinterInfo2 *pinfo2,
7438 struct spoolss_DeviceMode *devmode)
7440 const struct loadparm_substitution *lp_sub =
7441 loadparm_s3_global_substitution();
7444 t = gmtime(&queue->time);
7448 r->printer_name = lp_servicename(mem_ctx, lp_sub, snum);
7449 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7450 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7451 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7452 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7453 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7454 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7455 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7456 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7457 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7458 r->data_type = talloc_strdup(mem_ctx, "RAW");
7459 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7460 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7461 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7462 r->parameters = talloc_strdup(mem_ctx, "");
7463 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7464 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7465 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7467 r->devmode = devmode;
7469 r->text_status = talloc_strdup(mem_ctx, "");
7470 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7474 r->status = nt_printj_status(queue->status);
7475 r->priority = queue->priority;
7476 r->position = position;
7479 r->total_pages = queue->page_count;
7480 r->size = queue->size;
7481 init_systemtime(&r->submitted, t);
7483 r->pages_printed = 0; /* ??? */
7488 /****************************************************************************
7489 Enumjobs at level 1.
7490 ****************************************************************************/
7492 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7493 const print_queue_struct *queue,
7494 uint32_t num_queues, int snum,
7495 struct spoolss_PrinterInfo2 *pinfo2,
7496 union spoolss_JobInfo **info_p,
7499 union spoolss_JobInfo *info;
7501 WERROR result = WERR_OK;
7502 uint32_t num_filled;
7503 struct tdb_print_db *pdb;
7505 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7507 result = WERR_NOT_ENOUGH_MEMORY;
7511 pdb = get_print_db_byname(pinfo2->sharename);
7513 result = WERR_INVALID_PARAMETER;
7518 for (i = 0; i < num_queues; i++) {
7519 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7520 if (jobid == (uint32_t)-1) {
7521 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7525 result = fill_job_info1(info,
7526 &info[num_filled].info1,
7532 if (!W_ERROR_IS_OK(result)) {
7539 release_print_db(pdb);
7541 *count = num_filled;
7546 release_print_db(pdb);
7554 /****************************************************************************
7555 Enumjobs at level 2.
7556 ****************************************************************************/
7558 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7559 const print_queue_struct *queue,
7560 uint32_t num_queues, int snum,
7561 struct spoolss_PrinterInfo2 *pinfo2,
7562 union spoolss_JobInfo **info_p,
7565 union spoolss_JobInfo *info;
7567 WERROR result = WERR_OK;
7568 uint32_t num_filled;
7569 struct tdb_print_db *pdb;
7571 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7573 result = WERR_NOT_ENOUGH_MEMORY;
7577 pdb = get_print_db_byname(pinfo2->sharename);
7579 result = WERR_INVALID_PARAMETER;
7584 for (i = 0; i< num_queues; i++) {
7585 struct spoolss_DeviceMode *devmode;
7586 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7587 if (jobid == (uint32_t)-1) {
7588 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7592 result = spoolss_create_default_devmode(info,
7593 pinfo2->printername,
7595 if (!W_ERROR_IS_OK(result)) {
7596 DEBUG(3, ("Can't proceed w/o a devmode!\n"));
7600 result = fill_job_info2(info,
7601 &info[num_filled].info2,
7608 if (!W_ERROR_IS_OK(result)) {
7614 release_print_db(pdb);
7616 *count = num_filled;
7621 release_print_db(pdb);
7629 /****************************************************************************
7630 Enumjobs at level 3.
7631 ****************************************************************************/
7633 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7634 const print_queue_struct *queue,
7635 uint32_t num_queues, int snum,
7636 struct spoolss_PrinterInfo2 *pinfo2,
7637 union spoolss_JobInfo **info_p,
7640 union spoolss_JobInfo *info;
7642 WERROR result = WERR_OK;
7643 uint32_t num_filled;
7644 struct tdb_print_db *pdb;
7646 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7648 result = WERR_NOT_ENOUGH_MEMORY;
7652 pdb = get_print_db_byname(pinfo2->sharename);
7654 result = WERR_INVALID_PARAMETER;
7659 for (i = 0; i < num_queues; i++) {
7660 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7661 if (jobid == (uint32_t)-1) {
7662 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7666 info[num_filled].info3.job_id = jobid;
7667 /* next_job_id is overwritten on next iteration */
7668 info[num_filled].info3.next_job_id = 0;
7669 info[num_filled].info3.reserved = 0;
7671 if (num_filled > 0) {
7672 info[num_filled - 1].info3.next_job_id = jobid;
7677 release_print_db(pdb);
7679 *count = num_filled;
7690 /****************************************************************
7692 ****************************************************************/
7694 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7695 struct spoolss_EnumJobs *r)
7698 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7700 print_status_struct prt_status;
7701 print_queue_struct *queue = NULL;
7704 /* that's an [in out] buffer */
7706 if (!r->in.buffer && (r->in.offered != 0)) {
7707 return WERR_INVALID_PARAMETER;
7710 if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7711 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7712 return WERR_INVALID_LEVEL;
7715 DEBUG(4,("_spoolss_EnumJobs\n"));
7719 *r->out.info = NULL;
7721 /* lookup the printer snum and tdb entry */
7723 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7724 return WERR_INVALID_HANDLE;
7727 result = winreg_get_printer_internal(p->mem_ctx,
7728 get_session_info_system(),
7730 lp_const_servicename(snum),
7732 if (!W_ERROR_IS_OK(result)) {
7736 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7737 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7738 count, prt_status.status, prt_status.message));
7742 TALLOC_FREE(pinfo2);
7746 switch (r->in.level) {
7748 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7749 pinfo2, r->out.info, r->out.count);
7752 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7753 pinfo2, r->out.info, r->out.count);
7756 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7757 pinfo2, r->out.info, r->out.count);
7760 SMB_ASSERT(false); /* level checked on entry */
7765 TALLOC_FREE(pinfo2);
7767 if (!W_ERROR_IS_OK(result)) {
7771 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7773 *r->out.info, r->in.level,
7775 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7776 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7778 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7781 /****************************************************************
7782 _spoolss_ScheduleJob
7783 ****************************************************************/
7785 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7786 struct spoolss_ScheduleJob *r)
7791 /****************************************************************
7792 ****************************************************************/
7794 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7795 struct messaging_context *msg_ctx,
7796 const char *printer_name,
7798 struct spoolss_SetJobInfo1 *r)
7802 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7803 return WERR_INVALID_HANDLE;
7806 if (strequal(old_doc_name, r->document_name)) {
7810 if (!print_job_set_name(global_event_context(), msg_ctx,
7811 printer_name, job_id, r->document_name)) {
7812 return WERR_INVALID_HANDLE;
7818 /****************************************************************
7820 ****************************************************************/
7822 WERROR _spoolss_SetJob(struct pipes_struct *p,
7823 struct spoolss_SetJob *r)
7825 struct dcesrv_call_state *dce_call = p->dce_call;
7826 struct auth_session_info *session_info =
7827 dcesrv_call_session_info(dce_call);
7829 WERROR errcode = WERR_INVALID_FUNCTION;
7831 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7832 return WERR_INVALID_HANDLE;
7835 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7836 return WERR_INVALID_PRINTER_NAME;
7839 switch (r->in.command) {
7840 case SPOOLSS_JOB_CONTROL_CANCEL:
7841 case SPOOLSS_JOB_CONTROL_DELETE:
7842 errcode = print_job_delete(session_info, p->msg_ctx,
7843 snum, r->in.job_id);
7844 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7848 case SPOOLSS_JOB_CONTROL_PAUSE:
7849 errcode = print_job_pause(session_info, p->msg_ctx,
7850 snum, r->in.job_id);
7852 case SPOOLSS_JOB_CONTROL_RESTART:
7853 case SPOOLSS_JOB_CONTROL_RESUME:
7854 errcode = print_job_resume(session_info, p->msg_ctx,
7855 snum, r->in.job_id);
7857 case SPOOLSS_JOB_CONTROL_NOOP:
7861 return WERR_INVALID_LEVEL;
7864 if (!W_ERROR_IS_OK(errcode)) {
7868 if (r->in.ctr == NULL) {
7872 switch (r->in.ctr->level) {
7874 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7875 lp_const_servicename(snum),
7877 r->in.ctr->info.info1);
7883 return WERR_INVALID_LEVEL;
7889 /****************************************************************************
7890 Enumerates all printer drivers by level and architecture.
7891 ****************************************************************************/
7893 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7894 const struct auth_session_info *session_info,
7895 struct messaging_context *msg_ctx,
7896 const char *servername,
7897 const char *architecture,
7899 union spoolss_DriverInfo **info_p,
7904 struct spoolss_DriverInfo8 *driver;
7905 union spoolss_DriverInfo *info = NULL;
7907 WERROR result = WERR_OK;
7908 uint32_t num_drivers;
7909 const char **drivers;
7910 struct dcerpc_binding_handle *b;
7911 TALLOC_CTX *tmp_ctx = NULL;
7916 tmp_ctx = talloc_new(mem_ctx);
7918 return WERR_NOT_ENOUGH_MEMORY;
7921 result = winreg_printer_binding_handle(tmp_ctx,
7925 if (!W_ERROR_IS_OK(result)) {
7929 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7930 result = winreg_get_driver_list(tmp_ctx, b,
7931 architecture, version,
7932 &num_drivers, &drivers);
7933 if (!W_ERROR_IS_OK(result)) {
7936 DEBUG(4, ("we have:[%d] drivers in environment"
7937 " [%s] and version [%d]\n",
7938 num_drivers, architecture, version));
7940 if (num_drivers != 0) {
7941 info = talloc_realloc(tmp_ctx, info,
7942 union spoolss_DriverInfo,
7943 count + num_drivers);
7945 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7946 "failed to enlarge driver info buffer!\n"));
7947 result = WERR_NOT_ENOUGH_MEMORY;
7952 for (i = 0; i < num_drivers; i++) {
7953 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7955 result = winreg_get_driver(tmp_ctx, b,
7956 architecture, drivers[i],
7958 if (!W_ERROR_IS_OK(result)) {
7964 result = fill_printer_driver_info1(info, &info[count+i].info1,
7965 driver, servername);
7968 result = fill_printer_driver_info2(info, &info[count+i].info2,
7969 driver, servername);
7972 result = fill_printer_driver_info3(info, &info[count+i].info3,
7973 driver, servername);
7976 result = fill_printer_driver_info4(info, &info[count+i].info4,
7977 driver, servername);
7980 result = fill_printer_driver_info5(info, &info[count+i].info5,
7981 driver, servername);
7984 result = fill_printer_driver_info6(info, &info[count+i].info6,
7985 driver, servername);
7988 result = fill_printer_driver_info8(info, &info[count+i].info8,
7989 driver, servername);
7992 result = WERR_INVALID_LEVEL;
7996 TALLOC_FREE(driver);
7998 if (!W_ERROR_IS_OK(result)) {
8003 count += num_drivers;
8004 TALLOC_FREE(drivers);
8008 if (W_ERROR_IS_OK(result)) {
8009 *info_p = talloc_move(mem_ctx, &info);
8013 talloc_free(tmp_ctx);
8017 /****************************************************************************
8018 Enumerates all printer drivers by level.
8019 ****************************************************************************/
8021 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
8022 const struct auth_session_info *session_info,
8023 struct messaging_context *msg_ctx,
8024 const char *servername,
8025 const char *architecture,
8027 union spoolss_DriverInfo **info_p,
8031 WERROR result = WERR_OK;
8033 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
8035 for (a=0; archi_table[a].long_archi != NULL; a++) {
8037 union spoolss_DriverInfo *info = NULL;
8040 result = enumprinterdrivers_level_by_architecture(mem_ctx,
8044 archi_table[a].long_archi,
8048 if (!W_ERROR_IS_OK(result)) {
8052 for (i=0; i < count; i++) {
8053 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
8054 info[i], info_p, count_p);
8061 return enumprinterdrivers_level_by_architecture(mem_ctx,
8071 /****************************************************************
8072 _spoolss_EnumPrinterDrivers
8073 ****************************************************************/
8075 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
8076 struct spoolss_EnumPrinterDrivers *r)
8078 const char *cservername;
8081 /* that's an [in out] buffer */
8083 if (!r->in.buffer && (r->in.offered != 0)) {
8084 return WERR_INVALID_PARAMETER;
8087 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
8091 *r->out.info = NULL;
8093 cservername = canon_servername(r->in.server);
8095 if (!is_myname_or_ipaddr(cservername)) {
8096 return WERR_UNKNOWN_PRINTER_DRIVER;
8099 result = enumprinterdrivers_level(p->mem_ctx,
8100 get_session_info_system(),
8107 if (!W_ERROR_IS_OK(result)) {
8111 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8112 spoolss_EnumPrinterDrivers,
8113 *r->out.info, r->in.level,
8115 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8116 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8118 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8121 /****************************************************************
8123 ****************************************************************/
8125 WERROR _spoolss_EnumForms(struct pipes_struct *p,
8126 struct spoolss_EnumForms *r)
8132 *r->out.info = NULL;
8134 /* that's an [in out] buffer */
8136 if (!r->in.buffer && (r->in.offered != 0) ) {
8137 return WERR_INVALID_PARAMETER;
8140 DEBUG(4,("_spoolss_EnumForms\n"));
8141 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8142 DEBUGADD(5,("Info level [%d]\n", r->in.level));
8144 switch (r->in.level) {
8146 result = winreg_printer_enumforms1_internal(p->mem_ctx,
8147 get_session_info_system(),
8153 result = WERR_INVALID_LEVEL;
8157 if (!W_ERROR_IS_OK(result)) {
8161 if (*r->out.count == 0) {
8162 return WERR_NO_MORE_ITEMS;
8165 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8167 *r->out.info, r->in.level,
8169 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8170 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8172 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8175 /****************************************************************
8177 ****************************************************************/
8179 WERROR _spoolss_GetForm(struct pipes_struct *p,
8180 struct spoolss_GetForm *r)
8184 /* that's an [in out] buffer */
8186 if (!r->in.buffer && (r->in.offered != 0)) {
8187 TALLOC_FREE(r->out.info);
8188 return WERR_INVALID_PARAMETER;
8191 DEBUG(4,("_spoolss_GetForm\n"));
8192 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8193 DEBUGADD(5,("Info level [%d]\n", r->in.level));
8195 switch (r->in.level) {
8197 result = winreg_printer_getform1_internal(p->mem_ctx,
8198 get_session_info_system(),
8201 &r->out.info->info1);
8204 result = WERR_INVALID_LEVEL;
8208 if (!W_ERROR_IS_OK(result)) {
8209 TALLOC_FREE(r->out.info);
8213 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8214 r->out.info, r->in.level);
8215 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8217 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8220 /****************************************************************************
8221 ****************************************************************************/
8223 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8224 struct spoolss_PortInfo1 *r,
8227 r->port_name = talloc_strdup(mem_ctx, name);
8228 W_ERROR_HAVE_NO_MEMORY(r->port_name);
8233 /****************************************************************************
8234 TODO: This probably needs distinguish between TCP/IP and Local ports
8236 ****************************************************************************/
8238 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8239 struct spoolss_PortInfo2 *r,
8242 r->port_name = talloc_strdup(mem_ctx, name);
8243 W_ERROR_HAVE_NO_MEMORY(r->port_name);
8245 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8246 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8248 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8249 W_ERROR_HAVE_NO_MEMORY(r->description);
8251 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8258 /****************************************************************************
8259 wrapper around the enum ports command
8260 ****************************************************************************/
8262 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8264 const struct loadparm_substitution *lp_sub =
8265 loadparm_s3_global_substitution();
8266 char *cmd = lp_enumports_command(talloc_tos(), lp_sub);
8267 char **qlines = NULL;
8268 char *command = NULL;
8276 /* if no hook then just fill in the default port */
8279 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8280 return WERR_NOT_ENOUGH_MEMORY;
8282 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8283 TALLOC_FREE(qlines);
8284 return WERR_NOT_ENOUGH_MEMORY;
8290 /* we have a valid enumport command */
8292 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8294 return WERR_NOT_ENOUGH_MEMORY;
8297 DEBUG(10,("Running [%s]\n", command));
8298 ret = smbrun(command, &fd, NULL);
8299 DEBUG(10,("Returned [%d]\n", ret));
8300 TALLOC_FREE(command);
8305 return WERR_ACCESS_DENIED;
8309 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8310 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8320 /****************************************************************************
8322 ****************************************************************************/
8324 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8325 union spoolss_PortInfo **info_p,
8328 union spoolss_PortInfo *info = NULL;
8330 WERROR result = WERR_OK;
8331 char **qlines = NULL;
8334 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8335 if (!W_ERROR_IS_OK(result)) {
8340 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8342 DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8343 result = WERR_NOT_ENOUGH_MEMORY;
8347 for (i=0; i<numlines; i++) {
8348 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8349 result = fill_port_1(info, &info[i].info1, qlines[i]);
8350 if (!W_ERROR_IS_OK(result)) {
8355 TALLOC_FREE(qlines);
8358 if (!W_ERROR_IS_OK(result)) {
8360 TALLOC_FREE(qlines);
8372 /****************************************************************************
8374 ****************************************************************************/
8376 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8377 union spoolss_PortInfo **info_p,
8380 union spoolss_PortInfo *info = NULL;
8382 WERROR result = WERR_OK;
8383 char **qlines = NULL;
8386 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8387 if (!W_ERROR_IS_OK(result)) {
8392 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8394 DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8395 result = WERR_NOT_ENOUGH_MEMORY;
8399 for (i=0; i<numlines; i++) {
8400 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8401 result = fill_port_2(info, &info[i].info2, qlines[i]);
8402 if (!W_ERROR_IS_OK(result)) {
8407 TALLOC_FREE(qlines);
8410 if (!W_ERROR_IS_OK(result)) {
8412 TALLOC_FREE(qlines);
8424 /****************************************************************
8426 ****************************************************************/
8428 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8429 struct spoolss_EnumPorts *r)
8433 /* that's an [in out] buffer */
8435 if (!r->in.buffer && (r->in.offered != 0)) {
8436 return WERR_INVALID_PARAMETER;
8439 DEBUG(4,("_spoolss_EnumPorts\n"));
8443 *r->out.info = NULL;
8445 switch (r->in.level) {
8447 result = enumports_level_1(p->mem_ctx, r->out.info,
8451 result = enumports_level_2(p->mem_ctx, r->out.info,
8455 return WERR_INVALID_LEVEL;
8458 if (!W_ERROR_IS_OK(result)) {
8462 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8464 *r->out.info, r->in.level,
8466 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8467 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8469 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8472 /****************************************************************************
8473 ****************************************************************************/
8475 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8477 struct spoolss_SetPrinterInfoCtr *info_ctr,
8478 struct spoolss_DeviceMode *devmode,
8479 struct security_descriptor *secdesc,
8480 struct spoolss_UserLevelCtr *user_ctr,
8481 struct policy_handle *handle)
8483 struct dcesrv_call_state *dce_call = p->dce_call;
8484 struct dcesrv_connection *dcesrv_conn = dce_call->conn;
8485 const struct tsocket_address *remote_address =
8486 dcesrv_connection_get_remote_address(dcesrv_conn);
8487 struct auth_session_info *session_info =
8488 dcesrv_call_session_info(dce_call);
8489 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8490 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8491 const struct loadparm_substitution *lp_sub =
8492 loadparm_s3_global_substitution();
8494 WERROR err = WERR_OK;
8496 /* samba does not have a concept of local, non-shared printers yet, so
8497 * make sure we always setup sharename - gd */
8498 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8499 (info2->printername != NULL && info2->printername[0] != '\0')) {
8500 DEBUG(5, ("spoolss_addprinterex_level_2: "
8501 "no sharename has been set, setting printername %s as sharename\n",
8502 info2->printername));
8503 info2->sharename = info2->printername;
8506 /* check to see if the printer already exists */
8507 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8508 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8510 return WERR_PRINTER_ALREADY_EXISTS;
8513 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8514 if ((snum = print_queue_snum(info2->printername)) != -1) {
8515 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8516 info2->printername));
8517 return WERR_PRINTER_ALREADY_EXISTS;
8521 /* validate printer info struct */
8522 if (!info2->printername || strlen(info2->printername) == 0) {
8523 return WERR_INVALID_PRINTER_NAME;
8525 if (!info2->portname || strlen(info2->portname) == 0) {
8526 return WERR_UNKNOWN_PORT;
8528 if (!info2->drivername || strlen(info2->drivername) == 0) {
8529 return WERR_UNKNOWN_PRINTER_DRIVER;
8531 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8532 return WERR_UNKNOWN_PRINTPROCESSOR;
8535 /* FIXME!!! smbd should check to see if the driver is installed before
8536 trying to add a printer like this --jerry */
8538 if (*lp_addprinter_command(talloc_tos(), lp_sub) ) {
8541 raddr = tsocket_address_inet_addr_string(remote_address,
8543 if (raddr == NULL) {
8544 return WERR_NOT_ENOUGH_MEMORY;
8547 if ( !add_printer_hook(p->mem_ctx, session_info->security_token,
8550 return WERR_ACCESS_DENIED;
8553 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8554 "smb.conf parameter \"addprinter command\" is defined. This "
8555 "parameter must exist for this call to succeed\n",
8556 info2->sharename ));
8559 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8560 return WERR_ACCESS_DENIED;
8563 /* you must be a printer admin to add a new printer */
8564 if (!W_ERROR_IS_OK(print_access_check(session_info,
8567 PRINTER_ACCESS_ADMINISTER))) {
8568 return WERR_ACCESS_DENIED;
8572 * Do sanity check on the requested changes for Samba.
8575 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8576 return WERR_INVALID_PARAMETER;
8579 if (devmode == NULL) {
8580 info2_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
8583 err = update_dsspooler(p->mem_ctx,
8584 get_session_info_system(),
8589 if (!W_ERROR_IS_OK(err)) {
8593 err = winreg_update_printer_internal(p->mem_ctx,
8594 get_session_info_system(),
8601 if (!W_ERROR_IS_OK(err)) {
8605 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8606 if (!W_ERROR_IS_OK(err)) {
8607 /* Handle open failed - remove addition. */
8608 ZERO_STRUCTP(handle);
8615 /****************************************************************
8616 _spoolss_AddPrinterEx
8617 ****************************************************************/
8619 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8620 struct spoolss_AddPrinterEx *r)
8622 switch (r->in.info_ctr->level) {
8624 /* we don't handle yet */
8625 /* but I know what to do ... */
8626 return WERR_INVALID_LEVEL;
8628 return spoolss_addprinterex_level_2(p, r->in.server,
8630 r->in.devmode_ctr->devmode,
8631 r->in.secdesc_ctr->sd,
8632 r->in.userlevel_ctr,
8635 return WERR_INVALID_LEVEL;
8639 /****************************************************************
8641 ****************************************************************/
8643 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8644 struct spoolss_AddPrinter *r)
8646 struct spoolss_AddPrinterEx a;
8647 struct spoolss_UserLevelCtr userlevel_ctr;
8649 ZERO_STRUCT(userlevel_ctr);
8651 userlevel_ctr.level = 1;
8653 a.in.server = r->in.server;
8654 a.in.info_ctr = r->in.info_ctr;
8655 a.in.devmode_ctr = r->in.devmode_ctr;
8656 a.in.secdesc_ctr = r->in.secdesc_ctr;
8657 a.in.userlevel_ctr = &userlevel_ctr;
8658 a.out.handle = r->out.handle;
8660 return _spoolss_AddPrinterEx(p, &a);
8663 /****************************************************************
8664 _spoolss_AddPrinterDriverEx
8665 ****************************************************************/
8667 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8668 struct spoolss_AddPrinterDriverEx *r)
8670 struct dcesrv_call_state *dce_call = p->dce_call;
8671 struct auth_session_info *session_info =
8672 dcesrv_call_session_info(dce_call);
8673 WERROR err = WERR_OK;
8674 const char *driver_name = NULL;
8675 const char *driver_directory = NULL;
8679 * we only support the semantics of AddPrinterDriver()
8680 * i.e. only copy files that are newer than existing ones
8683 if (r->in.flags == 0) {
8684 return WERR_INVALID_PARAMETER;
8687 if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8688 !(r->in.flags & APD_COPY_NEW_FILES)) {
8689 return WERR_ACCESS_DENIED;
8693 if (r->in.info_ctr->level != 3 &&
8694 r->in.info_ctr->level != 6 &&
8695 r->in.info_ctr->level != 8) {
8696 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8697 r->in.info_ctr->level));
8698 return WERR_INVALID_LEVEL;
8701 DEBUG(5,("Cleaning driver's information\n"));
8702 err = clean_up_driver_struct(p->mem_ctx,
8707 if (!W_ERROR_IS_OK(err)) {
8708 DBG_ERR("clean_up_driver_struct failed - %s\n",
8713 DEBUG(5,("Moving driver to final destination\n"));
8714 err = move_driver_to_download_area(session_info,
8717 if (!W_ERROR_IS_OK(err)) {
8718 DBG_ERR("move_driver_to_download_area failed - %s\n",
8723 err = winreg_add_driver_internal(p->mem_ctx,
8724 get_session_info_system(),
8729 if (!W_ERROR_IS_OK(err)) {
8730 DBG_ERR("winreg_add_driver_internal failed - %s\n",
8736 * I think this is where the DrvUpgradePrinter() hook would be
8737 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8738 * server. Right now, we just need to send ourselves a message
8739 * to update each printer bound to this driver. --jerry
8742 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8743 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8744 __func__, driver_name));
8751 /****************************************************************
8752 _spoolss_AddPrinterDriver
8753 ****************************************************************/
8755 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8756 struct spoolss_AddPrinterDriver *r)
8758 struct spoolss_AddPrinterDriverEx a;
8760 switch (r->in.info_ctr->level) {
8767 return WERR_INVALID_LEVEL;
8770 a.in.servername = r->in.servername;
8771 a.in.info_ctr = r->in.info_ctr;
8772 a.in.flags = APD_COPY_NEW_FILES;
8774 return _spoolss_AddPrinterDriverEx(p, &a);
8777 /****************************************************************************
8778 ****************************************************************************/
8780 struct _spoolss_paths {
8786 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8788 static const struct _spoolss_paths spoolss_paths[]= {
8789 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8790 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8793 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8794 const char *servername,
8795 const char *environment,
8799 const char *pservername = NULL;
8800 const char *long_archi;
8801 const char *short_archi;
8805 /* environment may be empty */
8806 if (environment && strlen(environment)) {
8807 long_archi = environment;
8809 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8810 "spoolss", "architecture",
8811 GLOBAL_SPOOLSS_ARCHITECTURE);
8814 /* servername may be empty */
8815 if (servername && strlen(servername)) {
8816 pservername = canon_servername(servername);
8818 if (!is_myname_or_ipaddr(pservername)) {
8819 return WERR_INVALID_PARAMETER;
8823 if (!(short_archi = get_short_archi(long_archi))) {
8824 return WERR_INVALID_ENVIRONMENT;
8827 switch (component) {
8828 case SPOOLSS_PRTPROCS_PATH:
8829 case SPOOLSS_DRIVER_PATH:
8831 *path = talloc_asprintf(mem_ctx,
8834 spoolss_paths[component].share,
8837 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8838 SPOOLSS_DEFAULT_SERVER_PATH,
8839 spoolss_paths[component].dir,
8844 return WERR_INVALID_PARAMETER;
8848 return WERR_NOT_ENOUGH_MEMORY;
8854 /****************************************************************************
8855 ****************************************************************************/
8857 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8858 const char *servername,
8859 const char *environment,
8860 struct spoolss_DriverDirectoryInfo1 *r)
8865 werr = compose_spoolss_server_path(mem_ctx,
8868 SPOOLSS_DRIVER_PATH,
8870 if (!W_ERROR_IS_OK(werr)) {
8874 DEBUG(4,("printer driver directory: [%s]\n", path));
8876 r->directory_name = path;
8881 /****************************************************************
8882 _spoolss_GetPrinterDriverDirectory
8883 ****************************************************************/
8885 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8886 struct spoolss_GetPrinterDriverDirectory *r)
8890 /* that's an [in out] buffer */
8892 if (!r->in.buffer && (r->in.offered != 0)) {
8893 TALLOC_FREE(r->out.info);
8894 return WERR_INVALID_PARAMETER;
8897 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8902 /* r->in.level is ignored */
8904 werror = getprinterdriverdir_level_1(p->mem_ctx,
8907 &r->out.info->info1);
8908 if (!W_ERROR_IS_OK(werror)) {
8909 TALLOC_FREE(r->out.info);
8913 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8914 r->out.info, r->in.level);
8915 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8917 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8920 /****************************************************************
8921 _spoolss_EnumPrinterData
8922 ****************************************************************/
8924 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8925 struct spoolss_EnumPrinterData *r)
8928 struct spoolss_EnumPrinterDataEx r2;
8930 struct spoolss_PrinterEnumValues *info, *val = NULL;
8933 r2.in.handle = r->in.handle;
8934 r2.in.key_name = "PrinterDriverData";
8936 r2.out.count = &count;
8937 r2.out.info = &info;
8938 r2.out.needed = &needed;
8940 result = _spoolss_EnumPrinterDataEx(p, &r2);
8941 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8942 r2.in.offered = needed;
8943 result = _spoolss_EnumPrinterDataEx(p, &r2);
8945 if (!W_ERROR_IS_OK(result)) {
8950 * The NT machine wants to know the biggest size of value and data
8952 * cf: MSDN EnumPrinterData remark section
8955 if (!r->in.value_offered && !r->in.data_offered) {
8956 uint32_t biggest_valuesize = 0;
8957 uint32_t biggest_datasize = 0;
8960 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8962 for (i=0; i<count; i++) {
8964 name_length = strlen(info[i].value_name);
8965 if (strlen(info[i].value_name) > biggest_valuesize) {
8966 biggest_valuesize = name_length;
8969 if (info[i].data_length > biggest_datasize) {
8970 biggest_datasize = info[i].data_length;
8973 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8977 /* the value is an UNICODE string but real_value_size is the length
8978 in bytes including the trailing 0 */
8980 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8981 *r->out.data_needed = biggest_datasize;
8983 DEBUG(6,("final values: [%d], [%d]\n",
8984 *r->out.value_needed, *r->out.data_needed));
8989 if (r->in.enum_index < count) {
8990 val = &info[r->in.enum_index];
8994 /* out_value should default to "" or else NT4 has
8995 problems unmarshalling the response */
8997 if (r->in.value_offered) {
8998 *r->out.value_needed = 1;
8999 r->out.value_name = talloc_strdup(r, "");
9000 if (!r->out.value_name) {
9001 return WERR_NOT_ENOUGH_MEMORY;
9004 r->out.value_name = NULL;
9005 *r->out.value_needed = 0;
9008 /* the data is counted in bytes */
9010 *r->out.data_needed = r->in.data_offered;
9012 result = WERR_NO_MORE_ITEMS;
9016 * - counted in bytes in the request
9017 * - counted in UNICODE chars in the max reply
9018 * - counted in bytes in the real size
9020 * take a pause *before* coding not *during* coding
9024 if (r->in.value_offered) {
9025 r->out.value_name = talloc_strdup(r, val->value_name);
9026 if (!r->out.value_name) {
9027 return WERR_NOT_ENOUGH_MEMORY;
9029 *r->out.value_needed = val->value_name_len;
9031 r->out.value_name = NULL;
9032 *r->out.value_needed = 0;
9037 *r->out.type = val->type;
9039 /* data - counted in bytes */
9042 * See the section "Dynamically Typed Query Parameters"
9046 if (r->out.data && val->data && val->data->data &&
9047 val->data_length && r->in.data_offered) {
9048 memcpy(r->out.data, val->data->data,
9049 MIN(val->data_length,r->in.data_offered));
9052 *r->out.data_needed = val->data_length;
9060 /****************************************************************
9061 _spoolss_SetPrinterData
9062 ****************************************************************/
9064 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
9065 struct spoolss_SetPrinterData *r)
9067 struct spoolss_SetPrinterDataEx r2;
9069 r2.in.handle = r->in.handle;
9070 r2.in.key_name = "PrinterDriverData";
9071 r2.in.value_name = r->in.value_name;
9072 r2.in.type = r->in.type;
9073 r2.in.data = r->in.data;
9074 r2.in.offered = r->in.offered;
9076 return _spoolss_SetPrinterDataEx(p, &r2);
9079 /****************************************************************
9080 _spoolss_ResetPrinter
9081 ****************************************************************/
9083 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
9084 struct spoolss_ResetPrinter *r)
9086 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9089 DEBUG(5,("_spoolss_ResetPrinter\n"));
9092 * All we do is to check to see if the handle and queue is valid.
9093 * This call really doesn't mean anything to us because we only
9094 * support RAW printing. --jerry
9098 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
9099 OUR_HANDLE(r->in.handle)));
9100 return WERR_INVALID_HANDLE;
9103 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
9104 return WERR_INVALID_HANDLE;
9107 /* blindly return success */
9111 /****************************************************************
9112 _spoolss_DeletePrinterData
9113 ****************************************************************/
9115 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
9116 struct spoolss_DeletePrinterData *r)
9118 struct spoolss_DeletePrinterDataEx r2;
9120 r2.in.handle = r->in.handle;
9121 r2.in.key_name = "PrinterDriverData";
9122 r2.in.value_name = r->in.value_name;
9124 return _spoolss_DeletePrinterDataEx(p, &r2);
9127 /****************************************************************
9129 ****************************************************************/
9131 WERROR _spoolss_AddForm(struct pipes_struct *p,
9132 struct spoolss_AddForm *r)
9134 struct dcesrv_call_state *dce_call = p->dce_call;
9135 struct auth_session_info *session_info =
9136 dcesrv_call_session_info(dce_call);
9137 struct spoolss_AddFormInfo1 *form;
9139 WERROR status = WERR_OK;
9140 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9141 struct dcerpc_binding_handle *b;
9142 TALLOC_CTX *tmp_ctx = NULL;
9144 DEBUG(5,("_spoolss_AddForm\n"));
9147 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9148 OUR_HANDLE(r->in.handle)));
9149 return WERR_INVALID_HANDLE;
9152 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9153 and not a printer admin, then fail */
9155 if ((session_info->unix_token->uid != sec_initial_uid()) &&
9156 !security_token_has_privilege(session_info->security_token,
9157 SEC_PRIV_PRINT_OPERATOR)) {
9158 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9159 return WERR_ACCESS_DENIED;
9162 if (r->in.info_ctr->level != 1) {
9163 return WERR_INVALID_LEVEL;
9166 form = r->in.info_ctr->info.info1;
9168 return WERR_INVALID_PARAMETER;
9171 switch (form->flags) {
9172 case SPOOLSS_FORM_USER:
9173 case SPOOLSS_FORM_BUILTIN:
9174 case SPOOLSS_FORM_PRINTER:
9177 return WERR_INVALID_PARAMETER;
9180 tmp_ctx = talloc_new(p->mem_ctx);
9182 return WERR_NOT_ENOUGH_MEMORY;
9185 status = winreg_printer_binding_handle(tmp_ctx,
9186 get_session_info_system(),
9189 if (!W_ERROR_IS_OK(status)) {
9193 status = winreg_printer_addform1(tmp_ctx, b, form);
9194 if (!W_ERROR_IS_OK(status)) {
9199 * ChangeID must always be set if this is a printer
9201 if (Printer->printer_type == SPLHND_PRINTER) {
9202 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9203 status = WERR_INVALID_HANDLE;
9207 status = winreg_printer_update_changeid(tmp_ctx, b,
9208 lp_const_servicename(snum));
9212 talloc_free(tmp_ctx);
9216 /****************************************************************
9218 ****************************************************************/
9220 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9221 struct spoolss_DeleteForm *r)
9223 struct dcesrv_call_state *dce_call = p->dce_call;
9224 struct auth_session_info *session_info =
9225 dcesrv_call_session_info(dce_call);
9226 const char *form_name = r->in.form_name;
9227 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9229 WERROR status = WERR_OK;
9230 struct dcerpc_binding_handle *b;
9231 TALLOC_CTX *tmp_ctx = NULL;
9233 DEBUG(5,("_spoolss_DeleteForm\n"));
9236 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9237 OUR_HANDLE(r->in.handle)));
9238 return WERR_INVALID_HANDLE;
9241 if ((session_info->unix_token->uid != sec_initial_uid()) &&
9242 !security_token_has_privilege(session_info->security_token,
9243 SEC_PRIV_PRINT_OPERATOR)) {
9244 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9245 return WERR_ACCESS_DENIED;
9248 tmp_ctx = talloc_new(p->mem_ctx);
9250 return WERR_NOT_ENOUGH_MEMORY;
9253 status = winreg_printer_binding_handle(tmp_ctx,
9254 get_session_info_system(),
9257 if (!W_ERROR_IS_OK(status)) {
9261 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9262 if (!W_ERROR_IS_OK(status)) {
9267 * ChangeID must always be set if this is a printer
9269 if (Printer->printer_type == SPLHND_PRINTER) {
9270 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9271 status = WERR_INVALID_HANDLE;
9275 status = winreg_printer_update_changeid(tmp_ctx, b,
9276 lp_const_servicename(snum));
9280 talloc_free(tmp_ctx);
9284 /****************************************************************
9286 ****************************************************************/
9288 WERROR _spoolss_SetForm(struct pipes_struct *p,
9289 struct spoolss_SetForm *r)
9291 struct dcesrv_call_state *dce_call = p->dce_call;
9292 struct auth_session_info *session_info =
9293 dcesrv_call_session_info(dce_call);
9294 struct spoolss_AddFormInfo1 *form;
9295 const char *form_name = r->in.form_name;
9297 WERROR status = WERR_OK;
9298 struct dcerpc_binding_handle *b;
9299 TALLOC_CTX *tmp_ctx = NULL;
9301 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9303 DEBUG(5,("_spoolss_SetForm\n"));
9306 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9307 OUR_HANDLE(r->in.handle)));
9308 return WERR_INVALID_HANDLE;
9311 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9312 and not a printer admin, then fail */
9314 if ((session_info->unix_token->uid != sec_initial_uid()) &&
9315 !security_token_has_privilege(session_info->security_token,
9316 SEC_PRIV_PRINT_OPERATOR)) {
9317 DEBUG(2,("_spoolss_SetForm: denied by insufficient permissions.\n"));
9318 return WERR_ACCESS_DENIED;
9321 if (r->in.info_ctr->level != 1) {
9322 return WERR_INVALID_LEVEL;
9325 form = r->in.info_ctr->info.info1;
9327 return WERR_INVALID_PARAMETER;
9330 tmp_ctx = talloc_new(p->mem_ctx);
9332 return WERR_NOT_ENOUGH_MEMORY;
9335 status = winreg_printer_binding_handle(tmp_ctx,
9336 get_session_info_system(),
9339 if (!W_ERROR_IS_OK(status)) {
9343 status = winreg_printer_setform1(tmp_ctx, b,
9346 if (!W_ERROR_IS_OK(status)) {
9351 * ChangeID must always be set if this is a printer
9353 if (Printer->printer_type == SPLHND_PRINTER) {
9354 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9355 status = WERR_INVALID_HANDLE;
9359 status = winreg_printer_update_changeid(tmp_ctx, b,
9360 lp_const_servicename(snum));
9364 talloc_free(tmp_ctx);
9368 /****************************************************************************
9369 fill_print_processor1
9370 ****************************************************************************/
9372 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9373 struct spoolss_PrintProcessorInfo1 *r,
9374 const char *print_processor_name)
9376 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9377 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9382 /****************************************************************************
9383 enumprintprocessors level 1.
9384 ****************************************************************************/
9386 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9387 union spoolss_PrintProcessorInfo **info_p,
9390 union spoolss_PrintProcessorInfo *info;
9393 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9394 W_ERROR_HAVE_NO_MEMORY(info);
9398 result = fill_print_processor1(info, &info[0].info1, "winprint");
9399 if (!W_ERROR_IS_OK(result)) {
9404 if (!W_ERROR_IS_OK(result)) {
9415 /****************************************************************
9416 _spoolss_EnumPrintProcessors
9417 ****************************************************************/
9419 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9420 struct spoolss_EnumPrintProcessors *r)
9424 /* that's an [in out] buffer */
9426 if (!r->in.buffer && (r->in.offered != 0)) {
9427 return WERR_INVALID_PARAMETER;
9430 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9433 * Enumerate the print processors ...
9435 * Just reply with "winprint", to keep NT happy
9436 * and I can use my nice printer checker.
9441 *r->out.info = NULL;
9443 if (!get_short_archi(r->in.environment)) {
9444 return WERR_INVALID_ENVIRONMENT;
9447 switch (r->in.level) {
9449 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9453 return WERR_INVALID_LEVEL;
9456 if (!W_ERROR_IS_OK(result)) {
9460 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9461 spoolss_EnumPrintProcessors,
9462 *r->out.info, r->in.level,
9464 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9465 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9467 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9470 /****************************************************************************
9471 fill_printprocdatatype1
9472 ****************************************************************************/
9474 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9475 struct spoolss_PrintProcDataTypesInfo1 *r,
9476 const char *name_array)
9478 r->name_array = talloc_strdup(mem_ctx, name_array);
9479 W_ERROR_HAVE_NO_MEMORY(r->name_array);
9484 /****************************************************************************
9485 enumprintprocdatatypes level 1.
9486 ****************************************************************************/
9488 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9489 union spoolss_PrintProcDataTypesInfo **info_p,
9493 union spoolss_PrintProcDataTypesInfo *info;
9495 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9496 W_ERROR_HAVE_NO_MEMORY(info);
9500 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9501 if (!W_ERROR_IS_OK(result)) {
9506 if (!W_ERROR_IS_OK(result)) {
9517 /****************************************************************
9518 _spoolss_EnumPrintProcessorDataTypes
9519 ****************************************************************/
9521 WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9522 struct spoolss_EnumPrintProcessorDataTypes *r)
9526 /* that's an [in out] buffer */
9528 if (!r->in.buffer && (r->in.offered != 0)) {
9529 return WERR_INVALID_PARAMETER;
9532 DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9536 *r->out.info = NULL;
9538 if (r->in.print_processor_name == NULL ||
9539 !strequal(r->in.print_processor_name, "winprint")) {
9540 return WERR_UNKNOWN_PRINTPROCESSOR;
9543 switch (r->in.level) {
9545 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9549 return WERR_INVALID_LEVEL;
9552 if (!W_ERROR_IS_OK(result)) {
9556 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9557 spoolss_EnumPrintProcessorDataTypes,
9558 *r->out.info, r->in.level,
9560 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9561 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9563 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9566 /****************************************************************************
9568 ****************************************************************************/
9570 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9571 struct spoolss_MonitorInfo1 *r,
9572 const char *monitor_name)
9574 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9575 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9580 /****************************************************************************
9582 ****************************************************************************/
9584 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9585 struct spoolss_MonitorInfo2 *r,
9586 const char *monitor_name,
9587 const char *environment,
9588 const char *dll_name)
9590 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9591 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9592 r->environment = talloc_strdup(mem_ctx, environment);
9593 W_ERROR_HAVE_NO_MEMORY(r->environment);
9594 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9595 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9600 /****************************************************************************
9601 enumprintmonitors level 1.
9602 ****************************************************************************/
9604 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9605 union spoolss_MonitorInfo **info_p,
9608 union spoolss_MonitorInfo *info;
9609 WERROR result = WERR_OK;
9611 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9612 W_ERROR_HAVE_NO_MEMORY(info);
9616 result = fill_monitor_1(info, &info[0].info1,
9618 if (!W_ERROR_IS_OK(result)) {
9622 result = fill_monitor_1(info, &info[1].info1,
9624 if (!W_ERROR_IS_OK(result)) {
9629 if (!W_ERROR_IS_OK(result)) {
9640 /****************************************************************************
9641 enumprintmonitors level 2.
9642 ****************************************************************************/
9644 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9645 union spoolss_MonitorInfo **info_p,
9648 union spoolss_MonitorInfo *info;
9649 WERROR result = WERR_OK;
9650 const char *architecture;
9652 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9653 W_ERROR_HAVE_NO_MEMORY(info);
9657 architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9660 GLOBAL_SPOOLSS_ARCHITECTURE);
9662 result = fill_monitor_2(info, &info[0].info2,
9666 if (!W_ERROR_IS_OK(result)) {
9670 result = fill_monitor_2(info, &info[1].info2,
9674 if (!W_ERROR_IS_OK(result)) {
9679 if (!W_ERROR_IS_OK(result)) {
9690 /****************************************************************
9691 _spoolss_EnumMonitors
9692 ****************************************************************/
9694 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9695 struct spoolss_EnumMonitors *r)
9699 /* that's an [in out] buffer */
9701 if (!r->in.buffer && (r->in.offered != 0)) {
9702 return WERR_INVALID_PARAMETER;
9705 DEBUG(5,("_spoolss_EnumMonitors\n"));
9708 * Enumerate the print monitors ...
9710 * Just reply with "Local Port", to keep NT happy
9711 * and I can use my nice printer checker.
9716 *r->out.info = NULL;
9718 switch (r->in.level) {
9720 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9724 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9728 return WERR_INVALID_LEVEL;
9731 if (!W_ERROR_IS_OK(result)) {
9735 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9736 spoolss_EnumMonitors,
9737 *r->out.info, r->in.level,
9739 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9740 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9742 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9745 /****************************************************************************
9746 ****************************************************************************/
9748 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9749 const print_queue_struct *queue,
9750 int count, int snum,
9751 struct spoolss_PrinterInfo2 *pinfo2,
9754 struct spoolss_JobInfo1 *r)
9759 for (i=0; i<count; i++) {
9760 if (queue[i].sysjob == sysjob) {
9766 if (found == false) {
9767 /* NT treats not found as bad param... yet another bad choice */
9768 return WERR_INVALID_PARAMETER;
9771 return fill_job_info1(mem_ctx,
9780 /****************************************************************************
9781 ****************************************************************************/
9783 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9784 const print_queue_struct *queue,
9785 int count, int snum,
9786 struct spoolss_PrinterInfo2 *pinfo2,
9789 struct spoolss_JobInfo2 *r)
9793 struct spoolss_DeviceMode *devmode;
9796 for (i=0; i<count; i++) {
9797 if (queue[i].sysjob == sysjob) {
9803 if (found == false) {
9804 /* NT treats not found as bad param... yet another bad
9806 return WERR_INVALID_PARAMETER;
9810 * if the print job does not have a DEVMODE associated with it,
9811 * just use the one for the printer. A NULL devicemode is not
9812 * a failure condition
9815 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9817 result = spoolss_create_default_devmode(mem_ctx,
9818 pinfo2->printername,
9820 if (!W_ERROR_IS_OK(result)) {
9821 DEBUG(3, ("Can't proceed w/o a devmode!\n"));
9826 return fill_job_info2(mem_ctx,
9836 /****************************************************************
9838 ****************************************************************/
9840 WERROR _spoolss_GetJob(struct pipes_struct *p,
9841 struct spoolss_GetJob *r)
9843 WERROR result = WERR_OK;
9844 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9845 const char *svc_name;
9849 struct tdb_print_db *pdb;
9850 print_queue_struct *queue = NULL;
9851 print_status_struct prt_status;
9853 /* that's an [in out] buffer */
9855 if (!r->in.buffer && (r->in.offered != 0)) {
9856 result = WERR_INVALID_PARAMETER;
9857 goto err_jinfo_free;
9860 DEBUG(5,("_spoolss_GetJob\n"));
9864 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9865 result = WERR_INVALID_HANDLE;
9866 goto err_jinfo_free;
9869 svc_name = lp_const_servicename(snum);
9870 if (svc_name == NULL) {
9871 result = WERR_INVALID_PARAMETER;
9872 goto err_jinfo_free;
9875 result = winreg_get_printer_internal(p->mem_ctx,
9876 get_session_info_system(),
9880 if (!W_ERROR_IS_OK(result)) {
9881 goto err_jinfo_free;
9884 pdb = get_print_db_byname(svc_name);
9886 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9887 result = WERR_INVALID_PARAMETER;
9888 goto err_pinfo_free;
9891 sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9892 release_print_db(pdb);
9894 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9895 result = WERR_INVALID_PARAMETER;
9896 goto err_pinfo_free;
9899 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9901 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9902 count, prt_status.status, prt_status.message));
9904 switch (r->in.level) {
9906 result = getjob_level_1(p->mem_ctx,
9907 queue, count, snum, pinfo2,
9908 r->in.job_id, sysjob,
9909 &r->out.info->info1);
9912 result = getjob_level_2(p->mem_ctx,
9913 queue, count, snum, pinfo2,
9914 r->in.job_id, sysjob,
9915 &r->out.info->info2);
9918 result = WERR_INVALID_LEVEL;
9923 TALLOC_FREE(pinfo2);
9925 if (!W_ERROR_IS_OK(result)) {
9926 goto err_jinfo_free;
9929 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9931 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9933 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9936 TALLOC_FREE(pinfo2);
9938 TALLOC_FREE(r->out.info);
9942 /****************************************************************
9943 _spoolss_GetPrinterDataEx
9944 ****************************************************************/
9946 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9947 struct spoolss_GetPrinterDataEx *r)
9950 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9951 const char *printer;
9953 WERROR result = WERR_OK;
9955 enum winreg_Type val_type = REG_NONE;
9956 uint8_t *val_data = NULL;
9957 uint32_t val_size = 0;
9958 struct dcerpc_binding_handle *b;
9959 TALLOC_CTX *tmp_ctx;
9961 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9963 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9964 r->in.key_name, r->in.value_name));
9966 /* in case of problem, return some default values */
9969 *r->out.type = REG_NONE;
9971 tmp_ctx = talloc_new(p->mem_ctx);
9973 return WERR_NOT_ENOUGH_MEMORY;
9977 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9978 OUR_HANDLE(r->in.handle)));
9979 result = WERR_INVALID_HANDLE;
9983 /* Is the handle to a printer or to the server? */
9985 if (Printer->printer_type == SPLHND_SERVER) {
9987 union spoolss_PrinterData data;
9989 result = getprinterdata_printer_server(tmp_ctx,
9993 if (!W_ERROR_IS_OK(result)) {
9997 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9998 *r->out.type, &data);
9999 if (!W_ERROR_IS_OK(result)) {
10003 *r->out.needed = blob.length;
10005 if (r->in.offered >= *r->out.needed) {
10006 memcpy(r->out.data, blob.data, blob.length);
10013 /* check to see if the keyname is valid */
10014 if (!strlen(r->in.key_name)) {
10015 result = WERR_INVALID_PARAMETER;
10019 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10020 result = WERR_INVALID_HANDLE;
10023 printer = lp_const_servicename(snum);
10025 result = winreg_printer_binding_handle(tmp_ctx,
10026 get_session_info_system(),
10029 if (!W_ERROR_IS_OK(result)) {
10033 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
10034 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
10035 strequal(r->in.value_name, "ChangeId")) {
10036 *r->out.type = REG_DWORD;
10037 *r->out.needed = 4;
10038 if (r->in.offered >= *r->out.needed) {
10039 uint32_t changeid = 0;
10041 result = winreg_printer_get_changeid(tmp_ctx, b,
10044 if (!W_ERROR_IS_OK(result)) {
10048 SIVAL(r->out.data, 0, changeid);
10054 result = winreg_get_printer_dataex(tmp_ctx, b,
10061 if (!W_ERROR_IS_OK(result)) {
10065 *r->out.needed = val_size;
10066 *r->out.type = val_type;
10068 if (r->in.offered >= *r->out.needed) {
10069 memcpy(r->out.data, val_data, val_size);
10073 /* NOTE: do not replace type when returning WERR_MORE_DATA */
10075 if (W_ERROR_IS_OK(result)) {
10076 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10079 talloc_free(tmp_ctx);
10083 /****************************************************************
10084 _spoolss_SetPrinterDataEx
10085 ****************************************************************/
10087 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
10088 struct spoolss_SetPrinterDataEx *r)
10090 const struct loadparm_substitution *lp_sub =
10091 loadparm_s3_global_substitution();
10092 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
10094 WERROR result = WERR_OK;
10095 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10097 struct dcerpc_binding_handle *b;
10098 TALLOC_CTX *tmp_ctx;
10100 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
10102 /* From MSDN documentation of SetPrinterDataEx: pass request to
10103 SetPrinterData if key is "PrinterDriverData" */
10106 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
10107 OUR_HANDLE(r->in.handle)));
10108 return WERR_INVALID_HANDLE;
10111 if (Printer->printer_type == SPLHND_SERVER) {
10112 DEBUG(10,("_spoolss_SetPrinterDataEx: "
10113 "Not implemented for server handles yet\n"));
10114 return WERR_INVALID_PARAMETER;
10117 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10118 return WERR_INVALID_HANDLE;
10122 * Access check : NT returns "access denied" if you make a
10123 * SetPrinterData call without the necessary privilege.
10124 * we were originally returning OK if nothing changed
10125 * which made Win2k issue **a lot** of SetPrinterData
10126 * when connecting to a printer --jerry
10129 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10130 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10131 "change denied by handle access permissions\n"));
10132 return WERR_ACCESS_DENIED;
10135 tmp_ctx = talloc_new(p->mem_ctx);
10137 return WERR_NOT_ENOUGH_MEMORY;
10140 result = winreg_printer_binding_handle(tmp_ctx,
10141 get_session_info_system(),
10144 if (!W_ERROR_IS_OK(result)) {
10148 result = winreg_get_printer(tmp_ctx, b,
10149 lp_servicename(talloc_tos(), lp_sub, snum),
10151 if (!W_ERROR_IS_OK(result)) {
10155 /* check for OID in valuename */
10157 oid_string = strchr(r->in.value_name, ',');
10159 *oid_string = '\0';
10163 /* save the registry data */
10165 result = winreg_set_printer_dataex(tmp_ctx, b,
10173 if (W_ERROR_IS_OK(result)) {
10174 /* save the OID if one was specified */
10176 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10177 r->in.key_name, SPOOL_OID_KEY);
10179 result = WERR_NOT_ENOUGH_MEMORY;
10184 * I'm not checking the status here on purpose. Don't know
10185 * if this is right, but I'm returning the status from the
10186 * previous set_printer_dataex() call. I have no idea if
10187 * this is right. --jerry
10189 winreg_set_printer_dataex(tmp_ctx, b,
10194 (uint8_t *) oid_string,
10195 strlen(oid_string) + 1);
10198 result = winreg_printer_update_changeid(tmp_ctx, b,
10199 lp_const_servicename(snum));
10204 talloc_free(tmp_ctx);
10208 /****************************************************************
10209 _spoolss_DeletePrinterDataEx
10210 ****************************************************************/
10212 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10213 struct spoolss_DeletePrinterDataEx *r)
10215 const char *printer;
10217 WERROR status = WERR_OK;
10218 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10220 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10223 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10224 "Invalid handle (%s:%u:%u).\n",
10225 OUR_HANDLE(r->in.handle)));
10226 return WERR_INVALID_HANDLE;
10229 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10230 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10231 "printer properties change denied by handle\n"));
10232 return WERR_ACCESS_DENIED;
10235 if (!r->in.value_name || !r->in.key_name) {
10236 return WERR_NOT_ENOUGH_MEMORY;
10239 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10240 return WERR_INVALID_HANDLE;
10242 printer = lp_const_servicename(snum);
10244 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10245 get_session_info_system(),
10250 if (W_ERROR_IS_OK(status)) {
10251 status = winreg_printer_update_changeid_internal(p->mem_ctx,
10252 get_session_info_system(),
10260 /****************************************************************
10261 _spoolss_EnumPrinterKey
10262 ****************************************************************/
10264 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10265 struct spoolss_EnumPrinterKey *r)
10268 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10270 WERROR result = WERR_FILE_NOT_FOUND;
10271 const char **array = NULL;
10274 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10277 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10278 OUR_HANDLE(r->in.handle)));
10279 return WERR_INVALID_HANDLE;
10282 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10283 return WERR_INVALID_HANDLE;
10286 result = winreg_enum_printer_key_internal(p->mem_ctx,
10287 get_session_info_system(),
10289 lp_const_servicename(snum),
10293 if (!W_ERROR_IS_OK(result)) {
10297 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10298 result = WERR_NOT_ENOUGH_MEMORY;
10302 *r->out._ndr_size = r->in.offered / 2;
10303 *r->out.needed = blob.length;
10305 if (r->in.offered < *r->out.needed) {
10306 result = WERR_MORE_DATA;
10309 r->out.key_buffer->string_array = array;
10313 if (!W_ERROR_IS_OK(result)) {
10314 TALLOC_FREE(array);
10315 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10316 *r->out.needed = 0;
10323 /****************************************************************
10324 _spoolss_DeletePrinterKey
10325 ****************************************************************/
10327 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10328 struct spoolss_DeletePrinterKey *r)
10330 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10333 const char *printer;
10334 struct dcerpc_binding_handle *b;
10335 TALLOC_CTX *tmp_ctx;
10337 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10340 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10341 OUR_HANDLE(r->in.handle)));
10342 return WERR_INVALID_HANDLE;
10345 /* if keyname == NULL, return error */
10346 if ( !r->in.key_name )
10347 return WERR_INVALID_PARAMETER;
10349 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10350 return WERR_INVALID_HANDLE;
10353 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10354 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10355 "printer properties change denied by handle\n"));
10356 return WERR_ACCESS_DENIED;
10359 printer = lp_const_servicename(snum);
10361 tmp_ctx = talloc_new(p->mem_ctx);
10363 return WERR_NOT_ENOUGH_MEMORY;
10366 status = winreg_printer_binding_handle(tmp_ctx,
10367 get_session_info_system(),
10370 if (!W_ERROR_IS_OK(status)) {
10374 /* delete the key and all subkeys */
10375 status = winreg_delete_printer_key(tmp_ctx, b,
10378 if (W_ERROR_IS_OK(status)) {
10379 status = winreg_printer_update_changeid(tmp_ctx, b,
10384 talloc_free(tmp_ctx);
10388 /****************************************************************
10389 _spoolss_EnumPrinterDataEx
10390 ****************************************************************/
10392 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10393 struct spoolss_EnumPrinterDataEx *r)
10395 uint32_t count = 0;
10396 struct spoolss_PrinterEnumValues *info = NULL;
10397 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10401 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10404 *r->out.needed = 0;
10405 *r->out.info = NULL;
10408 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10409 OUR_HANDLE(r->in.handle)));
10410 return WERR_INVALID_HANDLE;
10414 * first check for a keyname of NULL or "". Win2k seems to send
10415 * this a lot and we should send back WERR_INVALID_PARAMETER
10416 * no need to spend time looking up the printer in this case.
10420 if (!strlen(r->in.key_name)) {
10421 result = WERR_INVALID_PARAMETER;
10425 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10426 return WERR_INVALID_HANDLE;
10429 /* now look for a match on the key name */
10430 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10431 get_session_info_system(),
10433 lp_const_servicename(snum),
10437 if (!W_ERROR_IS_OK(result)) {
10441 *r->out.count = count;
10442 *r->out.info = info;
10445 if (!W_ERROR_IS_OK(result)) {
10449 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10450 spoolss_EnumPrinterDataEx,
10453 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10454 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10456 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10459 /****************************************************************************
10460 ****************************************************************************/
10462 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10463 const char *servername,
10464 const char *environment,
10465 struct spoolss_PrintProcessorDirectoryInfo1 *r)
10470 werr = compose_spoolss_server_path(mem_ctx,
10473 SPOOLSS_PRTPROCS_PATH,
10475 if (!W_ERROR_IS_OK(werr)) {
10479 DEBUG(4,("print processor directory: [%s]\n", path));
10481 r->directory_name = path;
10486 /****************************************************************
10487 _spoolss_GetPrintProcessorDirectory
10488 ****************************************************************/
10490 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10491 struct spoolss_GetPrintProcessorDirectory *r)
10494 char *prnproc_share = NULL;
10495 bool prnproc_share_exists = false;
10498 /* that's an [in out] buffer */
10500 if (!r->in.buffer && (r->in.offered != 0)) {
10501 result = WERR_INVALID_PARAMETER;
10502 goto err_info_free;
10505 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10508 *r->out.needed = 0;
10510 /* r->in.level is ignored */
10512 /* We always should reply with a local print processor directory so that
10513 * users are not forced to have a [prnproc$] share on the Samba spoolss
10514 * server, if users decide to do so, lets announce it though - Guenther */
10516 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10517 if (!prnproc_share) {
10518 result = WERR_NOT_ENOUGH_MEMORY;
10519 goto err_info_free;
10522 prnproc_share_exists = true;
10525 result = getprintprocessordirectory_level_1(p->mem_ctx,
10526 prnproc_share_exists ? r->in.server : NULL,
10528 &r->out.info->info1);
10529 if (!W_ERROR_IS_OK(result)) {
10530 goto err_info_free;
10533 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10534 r->out.info, r->in.level);
10535 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10537 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10540 TALLOC_FREE(r->out.info);
10544 /*******************************************************************
10545 ********************************************************************/
10547 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10548 const char *dllname)
10550 enum ndr_err_code ndr_err;
10551 struct spoolss_MonitorUi ui;
10553 ui.dll_name = dllname;
10555 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10556 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10557 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10558 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10560 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10563 /*******************************************************************
10564 Streams the monitor UI DLL name in UNICODE
10565 *******************************************************************/
10567 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10568 struct security_token *token, DATA_BLOB *in,
10569 DATA_BLOB *out, uint32_t *needed)
10571 const char *dllname = "tcpmonui.dll";
10573 *needed = (strlen(dllname)+1) * 2;
10575 if (out->length < *needed) {
10576 return WERR_INSUFFICIENT_BUFFER;
10579 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10580 return WERR_NOT_ENOUGH_MEMORY;
10586 /*******************************************************************
10587 ********************************************************************/
10589 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10590 struct spoolss_PortData1 *port1,
10591 const DATA_BLOB *buf)
10593 enum ndr_err_code ndr_err;
10594 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10595 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10596 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10597 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10599 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10602 /*******************************************************************
10603 ********************************************************************/
10605 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10606 struct spoolss_PortData2 *port2,
10607 const DATA_BLOB *buf)
10609 enum ndr_err_code ndr_err;
10610 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10611 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10612 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10613 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10615 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10618 /*******************************************************************
10619 Create a new TCP/IP port
10620 *******************************************************************/
10622 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10623 struct security_token *token, DATA_BLOB *in,
10624 DATA_BLOB *out, uint32_t *needed)
10626 struct spoolss_PortData1 port1;
10627 struct spoolss_PortData2 port2;
10628 char *device_uri = NULL;
10631 const char *portname;
10632 const char *hostaddress;
10634 uint32_t port_number;
10637 /* peek for spoolss_PortData version */
10639 if (!in || (in->length < (128 + 4))) {
10640 return WERR_GEN_FAILURE;
10643 version = IVAL(in->data, 128);
10647 ZERO_STRUCT(port1);
10649 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10650 return WERR_NOT_ENOUGH_MEMORY;
10653 portname = port1.portname;
10654 hostaddress = port1.hostaddress;
10655 queue = port1.queue;
10656 protocol = port1.protocol;
10657 port_number = port1.port_number;
10661 ZERO_STRUCT(port2);
10663 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10664 return WERR_NOT_ENOUGH_MEMORY;
10667 portname = port2.portname;
10668 hostaddress = port2.hostaddress;
10669 queue = port2.queue;
10670 protocol = port2.protocol;
10671 port_number = port2.port_number;
10675 DEBUG(1,("xcvtcp_addport: "
10676 "unknown version of port_data: %d\n", version));
10677 return WERR_UNKNOWN_PORT;
10680 /* create the device URI and call the add_port_hook() */
10682 switch (protocol) {
10683 case PROTOCOL_RAWTCP_TYPE:
10684 device_uri = talloc_asprintf(mem_ctx,
10685 "socket://%s:%d/", hostaddress,
10689 case PROTOCOL_LPR_TYPE:
10690 device_uri = talloc_asprintf(mem_ctx,
10691 "lpr://%s/%s", hostaddress, queue );
10695 return WERR_UNKNOWN_PORT;
10699 return WERR_NOT_ENOUGH_MEMORY;
10702 return add_port_hook(mem_ctx, token, portname, device_uri);
10705 /*******************************************************************
10706 *******************************************************************/
10708 struct xcv_api_table xcvtcp_cmds[] = {
10709 { "MonitorUI", xcvtcp_monitorui },
10710 { "AddPort", xcvtcp_addport},
10714 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10715 struct security_token *token, const char *command,
10722 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10724 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10725 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10726 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10729 return WERR_INVALID_FUNCTION;
10732 /*******************************************************************
10733 *******************************************************************/
10734 #if 0 /* don't support management using the "Local Port" monitor */
10736 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10737 struct security_token *token, DATA_BLOB *in,
10738 DATA_BLOB *out, uint32_t *needed)
10740 const char *dllname = "localui.dll";
10742 *needed = (strlen(dllname)+1) * 2;
10744 if (out->length < *needed) {
10745 return WERR_INSUFFICIENT_BUFFER;
10748 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10749 return WERR_NOT_ENOUGH_MEMORY;
10755 /*******************************************************************
10756 *******************************************************************/
10758 struct xcv_api_table xcvlocal_cmds[] = {
10759 { "MonitorUI", xcvlocal_monitorui },
10763 struct xcv_api_table xcvlocal_cmds[] = {
10770 /*******************************************************************
10771 *******************************************************************/
10773 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10774 struct security_token *token, const char *command,
10775 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10780 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10782 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10783 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10784 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10786 return WERR_INVALID_FUNCTION;
10789 /****************************************************************
10791 ****************************************************************/
10793 WERROR _spoolss_XcvData(struct pipes_struct *p,
10794 struct spoolss_XcvData *r)
10796 struct dcesrv_call_state *dce_call = p->dce_call;
10797 struct auth_session_info *session_info =
10798 dcesrv_call_session_info(dce_call);
10799 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10800 DATA_BLOB out_data = data_blob_null;
10804 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10805 OUR_HANDLE(r->in.handle)));
10806 return WERR_INVALID_HANDLE;
10809 /* Has to be a handle to the TCP/IP port monitor */
10811 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10812 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10813 return WERR_INVALID_HANDLE;
10816 /* requires administrative access to the server */
10818 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10819 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10820 return WERR_ACCESS_DENIED;
10823 /* Allocate the outgoing buffer */
10825 if (r->in.out_data_size) {
10826 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10827 if (out_data.data == NULL) {
10828 return WERR_NOT_ENOUGH_MEMORY;
10832 switch ( Printer->printer_type ) {
10833 case SPLHND_PORTMON_TCP:
10834 werror = process_xcvtcp_command(p->mem_ctx,
10835 session_info->security_token,
10836 r->in.function_name,
10837 &r->in.in_data, &out_data,
10840 case SPLHND_PORTMON_LOCAL:
10841 werror = process_xcvlocal_command(p->mem_ctx,
10842 session_info->security_token,
10843 r->in.function_name,
10844 &r->in.in_data, &out_data,
10848 werror = WERR_INVALID_PRINT_MONITOR;
10851 if (!W_ERROR_IS_OK(werror)) {
10855 *r->out.status_code = 0;
10857 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10858 memcpy(r->out.out_data, out_data.data,
10859 MIN(r->in.out_data_size, out_data.length));
10865 /****************************************************************
10866 _spoolss_AddPrintProcessor
10867 ****************************************************************/
10869 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10870 struct spoolss_AddPrintProcessor *r)
10872 /* for now, just indicate success and ignore the add. We'll
10873 automatically set the winprint processor for printer
10874 entries later. Used to debug the LexMark Optra S 1855 PCL
10880 /****************************************************************
10882 ****************************************************************/
10884 WERROR _spoolss_AddPort(struct pipes_struct *p,
10885 struct spoolss_AddPort *r)
10887 /* do what w2k3 does */
10889 return WERR_NOT_SUPPORTED;
10892 /****************************************************************
10893 _spoolss_GetPrinterDriver
10894 ****************************************************************/
10896 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10897 struct spoolss_GetPrinterDriver *r)
10899 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10900 return WERR_NOT_SUPPORTED;
10903 /****************************************************************
10904 _spoolss_ReadPrinter
10905 ****************************************************************/
10907 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10908 struct spoolss_ReadPrinter *r)
10910 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10911 return WERR_NOT_SUPPORTED;
10914 /****************************************************************
10915 _spoolss_WaitForPrinterChange
10916 ****************************************************************/
10918 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10919 struct spoolss_WaitForPrinterChange *r)
10921 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10922 return WERR_NOT_SUPPORTED;
10925 /****************************************************************
10926 _spoolss_ConfigurePort
10927 ****************************************************************/
10929 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10930 struct spoolss_ConfigurePort *r)
10932 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10933 return WERR_NOT_SUPPORTED;
10936 /****************************************************************
10937 _spoolss_DeletePort
10938 ****************************************************************/
10940 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10941 struct spoolss_DeletePort *r)
10943 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10944 return WERR_NOT_SUPPORTED;
10947 /****************************************************************
10948 _spoolss_CreatePrinterIC
10949 ****************************************************************/
10951 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10952 struct spoolss_CreatePrinterIC *r)
10954 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10955 return WERR_NOT_SUPPORTED;
10958 /****************************************************************
10959 _spoolss_PlayGDIScriptOnPrinterIC
10960 ****************************************************************/
10962 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10963 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10965 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10966 return WERR_NOT_SUPPORTED;
10969 /****************************************************************
10970 _spoolss_DeletePrinterIC
10971 ****************************************************************/
10973 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10974 struct spoolss_DeletePrinterIC *r)
10976 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10977 return WERR_NOT_SUPPORTED;
10980 /****************************************************************
10981 _spoolss_AddPrinterConnection
10982 ****************************************************************/
10984 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10985 struct spoolss_AddPrinterConnection *r)
10987 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10988 return WERR_NOT_SUPPORTED;
10991 /****************************************************************
10992 _spoolss_DeletePrinterConnection
10993 ****************************************************************/
10995 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10996 struct spoolss_DeletePrinterConnection *r)
10998 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10999 return WERR_NOT_SUPPORTED;
11002 /****************************************************************
11003 _spoolss_PrinterMessageBox
11004 ****************************************************************/
11006 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
11007 struct spoolss_PrinterMessageBox *r)
11009 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11010 return WERR_NOT_SUPPORTED;
11013 /****************************************************************
11014 _spoolss_AddMonitor
11015 ****************************************************************/
11017 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
11018 struct spoolss_AddMonitor *r)
11020 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11021 return WERR_NOT_SUPPORTED;
11024 /****************************************************************
11025 _spoolss_DeleteMonitor
11026 ****************************************************************/
11028 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
11029 struct spoolss_DeleteMonitor *r)
11031 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11032 return WERR_NOT_SUPPORTED;
11035 /****************************************************************
11036 _spoolss_DeletePrintProcessor
11037 ****************************************************************/
11039 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
11040 struct spoolss_DeletePrintProcessor *r)
11042 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11043 return WERR_NOT_SUPPORTED;
11046 /****************************************************************
11047 _spoolss_AddPrintProvidor
11048 ****************************************************************/
11050 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
11051 struct spoolss_AddPrintProvidor *r)
11053 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11054 return WERR_NOT_SUPPORTED;
11057 /****************************************************************
11058 _spoolss_DeletePrintProvidor
11059 ****************************************************************/
11061 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
11062 struct spoolss_DeletePrintProvidor *r)
11064 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11065 return WERR_NOT_SUPPORTED;
11068 /****************************************************************
11069 _spoolss_FindFirstPrinterChangeNotification
11070 ****************************************************************/
11072 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
11073 struct spoolss_FindFirstPrinterChangeNotification *r)
11075 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11076 return WERR_NOT_SUPPORTED;
11079 /****************************************************************
11080 _spoolss_FindNextPrinterChangeNotification
11081 ****************************************************************/
11083 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
11084 struct spoolss_FindNextPrinterChangeNotification *r)
11086 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11087 return WERR_NOT_SUPPORTED;
11090 /****************************************************************
11091 _spoolss_RouterFindFirstPrinterChangeNotificationOld
11092 ****************************************************************/
11094 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
11095 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
11097 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11098 return WERR_NOT_SUPPORTED;
11101 /****************************************************************
11102 _spoolss_ReplyOpenPrinter
11103 ****************************************************************/
11105 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
11106 struct spoolss_ReplyOpenPrinter *r)
11108 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11109 return WERR_NOT_SUPPORTED;
11112 /****************************************************************
11113 _spoolss_RouterReplyPrinter
11114 ****************************************************************/
11116 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
11117 struct spoolss_RouterReplyPrinter *r)
11119 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11120 return WERR_NOT_SUPPORTED;
11123 /****************************************************************
11124 _spoolss_ReplyClosePrinter
11125 ****************************************************************/
11127 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11128 struct spoolss_ReplyClosePrinter *r)
11130 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11131 return WERR_NOT_SUPPORTED;
11134 /****************************************************************
11136 ****************************************************************/
11138 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11139 struct spoolss_AddPortEx *r)
11141 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11142 return WERR_NOT_SUPPORTED;
11145 /****************************************************************
11146 _spoolss_RouterFindFirstPrinterChangeNotification
11147 ****************************************************************/
11149 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11150 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11152 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11153 return WERR_NOT_SUPPORTED;
11156 /****************************************************************
11157 _spoolss_SpoolerInit
11158 ****************************************************************/
11160 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11161 struct spoolss_SpoolerInit *r)
11163 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11164 return WERR_NOT_SUPPORTED;
11167 /****************************************************************
11168 _spoolss_ResetPrinterEx
11169 ****************************************************************/
11171 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11172 struct spoolss_ResetPrinterEx *r)
11174 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11175 return WERR_NOT_SUPPORTED;
11178 /****************************************************************
11179 _spoolss_RouterReplyPrinterEx
11180 ****************************************************************/
11182 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11183 struct spoolss_RouterReplyPrinterEx *r)
11185 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11186 return WERR_NOT_SUPPORTED;
11189 /****************************************************************
11191 ****************************************************************/
11193 WERROR _spoolss_44(struct pipes_struct *p,
11194 struct spoolss_44 *r)
11196 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11197 return WERR_NOT_SUPPORTED;
11200 /****************************************************************
11202 ****************************************************************/
11204 WERROR _spoolss_SetPort(struct pipes_struct *p,
11205 struct spoolss_SetPort *r)
11207 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11208 return WERR_NOT_SUPPORTED;
11211 /****************************************************************
11213 ****************************************************************/
11215 WERROR _spoolss_4a(struct pipes_struct *p,
11216 struct spoolss_4a *r)
11218 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11219 return WERR_NOT_SUPPORTED;
11222 /****************************************************************
11224 ****************************************************************/
11226 WERROR _spoolss_4b(struct pipes_struct *p,
11227 struct spoolss_4b *r)
11229 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11230 return WERR_NOT_SUPPORTED;
11233 /****************************************************************
11235 ****************************************************************/
11237 WERROR _spoolss_4c(struct pipes_struct *p,
11238 struct spoolss_4c *r)
11240 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11241 return WERR_NOT_SUPPORTED;
11244 /****************************************************************
11246 ****************************************************************/
11248 WERROR _spoolss_53(struct pipes_struct *p,
11249 struct spoolss_53 *r)
11251 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11252 return WERR_NOT_SUPPORTED;
11255 /****************************************************************
11256 _spoolss_AddPerMachineConnection
11257 ****************************************************************/
11259 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11260 struct spoolss_AddPerMachineConnection *r)
11262 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11263 return WERR_NOT_SUPPORTED;
11266 /****************************************************************
11267 _spoolss_DeletePerMachineConnection
11268 ****************************************************************/
11270 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11271 struct spoolss_DeletePerMachineConnection *r)
11273 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11274 return WERR_NOT_SUPPORTED;
11277 /****************************************************************
11278 _spoolss_EnumPerMachineConnections
11279 ****************************************************************/
11281 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11282 struct spoolss_EnumPerMachineConnections *r)
11284 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11285 return WERR_NOT_SUPPORTED;
11288 /****************************************************************
11290 ****************************************************************/
11292 WERROR _spoolss_5a(struct pipes_struct *p,
11293 struct spoolss_5a *r)
11295 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11296 return WERR_NOT_SUPPORTED;
11299 /****************************************************************
11301 ****************************************************************/
11303 WERROR _spoolss_5b(struct pipes_struct *p,
11304 struct spoolss_5b *r)
11306 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11307 return WERR_NOT_SUPPORTED;
11310 /****************************************************************
11312 ****************************************************************/
11314 WERROR _spoolss_5c(struct pipes_struct *p,
11315 struct spoolss_5c *r)
11317 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11318 return WERR_NOT_SUPPORTED;
11321 /****************************************************************
11323 ****************************************************************/
11325 WERROR _spoolss_5d(struct pipes_struct *p,
11326 struct spoolss_5d *r)
11328 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11329 return WERR_NOT_SUPPORTED;
11332 /****************************************************************
11334 ****************************************************************/
11336 WERROR _spoolss_5e(struct pipes_struct *p,
11337 struct spoolss_5e *r)
11339 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11340 return WERR_NOT_SUPPORTED;
11343 /****************************************************************
11345 ****************************************************************/
11347 WERROR _spoolss_5f(struct pipes_struct *p,
11348 struct spoolss_5f *r)
11350 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11351 return WERR_NOT_SUPPORTED;
11354 /****************************************************************
11356 ****************************************************************/
11358 WERROR _spoolss_60(struct pipes_struct *p,
11359 struct spoolss_60 *r)
11361 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11362 return WERR_NOT_SUPPORTED;
11365 /****************************************************************
11366 _spoolss_SendRecvBidiData
11367 ****************************************************************/
11369 WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11370 struct spoolss_SendRecvBidiData *r)
11372 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11373 return WERR_NOT_SUPPORTED;
11376 /****************************************************************
11378 ****************************************************************/
11380 WERROR _spoolss_62(struct pipes_struct *p,
11381 struct spoolss_62 *r)
11383 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11384 return WERR_NOT_SUPPORTED;
11387 /****************************************************************
11389 ****************************************************************/
11391 WERROR _spoolss_63(struct pipes_struct *p,
11392 struct spoolss_63 *r)
11394 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11395 return WERR_NOT_SUPPORTED;
11398 /****************************************************************
11400 ****************************************************************/
11402 WERROR _spoolss_64(struct pipes_struct *p,
11403 struct spoolss_64 *r)
11405 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11406 return WERR_NOT_SUPPORTED;
11409 /****************************************************************
11411 ****************************************************************/
11413 WERROR _spoolss_65(struct pipes_struct *p,
11414 struct spoolss_65 *r)
11416 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11417 return WERR_NOT_SUPPORTED;
11420 /****************************************************************
11421 _spoolss_GetCorePrinterDrivers
11422 ****************************************************************/
11424 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11425 struct spoolss_GetCorePrinterDrivers *r)
11427 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11428 return HRES_ERROR_NOT_SUPPORTED;
11431 /****************************************************************
11433 ****************************************************************/
11435 WERROR _spoolss_67(struct pipes_struct *p,
11436 struct spoolss_67 *r)
11438 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11439 return WERR_NOT_SUPPORTED;
11442 /****************************************************************
11443 _spoolss_GetPrinterDriverPackagePath
11444 ****************************************************************/
11446 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11447 struct spoolss_GetPrinterDriverPackagePath *r)
11449 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11450 return HRES_ERROR_NOT_SUPPORTED;
11453 /****************************************************************
11455 ****************************************************************/
11457 WERROR _spoolss_69(struct pipes_struct *p,
11458 struct spoolss_69 *r)
11460 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11461 return WERR_NOT_SUPPORTED;
11464 /****************************************************************
11466 ****************************************************************/
11468 WERROR _spoolss_6a(struct pipes_struct *p,
11469 struct spoolss_6a *r)
11471 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11472 return WERR_NOT_SUPPORTED;
11475 /****************************************************************
11477 ****************************************************************/
11479 WERROR _spoolss_6b(struct pipes_struct *p,
11480 struct spoolss_6b *r)
11482 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11483 return WERR_NOT_SUPPORTED;
11486 /****************************************************************
11488 ****************************************************************/
11490 WERROR _spoolss_6c(struct pipes_struct *p,
11491 struct spoolss_6c *r)
11493 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11494 return WERR_NOT_SUPPORTED;
11497 /****************************************************************
11499 ****************************************************************/
11501 WERROR _spoolss_6d(struct pipes_struct *p,
11502 struct spoolss_6d *r)
11504 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11505 return WERR_NOT_SUPPORTED;
11508 /****************************************************************
11509 _spoolss_GetJobNamedPropertyValue
11510 ****************************************************************/
11512 WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11513 struct spoolss_GetJobNamedPropertyValue *r)
11515 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11516 return WERR_NOT_SUPPORTED;
11519 /****************************************************************
11520 _spoolss_SetJobNamedProperty
11521 ****************************************************************/
11523 WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11524 struct spoolss_SetJobNamedProperty *r)
11526 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11527 return WERR_NOT_SUPPORTED;
11530 /****************************************************************
11531 _spoolss_DeleteJobNamedProperty
11532 ****************************************************************/
11534 WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11535 struct spoolss_DeleteJobNamedProperty *r)
11537 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11538 return WERR_NOT_SUPPORTED;
11541 /****************************************************************
11542 _spoolss_EnumJobNamedProperties
11543 ****************************************************************/
11545 WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11546 struct spoolss_EnumJobNamedProperties *r)
11548 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11549 return WERR_NOT_SUPPORTED;
11552 /****************************************************************
11554 ****************************************************************/
11556 WERROR _spoolss_72(struct pipes_struct *p,
11557 struct spoolss_72 *r)
11559 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11560 return WERR_NOT_SUPPORTED;
11563 /****************************************************************
11565 ****************************************************************/
11567 WERROR _spoolss_73(struct pipes_struct *p,
11568 struct spoolss_73 *r)
11570 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11571 return WERR_NOT_SUPPORTED;
11574 /****************************************************************
11575 _spoolss_RpcLogJobInfoForBranchOffice
11576 ****************************************************************/
11578 WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11579 struct spoolss_LogJobInfoForBranchOffice *r)
11581 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11582 return WERR_NOT_SUPPORTED;
11585 static NTSTATUS spoolss__op_init_server(struct dcesrv_context *dce_ctx,
11586 const struct dcesrv_endpoint_server *ep_server);
11588 static NTSTATUS spoolss__op_shutdown_server(struct dcesrv_context *dce_ctx,
11589 const struct dcesrv_endpoint_server *ep_server);
11591 #define DCESRV_INTERFACE_SPOOLSS_INIT_SERVER \
11592 spoolss_init_server
11594 #define DCESRV_INTERFACE_SPOOLSS_SHUTDOWN_SERVER \
11595 spoolss_shutdown_server
11597 static NTSTATUS spoolss_init_server(struct dcesrv_context *dce_ctx,
11598 const struct dcesrv_endpoint_server *ep_server)
11600 struct messaging_context *msg_ctx = global_messaging_context();
11604 * Migrate the printers first.
11606 ok = nt_printing_tdb_migrate(msg_ctx);
11608 return NT_STATUS_UNSUCCESSFUL;
11611 return spoolss__op_init_server(dce_ctx, ep_server);
11614 static NTSTATUS spoolss_shutdown_server(struct dcesrv_context *dce_ctx,
11615 const struct dcesrv_endpoint_server *ep_server)
11617 srv_spoolss_cleanup();
11619 return spoolss__op_shutdown_server(dce_ctx, ep_server);
11622 /* include the generated boilerplate */
11623 #include "librpc/gen_ndr/ndr_spoolss_scompat.c"