2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
41 #include "include/printing.h"
43 #include "../librpc/gen_ndr/netlogon.h"
45 #include "printing/notify.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62 ((info)?ndr_size_##fn(info, level, 0):0)
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
73 #define DBGC_CLASS DBGC_RPC_SRV
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
79 struct notify_back_channel;
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86 struct printer_handle *prev, *next;
87 bool document_started;
89 uint32_t jobid; /* jobid in printing backend */
91 const char *servername;
94 uint32_t access_granted;
99 uint32_t printerlocal;
100 struct spoolss_NotifyOption *option;
101 struct policy_handle cli_hnd;
102 struct notify_back_channel *cli_chan;
104 /* are we in a FindNextPrinterChangeNotify() call? */
106 struct messaging_context *msg_ctx;
113 /* devmode sent in the OpenPrinter() call */
114 struct spoolss_DeviceMode *devmode;
116 /* TODO cache the printer info2 structure */
117 struct spoolss_PrinterInfo2 *info2;
121 static struct printer_handle *printers_list;
123 struct printer_session_counter {
124 struct printer_session_counter *next;
125 struct printer_session_counter *prev;
131 static struct printer_session_counter *counter_list;
133 struct notify_back_channel {
134 struct notify_back_channel *prev, *next;
136 /* associated client */
137 struct sockaddr_storage client_address;
139 /* print notify back-channel pipe handle*/
140 struct rpc_pipe_client *cli_pipe;
141 struct cli_state *cli;
142 uint32_t active_connections;
145 static struct notify_back_channel *back_channels;
147 /* Map generic permissions to printer object specific permissions */
149 const struct standard_mapping printer_std_mapping = {
156 /* Map generic permissions to print server object specific permissions */
158 const struct standard_mapping printserver_std_mapping = {
165 /* API table for Xcv Monitor functions */
167 struct xcv_api_table {
169 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
172 static void prune_printername_cache(void);
174 /********************************************************************
175 * Canonicalize servername.
176 ********************************************************************/
178 static const char *canon_servername(const char *servername)
180 const char *pservername = servername;
181 while (*pservername == '\\') {
187 /* translate between internal status numbers and NT status numbers */
188 static int nt_printj_status(int v)
194 return JOB_STATUS_PAUSED;
196 return JOB_STATUS_SPOOLING;
198 return JOB_STATUS_PRINTING;
200 return JOB_STATUS_ERROR;
202 return JOB_STATUS_DELETING;
204 return JOB_STATUS_OFFLINE;
206 return JOB_STATUS_PAPEROUT;
208 return JOB_STATUS_PRINTED;
210 return JOB_STATUS_DELETED;
212 return JOB_STATUS_BLOCKED_DEVQ;
213 case LPQ_USER_INTERVENTION:
214 return JOB_STATUS_USER_INTERVENTION;
219 static int nt_printq_status(int v)
223 return PRINTER_STATUS_PAUSED;
232 /***************************************************************************
233 Disconnect from the client
234 ****************************************************************************/
236 static void srv_spoolss_replycloseprinter(int snum,
237 struct printer_handle *prn_hnd)
243 * Tell the specific printing tdb we no longer want messages for this printer
244 * by deregistering our PID.
247 if (!print_notify_deregister_pid(snum)) {
248 DEBUG(0, ("Failed to register our pid for printer %s\n",
249 lp_const_servicename(snum)));
252 /* weird if the test succeeds !!! */
253 if (prn_hnd->notify.cli_chan == NULL ||
254 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
255 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
256 prn_hnd->notify.cli_chan->active_connections == 0) {
257 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
258 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
259 TALLOC_FREE(prn_hnd->notify.cli_chan);
263 status = dcerpc_spoolss_ReplyClosePrinter(
264 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
266 &prn_hnd->notify.cli_hnd,
268 if (!NT_STATUS_IS_OK(status)) {
269 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
271 result = ntstatus_to_werror(status);
272 } else if (!W_ERROR_IS_OK(result)) {
273 DEBUG(0, ("reply_close_printer failed [%s].\n",
274 win_errstr(result)));
277 /* if it's the last connection, deconnect the IPC$ share */
278 if (prn_hnd->notify.cli_chan->active_connections == 1) {
280 cli_shutdown(prn_hnd->notify.cli_chan->cli);
281 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
282 TALLOC_FREE(prn_hnd->notify.cli_chan);
284 if (prn_hnd->notify.msg_ctx != NULL) {
285 messaging_deregister(prn_hnd->notify.msg_ctx,
286 MSG_PRINTER_NOTIFY2, NULL);
290 if (prn_hnd->notify.cli_chan) {
291 prn_hnd->notify.cli_chan->active_connections--;
292 prn_hnd->notify.cli_chan = NULL;
296 /****************************************************************************
297 Functions to free a printer entry datastruct.
298 ****************************************************************************/
300 static int printer_entry_destructor(struct printer_handle *Printer)
302 if (Printer->notify.cli_chan != NULL &&
303 Printer->notify.cli_chan->active_connections > 0) {
306 switch(Printer->printer_type) {
308 srv_spoolss_replycloseprinter(snum, Printer);
312 snum = print_queue_snum(Printer->sharename);
314 srv_spoolss_replycloseprinter(snum, Printer);
322 Printer->notify.flags=0;
323 Printer->notify.options=0;
324 Printer->notify.localmachine[0]='\0';
325 Printer->notify.printerlocal=0;
326 TALLOC_FREE(Printer->notify.option);
327 TALLOC_FREE(Printer->devmode);
329 /* Remove from the internal list. */
330 DLIST_REMOVE(printers_list, Printer);
334 /****************************************************************************
335 find printer index by handle
336 ****************************************************************************/
338 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
339 struct policy_handle *hnd)
341 struct printer_handle *find_printer = NULL;
343 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
344 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
351 /****************************************************************************
352 Close printer index by handle.
353 ****************************************************************************/
355 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
357 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
360 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
365 close_policy_hnd(p, hnd);
370 /****************************************************************************
371 Delete a printer given a handle.
372 ****************************************************************************/
374 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
375 const char *sharename,
376 struct messaging_context *msg_ctx)
378 char *cmd = lp_deleteprinter_command(talloc_tos());
379 char *command = NULL;
381 bool is_print_op = false;
383 /* can't fail if we don't try */
388 command = talloc_asprintf(ctx,
392 return WERR_NOT_ENOUGH_MEMORY;
395 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
397 DEBUG(10,("Running [%s]\n", command));
399 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
404 ret = smbrun(command, NULL, NULL);
406 /* Tell everyone we updated smb.conf. */
407 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
413 /********** END SePrintOperatorPrivlege BLOCK **********/
415 DEBUGADD(10,("returned [%d]\n", ret));
417 TALLOC_FREE(command);
420 return WERR_INVALID_HANDLE; /* What to return here? */
425 /****************************************************************************
426 Delete a printer given a handle.
427 ****************************************************************************/
429 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
431 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
435 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
437 return WERR_INVALID_HANDLE;
441 * It turns out that Windows allows delete printer on a handle
442 * opened by an admin user, then used on a pipe handle created
443 * by an anonymous user..... but they're working on security.... riiight !
447 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
448 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
449 return WERR_ACCESS_DENIED;
452 /* this does not need a become root since the access check has been
453 done on the handle already */
455 result = winreg_delete_printer_key_internal(p->mem_ctx,
456 get_session_info_system(),
460 if (!W_ERROR_IS_OK(result)) {
461 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
462 return WERR_INVALID_HANDLE;
465 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
466 Printer->sharename, p->msg_ctx);
467 if (!W_ERROR_IS_OK(result)) {
470 prune_printername_cache();
474 /****************************************************************************
475 Return the snum of a printer corresponding to an handle.
476 ****************************************************************************/
478 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
479 int *number, struct share_params **params)
481 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
484 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
489 switch (Printer->printer_type) {
491 DEBUG(4,("short name:%s\n", Printer->sharename));
492 *number = print_queue_snum(Printer->sharename);
493 return (*number != -1);
501 /****************************************************************************
502 Set printer handle type.
503 Check if it's \\server or \\server\printer
504 ****************************************************************************/
506 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
508 DEBUG(3,("Setting printer type=%s\n", handlename));
510 /* it's a print server */
511 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
512 DEBUGADD(4,("Printer is a print server\n"));
513 Printer->printer_type = SPLHND_SERVER;
515 /* it's a printer (set_printer_hnd_name() will handle port monitors */
517 DEBUGADD(4,("Printer is a printer\n"));
518 Printer->printer_type = SPLHND_PRINTER;
524 static void prune_printername_cache_fn(const char *key, const char *value,
525 time_t timeout, void *private_data)
530 static void prune_printername_cache(void)
532 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
535 /****************************************************************************
536 Set printer handle name.. Accept names like \\server, \\server\printer,
537 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
538 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
539 XcvDataPort() interface.
540 ****************************************************************************/
542 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
543 const struct auth_session_info *session_info,
544 struct messaging_context *msg_ctx,
545 struct printer_handle *Printer,
546 const char *handlename)
549 int n_services=lp_numservices();
551 const char *printername;
552 const char *servername = NULL;
555 struct spoolss_PrinterInfo2 *info2 = NULL;
560 * Hopefully nobody names his printers like this. Maybe \ or ,
561 * are illegal in printer names even?
563 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
567 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
568 (unsigned long)strlen(handlename)));
570 aprinter = discard_const_p(char, handlename);
571 if ( *handlename == '\\' ) {
572 servername = canon_servername(handlename);
573 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
577 if (!is_myname_or_ipaddr(servername)) {
578 return WERR_INVALID_PRINTER_NAME;
580 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
581 if (Printer->servername == NULL) {
582 return WERR_NOT_ENOUGH_MEMORY;
586 if (Printer->printer_type == SPLHND_SERVER) {
590 if (Printer->printer_type != SPLHND_PRINTER) {
591 return WERR_INVALID_HANDLE;
594 DEBUGADD(5, ("searching for [%s]\n", aprinter));
596 p = strchr(aprinter, ',');
603 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
605 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
611 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
614 /* check for the Port Monitor Interface */
615 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
616 Printer->printer_type = SPLHND_PORTMON_TCP;
617 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
620 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
621 Printer->printer_type = SPLHND_PORTMON_LOCAL;
622 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
626 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
627 if (cache_key == NULL) {
628 return WERR_NOT_ENOUGH_MEMORY;
632 * With hundreds of printers, the "for" loop iterating all
633 * shares can be quite expensive, as it is done on every
634 * OpenPrinter. The loop maps "aprinter" to "sname", the
635 * result of which we cache in gencache.
637 if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
638 found = (strcmp(tmp, printer_not_found) != 0);
640 DEBUG(4, ("Printer %s not found\n", aprinter));
642 return WERR_INVALID_PRINTER_NAME;
648 /* Search all sharenames first as this is easier than pulling
649 the printer_info_2 off of disk. Don't use find_service() since
650 that calls out to map_username() */
652 /* do another loop to look for printernames */
653 for (snum = 0; !found && snum < n_services; snum++) {
654 const char *printer = lp_const_servicename(snum);
656 /* no point going on if this is not a printer */
657 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
661 /* ignore [printers] share */
662 if (strequal(printer, "printers")) {
666 fstrcpy(sname, printer);
667 if (strequal(aprinter, printer)) {
672 /* no point looking up the printer object if
673 we aren't allowing printername != sharename */
674 if (lp_force_printername(snum)) {
678 result = winreg_get_printer_internal(mem_ctx,
683 if ( !W_ERROR_IS_OK(result) ) {
684 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
685 sname, win_errstr(result)));
689 printername = strrchr(info2->printername, '\\');
690 if (printername == NULL) {
691 printername = info2->printername;
696 if (strequal(printername, aprinter)) {
701 DEBUGADD(10, ("printername: %s\n", printername));
707 gencache_set(cache_key, printer_not_found,
708 time_mono(NULL) + 300);
709 TALLOC_FREE(cache_key);
710 DEBUGADD(4,("Printer not found\n"));
711 return WERR_INVALID_PRINTER_NAME;
714 gencache_set(cache_key, sname, time_mono(NULL) + 300);
715 TALLOC_FREE(cache_key);
717 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
719 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
724 /****************************************************************************
725 Find first available printer slot. creates a printer handle for you.
726 ****************************************************************************/
728 static WERROR open_printer_hnd(struct pipes_struct *p,
729 struct policy_handle *hnd,
731 uint32_t access_granted)
733 struct printer_handle *new_printer;
736 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
738 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
739 if (new_printer == NULL) {
740 return WERR_NOT_ENOUGH_MEMORY;
742 talloc_set_destructor(new_printer, printer_entry_destructor);
744 /* This also steals the printer_handle on the policy_handle */
745 if (!create_policy_hnd(p, hnd, new_printer)) {
746 TALLOC_FREE(new_printer);
747 return WERR_INVALID_HANDLE;
750 /* Add to the internal list. */
751 DLIST_ADD(printers_list, new_printer);
753 new_printer->notify.option=NULL;
755 if (!set_printer_hnd_printertype(new_printer, name)) {
756 close_printer_handle(p, hnd);
757 return WERR_INVALID_HANDLE;
760 result = set_printer_hnd_name(p->mem_ctx,
761 get_session_info_system(),
764 if (!W_ERROR_IS_OK(result)) {
765 close_printer_handle(p, hnd);
769 new_printer->access_granted = access_granted;
771 DEBUG(5, ("%d printer handles active\n",
772 (int)num_pipe_handles(p)));
777 /***************************************************************************
778 check to see if the client motify handle is monitoring the notification
779 given by (notify_type, notify_field).
780 **************************************************************************/
782 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
783 uint16_t notify_field)
788 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
789 uint16_t notify_field)
791 struct spoolss_NotifyOption *option = p->notify.option;
795 * Flags should always be zero when the change notify
796 * is registered by the client's spooler. A user Win32 app
797 * might use the flags though instead of the NOTIFY_OPTION_INFO
806 return is_monitoring_event_flags(
807 p->notify.flags, notify_type, notify_field);
809 for (i = 0; i < option->count; i++) {
811 /* Check match for notify_type */
813 if (option->types[i].type != notify_type)
816 /* Check match for field */
818 for (j = 0; j < option->types[i].count; j++) {
819 if (option->types[i].fields[j].field == notify_field) {
825 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
826 p->servername, p->sharename, notify_type, notify_field));
831 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
832 _data->data.integer[0] = _integer; \
833 _data->data.integer[1] = 0;
836 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
837 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
838 if (!_data->data.string.string) {\
839 _data->data.string.size = 0; \
841 _data->data.string.size = strlen_m_term(_p) * 2;
843 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
844 _data->data.devmode.devmode = _devmode;
846 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
851 struct spoolss_Time st;
855 if (!init_systemtime(&st, t)) {
859 p = talloc_array(mem_ctx, char, len);
865 * Systemtime must be linearized as a set of UINT16's.
866 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
869 SSVAL(p, 0, st.year);
870 SSVAL(p, 2, st.month);
871 SSVAL(p, 4, st.day_of_week);
873 SSVAL(p, 8, st.hour);
874 SSVAL(p, 10, st.minute);
875 SSVAL(p, 12, st.second);
876 SSVAL(p, 14, st.millisecond);
882 /* Convert a notification message to a struct spoolss_Notify */
884 static void notify_one_value(struct spoolss_notify_msg *msg,
885 struct spoolss_Notify *data,
888 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
891 static void notify_string(struct spoolss_notify_msg *msg,
892 struct spoolss_Notify *data,
895 /* The length of the message includes the trailing \0 */
897 data->data.string.size = msg->len * 2;
898 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
899 if (!data->data.string.string) {
900 data->data.string.size = 0;
905 static void notify_system_time(struct spoolss_notify_msg *msg,
906 struct spoolss_Notify *data,
909 data->data.string.string = NULL;
910 data->data.string.size = 0;
912 if (msg->len != sizeof(time_t)) {
913 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
918 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
919 &data->data.string.string,
920 &data->data.string.size);
923 struct notify2_message_table {
925 void (*fn)(struct spoolss_notify_msg *msg,
926 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
929 static struct notify2_message_table printer_notify_table[] = {
930 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
931 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
932 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
933 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
934 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
935 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
936 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
937 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
938 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
939 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
940 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
941 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
942 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
943 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
944 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
945 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
946 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
947 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
948 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
951 static struct notify2_message_table job_notify_table[] = {
952 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
953 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
954 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
955 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
956 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
957 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
958 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
959 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
960 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
961 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
962 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
963 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
964 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
965 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
966 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
967 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
968 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
969 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
970 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
971 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
972 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
973 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
974 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
975 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
979 /***********************************************************************
980 Allocate talloc context for container object
981 **********************************************************************/
983 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
988 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
993 /***********************************************************************
994 release all allocated memory and zero out structure
995 **********************************************************************/
997 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1003 talloc_destroy(ctr->ctx);
1010 /***********************************************************************
1011 **********************************************************************/
1013 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1021 /***********************************************************************
1022 **********************************************************************/
1024 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1026 if ( !ctr || !ctr->msg_groups )
1029 if ( idx >= ctr->num_groups )
1032 return &ctr->msg_groups[idx];
1036 /***********************************************************************
1037 How many groups of change messages do we have ?
1038 **********************************************************************/
1040 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1045 return ctr->num_groups;
1048 /***********************************************************************
1049 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1050 **********************************************************************/
1052 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1054 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1055 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1056 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1062 /* loop over all groups looking for a matching printer name */
1064 for ( i=0; i<ctr->num_groups; i++ ) {
1065 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1069 /* add a new group? */
1071 if ( i == ctr->num_groups ) {
1074 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1075 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1078 ctr->msg_groups = groups;
1080 /* clear the new entry and set the printer name */
1082 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1083 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1086 /* add the change messages; 'i' is the correct index now regardless */
1088 msg_grp = &ctr->msg_groups[i];
1090 msg_grp->num_msgs++;
1092 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1093 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1096 msg_grp->msgs = msg_list;
1098 new_slot = msg_grp->num_msgs-1;
1099 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1101 /* need to allocate own copy of data */
1103 if ( msg->len != 0 )
1104 msg_grp->msgs[new_slot].notify.data = (char *)
1105 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1107 return ctr->num_groups;
1110 static void construct_info_data(struct spoolss_Notify *info_data,
1111 enum spoolss_NotifyType type,
1112 uint16_t field, int id);
1114 /***********************************************************************
1115 Send a change notication message on all handles which have a call
1117 **********************************************************************/
1119 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1120 struct printer_handle *prn_hnd,
1121 SPOOLSS_NOTIFY_MSG *messages,
1123 struct spoolss_Notify **_notifies,
1126 struct spoolss_Notify *notifies;
1127 SPOOLSS_NOTIFY_MSG *msg;
1132 notifies = talloc_zero_array(mem_ctx,
1133 struct spoolss_Notify, num_msgs);
1138 for (i = 0; i < num_msgs; i++) {
1142 /* Are we monitoring this event? */
1144 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1148 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1149 "for printer [%s]\n",
1150 msg->type, msg->field, prn_hnd->sharename));
1153 * if the is a printer notification handle and not a job
1154 * notification type, then set the id to 0.
1155 * Otherwise just use what was specified in the message.
1157 * When registering change notification on a print server
1158 * handle we always need to send back the id (snum) matching
1159 * the printer for which the change took place.
1160 * For change notify registered on a printer handle,
1161 * this does not matter and the id should be 0.
1166 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1167 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1173 /* Convert unix jobid to smb jobid */
1175 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1176 id = sysjob_to_jobid(msg->id);
1179 DEBUG(3, ("no such unix jobid %d\n",
1185 construct_info_data(¬ifies[count],
1186 msg->type, msg->field, id);
1189 case PRINTER_NOTIFY_TYPE:
1190 if (printer_notify_table[msg->field].fn) {
1191 printer_notify_table[msg->field].fn(msg,
1192 ¬ifies[count], mem_ctx);
1196 case JOB_NOTIFY_TYPE:
1197 if (job_notify_table[msg->field].fn) {
1198 job_notify_table[msg->field].fn(msg,
1199 ¬ifies[count], mem_ctx);
1204 DEBUG(5, ("Unknown notification type %d\n",
1212 *_notifies = notifies;
1218 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1219 struct printer_handle *prn_hnd,
1220 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1222 struct spoolss_Notify *notifies;
1224 union spoolss_ReplyPrinterInfo info;
1225 struct spoolss_NotifyInfo info0;
1226 uint32_t reply_result;
1231 /* Is there notification on this handle? */
1232 if (prn_hnd->notify.cli_chan == NULL ||
1233 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1234 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1235 prn_hnd->notify.cli_chan->active_connections == 0) {
1239 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1240 prn_hnd->servername, prn_hnd->sharename));
1242 /* For this printer? Print servers always receive notifications. */
1243 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1244 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1248 DEBUG(10,("Our printer\n"));
1250 /* build the array of change notifications */
1251 ret = build_notify2_messages(mem_ctx, prn_hnd,
1253 msg_group->num_msgs,
1259 info0.version = 0x2;
1260 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1261 info0.count = count;
1262 info0.notifies = notifies;
1264 info.info0 = &info0;
1266 status = dcerpc_spoolss_RouterReplyPrinterEx(
1267 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1269 &prn_hnd->notify.cli_hnd,
1270 prn_hnd->notify.change, /* color */
1271 prn_hnd->notify.flags,
1273 0, /* reply_type, must be 0 */
1275 if (!NT_STATUS_IS_OK(status)) {
1276 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1278 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1279 nt_errstr(status)));
1280 werr = ntstatus_to_werror(status);
1281 } else if (!W_ERROR_IS_OK(werr)) {
1282 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1284 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1287 switch (reply_result) {
1290 case PRINTER_NOTIFY_INFO_DISCARDED:
1291 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1292 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1301 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1303 struct printer_handle *p;
1304 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1305 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1309 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1313 if (!msg_group->msgs) {
1314 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1318 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1320 /* loop over all printers */
1322 for (p = printers_list; p; p = p->next) {
1323 ret = send_notify2_printer(mem_ctx, p, msg_group);
1330 DEBUG(8,("send_notify2_changes: Exit...\n"));
1334 /***********************************************************************
1335 **********************************************************************/
1337 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1340 uint32_t tv_sec, tv_usec;
1343 /* Unpack message */
1345 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1348 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1350 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1353 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1354 &msg->notify.value[0], &msg->notify.value[1]);
1356 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1357 &msg->len, &msg->notify.data);
1359 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1360 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1362 tv->tv_sec = tv_sec;
1363 tv->tv_usec = tv_usec;
1366 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1367 msg->notify.value[1]));
1369 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1374 /********************************************************************
1375 Receive a notify2 message list
1376 ********************************************************************/
1378 static void receive_notify2_message_list(struct messaging_context *msg,
1381 struct server_id server_id,
1384 size_t msg_count, i;
1385 char *buf = (char *)data->data;
1388 SPOOLSS_NOTIFY_MSG notify;
1389 SPOOLSS_NOTIFY_MSG_CTR messages;
1392 if (data->length < 4) {
1393 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1397 msg_count = IVAL(buf, 0);
1400 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1402 if (msg_count == 0) {
1403 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1407 /* initialize the container */
1409 ZERO_STRUCT( messages );
1410 notify_msg_ctr_init( &messages );
1413 * build message groups for each printer identified
1414 * in a change_notify msg. Remember that a PCN message
1415 * includes the handle returned for the srv_spoolss_replyopenprinter()
1416 * call. Therefore messages are grouped according to printer handle.
1419 for ( i=0; i<msg_count; i++ ) {
1420 struct timeval msg_tv;
1422 if (msg_ptr + 4 - buf > data->length) {
1423 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1427 msg_len = IVAL(msg_ptr,0);
1430 if (msg_ptr + msg_len - buf > data->length) {
1431 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1435 /* unpack messages */
1437 ZERO_STRUCT( notify );
1438 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1441 /* add to correct list in container */
1443 notify_msg_ctr_addmsg( &messages, ¬ify );
1445 /* free memory that might have been allocated by notify2_unpack_msg() */
1447 if ( notify.len != 0 )
1448 SAFE_FREE( notify.notify.data );
1451 /* process each group of messages */
1453 num_groups = notify_msg_ctr_numgroups( &messages );
1454 for ( i=0; i<num_groups; i++ )
1455 send_notify2_changes( &messages, i );
1460 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1461 (uint32_t)msg_count ));
1463 notify_msg_ctr_destroy( &messages );
1468 /********************************************************************
1469 Send a message to ourself about new driver being installed
1470 so we can upgrade the information for each printer bound to this
1472 ********************************************************************/
1474 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1475 struct messaging_context *msg_ctx)
1477 int len = strlen(drivername);
1482 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1485 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1486 MSG_PRINTER_DRVUPGRADE,
1487 (const uint8_t *)drivername, len+1);
1492 void srv_spoolss_cleanup(void)
1494 struct printer_session_counter *session_counter;
1496 for (session_counter = counter_list;
1497 session_counter != NULL;
1498 session_counter = counter_list) {
1499 DLIST_REMOVE(counter_list, session_counter);
1500 TALLOC_FREE(session_counter);
1504 /**********************************************************************
1505 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1506 over all printers, upgrading ones as necessary
1507 This is now *ONLY* called inside the background lpq updater. JRA.
1508 **********************************************************************/
1510 void do_drv_upgrade_printer(struct messaging_context *msg,
1513 struct server_id server_id,
1516 TALLOC_CTX *tmp_ctx;
1517 const struct auth_session_info *session_info = get_session_info_system();
1518 struct spoolss_PrinterInfo2 *pinfo2;
1520 const char *drivername;
1522 int n_services = lp_numservices();
1523 struct dcerpc_binding_handle *b = NULL;
1525 tmp_ctx = talloc_new(NULL);
1526 if (!tmp_ctx) return;
1528 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1530 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1534 DEBUG(10, ("do_drv_upgrade_printer: "
1535 "Got message for new driver [%s]\n", drivername));
1537 /* Iterate the printer list */
1539 for (snum = 0; snum < n_services; snum++) {
1540 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1544 /* ignore [printers] share */
1545 if (strequal(lp_const_servicename(snum), "printers")) {
1550 result = winreg_printer_binding_handle(tmp_ctx,
1554 if (!W_ERROR_IS_OK(result)) {
1559 result = winreg_get_printer(tmp_ctx, b,
1560 lp_const_servicename(snum),
1563 if (!W_ERROR_IS_OK(result)) {
1567 if (!pinfo2->drivername) {
1571 if (strcmp(drivername, pinfo2->drivername) != 0) {
1575 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1577 /* all we care about currently is the change_id */
1578 result = winreg_printer_update_changeid(tmp_ctx, b,
1579 pinfo2->printername);
1581 if (!W_ERROR_IS_OK(result)) {
1582 DEBUG(3, ("do_drv_upgrade_printer: "
1583 "Failed to update changeid [%s]\n",
1584 win_errstr(result)));
1590 talloc_free(tmp_ctx);
1593 /********************************************************************
1594 Update the cache for all printq's with a registered client
1596 ********************************************************************/
1598 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1600 struct printer_handle *printer = printers_list;
1603 /* loop through all printers and update the cache where
1604 a client is connected */
1606 if ((printer->printer_type == SPLHND_PRINTER) &&
1607 ((printer->notify.cli_chan != NULL) &&
1608 (printer->notify.cli_chan->active_connections > 0))) {
1609 snum = print_queue_snum(printer->sharename);
1610 print_queue_status(msg_ctx, snum, NULL, NULL);
1613 printer = printer->next;
1619 /****************************************************************
1620 _spoolss_OpenPrinter
1621 ****************************************************************/
1623 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1624 struct spoolss_OpenPrinter *r)
1626 struct spoolss_OpenPrinterEx e;
1627 struct spoolss_UserLevel1 level1;
1630 ZERO_STRUCT(level1);
1632 e.in.printername = r->in.printername;
1633 e.in.datatype = r->in.datatype;
1634 e.in.devmode_ctr = r->in.devmode_ctr;
1635 e.in.access_mask = r->in.access_mask;
1636 e.in.userlevel_ctr.level = 1;
1637 e.in.userlevel_ctr.user_info.level1 = &level1;
1639 e.out.handle = r->out.handle;
1641 werr = _spoolss_OpenPrinterEx(p, &e);
1643 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1644 /* OpenPrinterEx returns this for a bad
1645 * printer name. We must return WERR_INVALID_PRINTER_NAME
1648 werr = WERR_INVALID_PRINTER_NAME;
1654 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1655 struct spoolss_DeviceMode *orig,
1656 struct spoolss_DeviceMode **dest)
1658 struct spoolss_DeviceMode *dm;
1660 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1662 return WERR_NOT_ENOUGH_MEMORY;
1665 /* copy all values, then duplicate strings and structs */
1668 dm->devicename = talloc_strdup(dm, orig->devicename);
1669 if (!dm->devicename) {
1670 return WERR_NOT_ENOUGH_MEMORY;
1672 dm->formname = talloc_strdup(dm, orig->formname);
1673 if (!dm->formname) {
1674 return WERR_NOT_ENOUGH_MEMORY;
1676 if (orig->driverextra_data.data) {
1677 dm->driverextra_data.data =
1678 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1679 orig->driverextra_data.length);
1680 if (!dm->driverextra_data.data) {
1681 return WERR_NOT_ENOUGH_MEMORY;
1689 /****************************************************************
1690 _spoolss_OpenPrinterEx
1691 ****************************************************************/
1693 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1694 struct spoolss_OpenPrinterEx *r)
1699 struct printer_handle *Printer=NULL;
1703 if (!r->in.printername) {
1704 return WERR_INVALID_PARAMETER;
1707 if (!*r->in.printername) {
1708 return WERR_INVALID_PARAMETER;
1711 if (r->in.userlevel_ctr.level > 3) {
1712 return WERR_INVALID_PARAMETER;
1714 if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1715 (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1716 (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1717 return WERR_INVALID_PARAMETER;
1721 * The printcap printer share inventory is updated on client
1722 * enumeration. For clients that do not perform enumeration prior to
1723 * access, such as cupssmbadd, we reinitialise the printer share
1724 * inventory on open as well.
1727 delete_and_reload_printers(server_event_context(), p->msg_ctx);
1730 /* some sanity check because you can open a printer or a print server */
1731 /* aka: \\server\printer or \\server */
1733 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1735 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1736 if (!W_ERROR_IS_OK(result)) {
1737 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1738 "for printer %s\n", r->in.printername));
1739 ZERO_STRUCTP(r->out.handle);
1743 Printer = find_printer_index_by_hnd(p, r->out.handle);
1745 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1746 "handle we created for printer %s\n", r->in.printername));
1747 close_printer_handle(p, r->out.handle);
1748 ZERO_STRUCTP(r->out.handle);
1749 return WERR_INVALID_PARAMETER;
1753 * First case: the user is opening the print server:
1755 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1756 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1758 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1759 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1760 * or if the user is listed in the smb.conf printer admin parameter.
1762 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1763 * client view printer folder, but does not show the MSAPW.
1765 * Note: this test needs code to check access rights here too. Jeremy
1766 * could you look at this?
1768 * Second case: the user is opening a printer:
1769 * NT doesn't let us connect to a printer if the connecting user
1770 * doesn't have print permission.
1772 * Third case: user is opening a Port Monitor
1773 * access checks same as opening a handle to the print server.
1776 switch (Printer->printer_type )
1779 case SPLHND_PORTMON_TCP:
1780 case SPLHND_PORTMON_LOCAL:
1781 /* Printserver handles use global struct... */
1785 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1786 r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1787 r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1790 /* Map standard access rights to object specific access rights */
1792 se_map_standard(&r->in.access_mask,
1793 &printserver_std_mapping);
1795 /* Deny any object specific bits that don't apply to print
1796 servers (i.e printer and job specific bits) */
1798 r->in.access_mask &= SEC_MASK_SPECIFIC;
1800 if (r->in.access_mask &
1801 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1802 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1803 close_printer_handle(p, r->out.handle);
1804 ZERO_STRUCTP(r->out.handle);
1805 return WERR_ACCESS_DENIED;
1808 /* Allow admin access */
1810 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1812 if (!lp_show_add_printer_wizard()) {
1813 close_printer_handle(p, r->out.handle);
1814 ZERO_STRUCTP(r->out.handle);
1815 return WERR_ACCESS_DENIED;
1818 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1819 and not a printer admin, then fail */
1821 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1822 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1823 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1824 p->session_info->security_token)) {
1825 close_printer_handle(p, r->out.handle);
1826 ZERO_STRUCTP(r->out.handle);
1827 DEBUG(3,("access DENIED as user is not root, "
1828 "has no printoperator privilege and is "
1829 "not a member of the printoperator builtin group\n"));
1830 return WERR_ACCESS_DENIED;
1833 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1837 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1840 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1841 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1843 /* We fall through to return WERR_OK */
1846 case SPLHND_PRINTER:
1847 /* NT doesn't let us connect to a printer if the connecting user
1848 doesn't have print permission. */
1850 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1851 close_printer_handle(p, r->out.handle);
1852 ZERO_STRUCTP(r->out.handle);
1853 return WERR_INVALID_HANDLE;
1856 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1857 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1860 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1862 /* map an empty access mask to the minimum access mask */
1863 if (r->in.access_mask == 0x0)
1864 r->in.access_mask = PRINTER_ACCESS_USE;
1867 * If we are not serving the printer driver for this printer,
1868 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1869 * will keep NT clients happy --jerry
1872 if (lp_use_client_driver(snum)
1873 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1875 r->in.access_mask = PRINTER_ACCESS_USE;
1878 /* check smb.conf parameters and the the sec_desc */
1879 raddr = tsocket_address_inet_addr_string(p->remote_address,
1881 if (raddr == NULL) {
1882 return WERR_NOT_ENOUGH_MEMORY;
1885 rc = get_remote_hostname(p->remote_address,
1889 return WERR_NOT_ENOUGH_MEMORY;
1891 if (strequal(rhost, "UNKNOWN")) {
1895 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1897 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1898 ZERO_STRUCTP(r->out.handle);
1899 return WERR_ACCESS_DENIED;
1902 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1903 p->session_info->security_token, snum) ||
1904 !W_ERROR_IS_OK(print_access_check(p->session_info,
1907 r->in.access_mask))) {
1908 DEBUG(3, ("access DENIED for printer open\n"));
1909 close_printer_handle(p, r->out.handle);
1910 ZERO_STRUCTP(r->out.handle);
1911 return WERR_ACCESS_DENIED;
1914 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1915 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1916 close_printer_handle(p, r->out.handle);
1917 ZERO_STRUCTP(r->out.handle);
1918 return WERR_ACCESS_DENIED;
1921 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1922 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1924 r->in.access_mask = PRINTER_ACCESS_USE;
1926 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1927 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1929 winreg_create_printer_internal(p->mem_ctx,
1930 get_session_info_system(),
1932 lp_const_servicename(snum));
1937 /* sanity check to prevent programmer error */
1938 ZERO_STRUCTP(r->out.handle);
1939 return WERR_INVALID_HANDLE;
1942 Printer->access_granted = r->in.access_mask;
1945 * If the client sent a devmode in the OpenPrinter() call, then
1946 * save it here in case we get a job submission on this handle
1949 if ((Printer->printer_type != SPLHND_SERVER)
1950 && (r->in.devmode_ctr.devmode != NULL)) {
1951 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1958 /****************************************************************
1959 _spoolss_ClosePrinter
1960 ****************************************************************/
1962 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1963 struct spoolss_ClosePrinter *r)
1965 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1967 if (Printer && Printer->document_started) {
1968 struct spoolss_EndDocPrinter e;
1970 e.in.handle = r->in.handle;
1972 _spoolss_EndDocPrinter(p, &e);
1975 if (!close_printer_handle(p, r->in.handle))
1976 return WERR_INVALID_HANDLE;
1978 /* clear the returned printer handle. Observed behavior
1979 from Win2k server. Don't think this really matters.
1980 Previous code just copied the value of the closed
1983 ZERO_STRUCTP(r->out.handle);
1988 /****************************************************************
1989 _spoolss_DeletePrinter
1990 ****************************************************************/
1992 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1993 struct spoolss_DeletePrinter *r)
1995 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1999 if (Printer && Printer->document_started) {
2000 struct spoolss_EndDocPrinter e;
2002 e.in.handle = r->in.handle;
2004 _spoolss_EndDocPrinter(p, &e);
2007 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2008 winreg_delete_printer_key_internal(p->mem_ctx,
2009 get_session_info_system(),
2011 lp_const_servicename(snum),
2015 result = delete_printer_handle(p, r->in.handle);
2020 /*******************************************************************
2021 * static function to lookup the version id corresponding to an
2022 * long architecture string
2023 ******************************************************************/
2025 static const struct print_architecture_table_node archi_table[]= {
2027 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2028 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2029 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2030 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2031 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2032 {"Windows IA64", SPL_ARCH_IA64, 3 },
2033 {"Windows x64", SPL_ARCH_X64, 3 },
2037 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2038 SPOOLSS_DRIVER_VERSION_NT35,
2039 SPOOLSS_DRIVER_VERSION_NT4,
2040 SPOOLSS_DRIVER_VERSION_200X,
2043 static int get_version_id(const char *arch)
2047 for (i=0; archi_table[i].long_archi != NULL; i++)
2049 if (strcmp(arch, archi_table[i].long_archi) == 0)
2050 return (archi_table[i].version);
2056 /****************************************************************
2057 _spoolss_DeletePrinterDriver
2058 ****************************************************************/
2060 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2061 struct spoolss_DeletePrinterDriver *r)
2064 struct spoolss_DriverInfo8 *info = NULL;
2067 struct dcerpc_binding_handle *b;
2068 TALLOC_CTX *tmp_ctx = NULL;
2072 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2073 and not a printer admin, then fail */
2075 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2076 !security_token_has_privilege(p->session_info->security_token,
2077 SEC_PRIV_PRINT_OPERATOR)) {
2078 return WERR_ACCESS_DENIED;
2081 /* check that we have a valid driver name first */
2083 if ((version = get_version_id(r->in.architecture)) == -1) {
2084 return WERR_INVALID_ENVIRONMENT;
2087 tmp_ctx = talloc_new(p->mem_ctx);
2089 return WERR_NOT_ENOUGH_MEMORY;
2092 status = winreg_printer_binding_handle(tmp_ctx,
2093 get_session_info_system(),
2096 if (!W_ERROR_IS_OK(status)) {
2100 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2101 status = winreg_get_driver(tmp_ctx, b,
2102 r->in.architecture, r->in.driver,
2103 drv_cversion[i], &info);
2104 if (!W_ERROR_IS_OK(status)) {
2105 DEBUG(5, ("skipping del of driver with version %d\n",
2111 if (printer_driver_in_use(tmp_ctx, b, info)) {
2112 status = WERR_PRINTER_DRIVER_IN_USE;
2116 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2117 if (!W_ERROR_IS_OK(status)) {
2118 DEBUG(0, ("failed del of driver with version %d\n",
2123 if (found == false) {
2124 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2125 status = WERR_UNKNOWN_PRINTER_DRIVER;
2131 talloc_free(tmp_ctx);
2136 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2137 struct pipes_struct *p,
2138 struct spoolss_DeletePrinterDriverEx *r,
2139 struct dcerpc_binding_handle *b,
2140 struct spoolss_DriverInfo8 *info)
2145 if (printer_driver_in_use(mem_ctx, b, info)) {
2146 status = WERR_PRINTER_DRIVER_IN_USE;
2151 * we have a couple of cases to consider.
2152 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2153 * then the delete should fail if **any** files overlap with
2155 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2156 * non-overlapping files
2157 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2158 * are set, then do not delete any files
2159 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2162 delete_files = r->in.delete_flags
2163 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2167 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2168 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2169 status = WERR_PRINTER_DRIVER_IN_USE;
2173 * printer_driver_files_in_use() has trimmed overlapping files
2174 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2179 status = winreg_del_driver(mem_ctx, b, info, info->version);
2180 if (!W_ERROR_IS_OK(status)) {
2185 * now delete any associated files if delete_files is
2186 * true. Even if this part failes, we return succes
2187 * because the driver doesn not exist any more
2190 delete_driver_files(p->session_info, info);
2197 /****************************************************************
2198 _spoolss_DeletePrinterDriverEx
2199 ****************************************************************/
2201 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2202 struct spoolss_DeletePrinterDriverEx *r)
2204 struct spoolss_DriverInfo8 *info = NULL;
2206 struct dcerpc_binding_handle *b;
2207 TALLOC_CTX *tmp_ctx = NULL;
2211 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2212 and not a printer admin, then fail */
2214 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2215 !security_token_has_privilege(p->session_info->security_token,
2216 SEC_PRIV_PRINT_OPERATOR)) {
2217 return WERR_ACCESS_DENIED;
2220 /* check that we have a valid driver name first */
2221 if (get_version_id(r->in.architecture) == -1) {
2222 /* this is what NT returns */
2223 return WERR_INVALID_ENVIRONMENT;
2226 tmp_ctx = talloc_new(p->mem_ctx);
2228 return WERR_NOT_ENOUGH_MEMORY;
2231 status = winreg_printer_binding_handle(tmp_ctx,
2232 get_session_info_system(),
2235 if (!W_ERROR_IS_OK(status)) {
2239 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2240 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2241 && (drv_cversion[i] != r->in.version)) {
2245 /* check if a driver with this version exists before delete */
2246 status = winreg_get_driver(tmp_ctx, b,
2247 r->in.architecture, r->in.driver,
2248 drv_cversion[i], &info);
2249 if (!W_ERROR_IS_OK(status)) {
2250 DEBUG(5, ("skipping del of driver with version %d\n",
2256 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2257 if (!W_ERROR_IS_OK(status)) {
2258 DEBUG(0, ("failed to delete driver with version %d\n",
2263 if (found == false) {
2264 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2265 status = WERR_UNKNOWN_PRINTER_DRIVER;
2271 talloc_free(tmp_ctx);
2276 /********************************************************************
2277 GetPrinterData on a printer server Handle.
2278 ********************************************************************/
2280 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2282 enum winreg_Type *type,
2283 union spoolss_PrinterData *data)
2285 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2287 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2289 SIVAL(&data->value, 0, 0x00);
2293 if (!strcasecmp_m(value, "BeepEnabled")) {
2295 SIVAL(&data->value, 0, 0x00);
2299 if (!strcasecmp_m(value, "EventLog")) {
2301 /* formally was 0x1b */
2302 SIVAL(&data->value, 0, 0x00);
2306 if (!strcasecmp_m(value, "NetPopup")) {
2308 SIVAL(&data->value, 0, 0x00);
2312 if (!strcasecmp_m(value, "MajorVersion")) {
2315 /* Windows NT 4.0 seems to not allow uploading of drivers
2316 to a server that reports 0x3 as the MajorVersion.
2317 need to investigate more how Win2k gets around this .
2320 if (RA_WINNT == get_remote_arch()) {
2321 SIVAL(&data->value, 0, 0x02);
2323 SIVAL(&data->value, 0, 0x03);
2329 if (!strcasecmp_m(value, "MinorVersion")) {
2331 SIVAL(&data->value, 0, 0x00);
2336 * uint32_t size = 0x114
2337 * uint32_t major = 5
2338 * uint32_t minor = [0|1]
2339 * uint32_t build = [2195|2600]
2340 * extra unicode string = e.g. "Service Pack 3"
2342 if (!strcasecmp_m(value, "OSVersion")) {
2344 enum ndr_err_code ndr_err;
2345 struct spoolss_OSVersion os;
2347 os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2348 "spoolss", "os_major", 5);
2349 /* Windows 2000 == 5.0 */
2350 os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2351 "spoolss", "os_minor", 0);
2352 os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2353 "spoolss", "os_build", 2195);
2354 os.extra_string = ""; /* leave extra string empty */
2356 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2357 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2358 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2359 return WERR_GEN_FAILURE;
2362 if (DEBUGLEVEL >= 10) {
2363 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2367 data->binary = blob;
2373 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2376 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2377 W_ERROR_HAVE_NO_MEMORY(data->string);
2382 if (!strcasecmp_m(value, "Architecture")) {
2384 data->string = talloc_strdup(mem_ctx,
2385 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2386 W_ERROR_HAVE_NO_MEMORY(data->string);
2391 if (!strcasecmp_m(value, "DsPresent")) {
2394 /* only show the publish check box if we are a
2395 member of a AD domain */
2397 if (lp_security() == SEC_ADS) {
2398 SIVAL(&data->value, 0, 0x01);
2400 SIVAL(&data->value, 0, 0x00);
2405 if (!strcasecmp_m(value, "DNSMachineName")) {
2406 const char *hostname = get_mydnsfullname();
2409 return WERR_FILE_NOT_FOUND;
2413 data->string = talloc_strdup(mem_ctx, hostname);
2414 W_ERROR_HAVE_NO_MEMORY(data->string);
2421 return WERR_INVALID_PARAMETER;
2424 /****************************************************************
2425 _spoolss_GetPrinterData
2426 ****************************************************************/
2428 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2429 struct spoolss_GetPrinterData *r)
2431 struct spoolss_GetPrinterDataEx r2;
2433 r2.in.handle = r->in.handle;
2434 r2.in.key_name = "PrinterDriverData";
2435 r2.in.value_name = r->in.value_name;
2436 r2.in.offered = r->in.offered;
2437 r2.out.type = r->out.type;
2438 r2.out.data = r->out.data;
2439 r2.out.needed = r->out.needed;
2441 return _spoolss_GetPrinterDataEx(p, &r2);
2444 /*********************************************************
2445 Connect to the client machine.
2446 **********************************************************/
2448 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2449 struct sockaddr_storage *client_ss, const char *remote_machine)
2452 struct sockaddr_storage rm_addr;
2453 char addr[INET6_ADDRSTRLEN];
2455 if ( is_zero_addr(client_ss) ) {
2456 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2458 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2459 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2462 print_sockaddr(addr, sizeof(addr), &rm_addr);
2464 rm_addr = *client_ss;
2465 print_sockaddr(addr, sizeof(addr), &rm_addr);
2466 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2470 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2471 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2476 /* setup the connection */
2477 ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2478 &rm_addr, 0, "IPC$", "IPC",
2482 0, lp_client_signing());
2484 if ( !NT_STATUS_IS_OK( ret ) ) {
2485 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2490 if ( smbXcli_conn_protocol((*pp_cli)->conn) != PROTOCOL_NT1 ) {
2491 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2492 cli_shutdown(*pp_cli);
2497 * Ok - we have an anonymous connection to the IPC$ share.
2498 * Now start the NT Domain stuff :-).
2501 ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2502 if (!NT_STATUS_IS_OK(ret)) {
2503 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2504 remote_machine, nt_errstr(ret)));
2505 cli_shutdown(*pp_cli);
2512 /***************************************************************************
2513 Connect to the client.
2514 ****************************************************************************/
2516 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2517 uint32_t localprinter,
2518 enum winreg_Type type,
2519 struct policy_handle *handle,
2520 struct notify_back_channel **_chan,
2521 struct sockaddr_storage *client_ss,
2522 struct messaging_context *msg_ctx)
2526 struct notify_back_channel *chan;
2528 for (chan = back_channels; chan; chan = chan->next) {
2529 if (memcmp(&chan->client_address, client_ss,
2530 sizeof(struct sockaddr_storage)) == 0) {
2536 * If it's the first connection, contact the client
2537 * and connect to the IPC$ share anonymously
2540 fstring unix_printer;
2542 /* the +2 is to strip the leading 2 backslashs */
2543 fstrcpy(unix_printer, printer + 2);
2545 chan = talloc_zero(NULL, struct notify_back_channel);
2549 chan->client_address = *client_ss;
2551 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2556 DLIST_ADD(back_channels, chan);
2558 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2559 receive_notify2_message_list);
2562 if (chan->cli_pipe == NULL ||
2563 chan->cli_pipe->binding_handle == NULL) {
2564 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2565 "NULL %s for printer %s\n",
2566 chan->cli_pipe == NULL ?
2567 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2573 * Tell the specific printing tdb we want messages for this printer
2574 * by registering our PID.
2577 if (!print_notify_register_pid(snum)) {
2578 DEBUG(0, ("Failed to register our pid for printer %s\n",
2582 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2591 if (!NT_STATUS_IS_OK(status)) {
2592 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2593 result = ntstatus_to_werror(status);
2594 } else if (!W_ERROR_IS_OK(result)) {
2595 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2598 chan->active_connections++;
2601 return (W_ERROR_IS_OK(result));
2604 /****************************************************************
2605 ****************************************************************/
2607 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2608 const struct spoolss_NotifyOption *r)
2610 struct spoolss_NotifyOption *option;
2617 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2624 if (!option->count) {
2628 option->types = talloc_zero_array(option,
2629 struct spoolss_NotifyOptionType, option->count);
2630 if (!option->types) {
2631 talloc_free(option);
2635 for (i=0; i < option->count; i++) {
2636 option->types[i] = r->types[i];
2638 if (option->types[i].count) {
2639 option->types[i].fields = talloc_zero_array(option,
2640 union spoolss_Field, option->types[i].count);
2641 if (!option->types[i].fields) {
2642 talloc_free(option);
2645 for (k=0; k<option->types[i].count; k++) {
2646 option->types[i].fields[k] =
2647 r->types[i].fields[k];
2655 /****************************************************************
2656 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2658 * before replying OK: status=0 a rpc call is made to the workstation
2659 * asking ReplyOpenPrinter
2661 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2662 * called from api_spoolss_rffpcnex
2663 ****************************************************************/
2665 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2666 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2669 struct spoolss_NotifyOption *option = r->in.notify_options;
2670 struct sockaddr_storage client_ss;
2673 /* store the notify value in the printer struct */
2675 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2678 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2679 "Invalid handle (%s:%u:%u).\n",
2680 OUR_HANDLE(r->in.handle)));
2681 return WERR_INVALID_HANDLE;
2684 Printer->notify.flags = r->in.flags;
2685 Printer->notify.options = r->in.options;
2686 Printer->notify.printerlocal = r->in.printer_local;
2687 Printer->notify.msg_ctx = p->msg_ctx;
2689 TALLOC_FREE(Printer->notify.option);
2690 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2692 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2694 /* Connect to the client machine and send a ReplyOpenPrinter */
2696 if ( Printer->printer_type == SPLHND_SERVER)
2698 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2699 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2700 return WERR_INVALID_HANDLE;
2702 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2703 "remote_address is %s\n",
2704 tsocket_address_string(p->remote_address, p->mem_ctx)));
2706 if (!lp_print_notify_backchannel(snum)) {
2707 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2708 "backchannel disabled\n"));
2709 return WERR_RPC_S_SERVER_UNAVAILABLE;
2712 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2713 (struct sockaddr *) &client_ss,
2714 sizeof(struct sockaddr_storage));
2715 if (client_len < 0) {
2716 return WERR_NOT_ENOUGH_MEMORY;
2719 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2720 Printer->notify.printerlocal, REG_SZ,
2721 &Printer->notify.cli_hnd,
2722 &Printer->notify.cli_chan,
2723 &client_ss, p->msg_ctx)) {
2724 return WERR_RPC_S_SERVER_UNAVAILABLE;
2730 /*******************************************************************
2731 * fill a notify_info_data with the servername
2732 ********************************************************************/
2734 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2736 struct spoolss_Notify *data,
2737 print_queue_struct *queue,
2738 struct spoolss_PrinterInfo2 *pinfo2,
2739 TALLOC_CTX *mem_ctx)
2741 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2744 /*******************************************************************
2745 * fill a notify_info_data with the printername (not including the servername).
2746 ********************************************************************/
2748 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2750 struct spoolss_Notify *data,
2751 print_queue_struct *queue,
2752 struct spoolss_PrinterInfo2 *pinfo2,
2753 TALLOC_CTX *mem_ctx)
2755 /* the notify name should not contain the \\server\ part */
2756 const char *p = strrchr(pinfo2->printername, '\\');
2759 p = pinfo2->printername;
2764 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2767 /*******************************************************************
2768 * fill a notify_info_data with the servicename
2769 ********************************************************************/
2771 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2773 struct spoolss_Notify *data,
2774 print_queue_struct *queue,
2775 struct spoolss_PrinterInfo2 *pinfo2,
2776 TALLOC_CTX *mem_ctx)
2778 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2781 /*******************************************************************
2782 * fill a notify_info_data with the port name
2783 ********************************************************************/
2785 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2787 struct spoolss_Notify *data,
2788 print_queue_struct *queue,
2789 struct spoolss_PrinterInfo2 *pinfo2,
2790 TALLOC_CTX *mem_ctx)
2792 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2795 /*******************************************************************
2796 * fill a notify_info_data with the printername
2797 * but it doesn't exist, have to see what to do
2798 ********************************************************************/
2800 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2802 struct spoolss_Notify *data,
2803 print_queue_struct *queue,
2804 struct spoolss_PrinterInfo2 *pinfo2,
2805 TALLOC_CTX *mem_ctx)
2807 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2810 /*******************************************************************
2811 * fill a notify_info_data with the comment
2812 ********************************************************************/
2814 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2816 struct spoolss_Notify *data,
2817 print_queue_struct *queue,
2818 struct spoolss_PrinterInfo2 *pinfo2,
2819 TALLOC_CTX *mem_ctx)
2823 if (*pinfo2->comment == '\0') {
2824 p = lp_comment(talloc_tos(), snum);
2826 p = pinfo2->comment;
2829 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2832 /*******************************************************************
2833 * fill a notify_info_data with the comment
2834 * location = "Room 1, floor 2, building 3"
2835 ********************************************************************/
2837 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2839 struct spoolss_Notify *data,
2840 print_queue_struct *queue,
2841 struct spoolss_PrinterInfo2 *pinfo2,
2842 TALLOC_CTX *mem_ctx)
2844 const char *loc = pinfo2->location;
2847 status = printer_list_get_printer(mem_ctx,
2852 if (NT_STATUS_IS_OK(status)) {
2854 loc = pinfo2->location;
2858 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2861 /*******************************************************************
2862 * fill a notify_info_data with the device mode
2863 * jfm:xxxx don't to it for know but that's a real problem !!!
2864 ********************************************************************/
2866 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2868 struct spoolss_Notify *data,
2869 print_queue_struct *queue,
2870 struct spoolss_PrinterInfo2 *pinfo2,
2871 TALLOC_CTX *mem_ctx)
2873 /* for a dummy implementation we have to zero the fields */
2874 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2877 /*******************************************************************
2878 * fill a notify_info_data with the separator file name
2879 ********************************************************************/
2881 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2883 struct spoolss_Notify *data,
2884 print_queue_struct *queue,
2885 struct spoolss_PrinterInfo2 *pinfo2,
2886 TALLOC_CTX *mem_ctx)
2888 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2891 /*******************************************************************
2892 * fill a notify_info_data with the print processor
2893 * jfm:xxxx return always winprint to indicate we don't do anything to it
2894 ********************************************************************/
2896 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2898 struct spoolss_Notify *data,
2899 print_queue_struct *queue,
2900 struct spoolss_PrinterInfo2 *pinfo2,
2901 TALLOC_CTX *mem_ctx)
2903 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2906 /*******************************************************************
2907 * fill a notify_info_data with the print processor options
2908 * jfm:xxxx send an empty string
2909 ********************************************************************/
2911 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2913 struct spoolss_Notify *data,
2914 print_queue_struct *queue,
2915 struct spoolss_PrinterInfo2 *pinfo2,
2916 TALLOC_CTX *mem_ctx)
2918 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2921 /*******************************************************************
2922 * fill a notify_info_data with the data type
2923 * jfm:xxxx always send RAW as data type
2924 ********************************************************************/
2926 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2928 struct spoolss_Notify *data,
2929 print_queue_struct *queue,
2930 struct spoolss_PrinterInfo2 *pinfo2,
2931 TALLOC_CTX *mem_ctx)
2933 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2936 /*******************************************************************
2937 * fill a notify_info_data with the security descriptor
2938 * jfm:xxxx send an null pointer to say no security desc
2939 * have to implement security before !
2940 ********************************************************************/
2942 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2944 struct spoolss_Notify *data,
2945 print_queue_struct *queue,
2946 struct spoolss_PrinterInfo2 *pinfo2,
2947 TALLOC_CTX *mem_ctx)
2949 if (pinfo2->secdesc == NULL) {
2950 data->data.sd.sd = NULL;
2952 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2955 data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2959 /*******************************************************************
2960 * fill a notify_info_data with the attributes
2961 * jfm:xxxx a samba printer is always shared
2962 ********************************************************************/
2964 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2966 struct spoolss_Notify *data,
2967 print_queue_struct *queue,
2968 struct spoolss_PrinterInfo2 *pinfo2,
2969 TALLOC_CTX *mem_ctx)
2971 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2974 /*******************************************************************
2975 * fill a notify_info_data with the priority
2976 ********************************************************************/
2978 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2980 struct spoolss_Notify *data,
2981 print_queue_struct *queue,
2982 struct spoolss_PrinterInfo2 *pinfo2,
2983 TALLOC_CTX *mem_ctx)
2985 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2988 /*******************************************************************
2989 * fill a notify_info_data with the default priority
2990 ********************************************************************/
2992 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2994 struct spoolss_Notify *data,
2995 print_queue_struct *queue,
2996 struct spoolss_PrinterInfo2 *pinfo2,
2997 TALLOC_CTX *mem_ctx)
2999 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3002 /*******************************************************************
3003 * fill a notify_info_data with the start time
3004 ********************************************************************/
3006 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3008 struct spoolss_Notify *data,
3009 print_queue_struct *queue,
3010 struct spoolss_PrinterInfo2 *pinfo2,
3011 TALLOC_CTX *mem_ctx)
3013 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3016 /*******************************************************************
3017 * fill a notify_info_data with the until time
3018 ********************************************************************/
3020 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3022 struct spoolss_Notify *data,
3023 print_queue_struct *queue,
3024 struct spoolss_PrinterInfo2 *pinfo2,
3025 TALLOC_CTX *mem_ctx)
3027 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3030 /*******************************************************************
3031 * fill a notify_info_data with the status
3032 ********************************************************************/
3034 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3036 struct spoolss_Notify *data,
3037 print_queue_struct *queue,
3038 struct spoolss_PrinterInfo2 *pinfo2,
3039 TALLOC_CTX *mem_ctx)
3041 print_status_struct status;
3043 print_queue_length(msg_ctx, snum, &status);
3044 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3047 /*******************************************************************
3048 * fill a notify_info_data with the number of jobs queued
3049 ********************************************************************/
3051 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3053 struct spoolss_Notify *data,
3054 print_queue_struct *queue,
3055 struct spoolss_PrinterInfo2 *pinfo2,
3056 TALLOC_CTX *mem_ctx)
3058 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3059 data, print_queue_length(msg_ctx, snum, NULL));
3062 /*******************************************************************
3063 * fill a notify_info_data with the average ppm
3064 ********************************************************************/
3066 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3068 struct spoolss_Notify *data,
3069 print_queue_struct *queue,
3070 struct spoolss_PrinterInfo2 *pinfo2,
3071 TALLOC_CTX *mem_ctx)
3073 /* always respond 8 pages per minutes */
3074 /* a little hard ! */
3075 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3078 /*******************************************************************
3079 * fill a notify_info_data with username
3080 ********************************************************************/
3082 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3084 struct spoolss_Notify *data,
3085 print_queue_struct *queue,
3086 struct spoolss_PrinterInfo2 *pinfo2,
3087 TALLOC_CTX *mem_ctx)
3089 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3092 /*******************************************************************
3093 * fill a notify_info_data with job status
3094 ********************************************************************/
3096 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3098 struct spoolss_Notify *data,
3099 print_queue_struct *queue,
3100 struct spoolss_PrinterInfo2 *pinfo2,
3101 TALLOC_CTX *mem_ctx)
3103 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3106 /*******************************************************************
3107 * fill a notify_info_data with job name
3108 ********************************************************************/
3110 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3112 struct spoolss_Notify *data,
3113 print_queue_struct *queue,
3114 struct spoolss_PrinterInfo2 *pinfo2,
3115 TALLOC_CTX *mem_ctx)
3117 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3120 /*******************************************************************
3121 * fill a notify_info_data with job status
3122 ********************************************************************/
3124 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3126 struct spoolss_Notify *data,
3127 print_queue_struct *queue,
3128 struct spoolss_PrinterInfo2 *pinfo2,
3129 TALLOC_CTX *mem_ctx)
3132 * Now we're returning job status codes we just return a "" here. JRA.
3137 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3140 switch (queue->status) {
3145 p = ""; /* NT provides the paused string */
3154 #endif /* NO LONGER NEEDED. */
3156 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3159 /*******************************************************************
3160 * fill a notify_info_data with job time
3161 ********************************************************************/
3163 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3165 struct spoolss_Notify *data,
3166 print_queue_struct *queue,
3167 struct spoolss_PrinterInfo2 *pinfo2,
3168 TALLOC_CTX *mem_ctx)
3170 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3173 /*******************************************************************
3174 * fill a notify_info_data with job size
3175 ********************************************************************/
3177 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3179 struct spoolss_Notify *data,
3180 print_queue_struct *queue,
3181 struct spoolss_PrinterInfo2 *pinfo2,
3182 TALLOC_CTX *mem_ctx)
3184 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3187 /*******************************************************************
3188 * fill a notify_info_data with page info
3189 ********************************************************************/
3190 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3192 struct spoolss_Notify *data,
3193 print_queue_struct *queue,
3194 struct spoolss_PrinterInfo2 *pinfo2,
3195 TALLOC_CTX *mem_ctx)
3197 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3200 /*******************************************************************
3201 * fill a notify_info_data with pages printed info.
3202 ********************************************************************/
3203 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3205 struct spoolss_Notify *data,
3206 print_queue_struct *queue,
3207 struct spoolss_PrinterInfo2 *pinfo2,
3208 TALLOC_CTX *mem_ctx)
3210 /* Add code when back-end tracks this */
3211 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3214 /*******************************************************************
3215 Fill a notify_info_data with job position.
3216 ********************************************************************/
3218 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3220 struct spoolss_Notify *data,
3221 print_queue_struct *queue,
3222 struct spoolss_PrinterInfo2 *pinfo2,
3223 TALLOC_CTX *mem_ctx)
3225 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3228 /*******************************************************************
3229 Fill a notify_info_data with submitted time.
3230 ********************************************************************/
3232 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3234 struct spoolss_Notify *data,
3235 print_queue_struct *queue,
3236 struct spoolss_PrinterInfo2 *pinfo2,
3237 TALLOC_CTX *mem_ctx)
3239 data->data.string.string = NULL;
3240 data->data.string.size = 0;
3242 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3243 &data->data.string.string,
3244 &data->data.string.size);
3248 struct s_notify_info_data_table
3250 enum spoolss_NotifyType type;
3253 enum spoolss_NotifyTable variable_type;
3254 void (*fn) (struct messaging_context *msg_ctx,
3255 int snum, struct spoolss_Notify *data,
3256 print_queue_struct *queue,
3257 struct spoolss_PrinterInfo2 *pinfo2,
3258 TALLOC_CTX *mem_ctx);
3261 /* A table describing the various print notification constants and
3262 whether the notification data is a pointer to a variable sized
3263 buffer, a one value uint32_t or a two value uint32_t. */
3265 static const struct s_notify_info_data_table notify_info_data_table[] =
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3318 /*******************************************************************
3319 Return the variable_type of info_data structure.
3320 ********************************************************************/
3322 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3327 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3328 if ( (notify_info_data_table[i].type == type) &&
3329 (notify_info_data_table[i].field == field) ) {
3330 return notify_info_data_table[i].variable_type;
3334 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3336 return (enum spoolss_NotifyTable) 0;
3339 /****************************************************************************
3340 ****************************************************************************/
3342 static bool search_notify(enum spoolss_NotifyType type,
3348 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3349 if (notify_info_data_table[i].type == type &&
3350 notify_info_data_table[i].field == field &&
3351 notify_info_data_table[i].fn != NULL) {
3360 /****************************************************************************
3361 ****************************************************************************/
3363 static void construct_info_data(struct spoolss_Notify *info_data,
3364 enum spoolss_NotifyType type,
3365 uint16_t field, int id)
3367 info_data->type = type;
3368 info_data->field.field = field;
3369 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3370 info_data->job_id = id;
3373 /*******************************************************************
3375 * fill a notify_info struct with info asked
3377 ********************************************************************/
3379 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3380 struct printer_handle *print_hnd,
3381 struct spoolss_NotifyInfo *info,
3382 struct spoolss_PrinterInfo2 *pinfo2,
3384 const struct spoolss_NotifyOptionType *option_type,
3386 TALLOC_CTX *mem_ctx)
3389 enum spoolss_NotifyType type;
3392 struct spoolss_Notify *current_data;
3394 type = option_type->type;
3396 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3397 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3398 option_type->count, lp_servicename(talloc_tos(), snum)));
3400 for(field_num=0; field_num < option_type->count; field_num++) {
3401 field = option_type->fields[field_num].field;
3403 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3405 if (!search_notify(type, field, &j) )
3408 info->notifies = talloc_realloc(info, info->notifies,
3409 struct spoolss_Notify,
3411 if (info->notifies == NULL) {
3412 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3416 current_data = &info->notifies[info->count];
3418 construct_info_data(current_data, type, field, id);
3420 DEBUG(10, ("construct_notify_printer_info: "
3421 "calling [%s] snum=%d printername=[%s])\n",
3422 notify_info_data_table[j].name, snum,
3423 pinfo2->printername));
3425 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3426 NULL, pinfo2, mem_ctx);
3434 /*******************************************************************
3436 * fill a notify_info struct with info asked
3438 ********************************************************************/
3440 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3441 print_queue_struct *queue,
3442 struct spoolss_NotifyInfo *info,
3443 struct spoolss_PrinterInfo2 *pinfo2,
3445 const struct spoolss_NotifyOptionType *option_type,
3447 TALLOC_CTX *mem_ctx)
3450 enum spoolss_NotifyType type;
3452 struct spoolss_Notify *current_data;
3454 DEBUG(4,("construct_notify_jobs_info\n"));
3456 type = option_type->type;
3458 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3459 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3460 option_type->count));
3462 for(field_num=0; field_num<option_type->count; field_num++) {
3463 field = option_type->fields[field_num].field;
3465 if (!search_notify(type, field, &j) )
3468 info->notifies = talloc_realloc(info, info->notifies,
3469 struct spoolss_Notify,
3471 if (info->notifies == NULL) {
3472 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3476 current_data=&(info->notifies[info->count]);
3478 construct_info_data(current_data, type, field, id);
3479 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3480 queue, pinfo2, mem_ctx);
3488 * JFM: The enumeration is not that simple, it's even non obvious.
3490 * let's take an example: I want to monitor the PRINTER SERVER for
3491 * the printer's name and the number of jobs currently queued.
3492 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3493 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3495 * I have 3 printers on the back of my server.
3497 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3500 * 1 printer 1 name 1
3501 * 2 printer 1 cjob 1
3502 * 3 printer 2 name 2
3503 * 4 printer 2 cjob 2
3504 * 5 printer 3 name 3
3505 * 6 printer 3 name 3
3507 * that's the print server case, the printer case is even worse.
3510 /*******************************************************************
3512 * enumerate all printers on the printserver
3513 * fill a notify_info struct with info asked
3515 ********************************************************************/
3517 static WERROR printserver_notify_info(struct pipes_struct *p,
3518 struct policy_handle *hnd,
3519 struct spoolss_NotifyInfo *info,
3520 TALLOC_CTX *mem_ctx)
3523 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3524 int n_services=lp_numservices();
3526 struct spoolss_NotifyOption *option;
3527 struct spoolss_NotifyOptionType option_type;
3528 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3531 DEBUG(4,("printserver_notify_info\n"));
3534 return WERR_INVALID_HANDLE;
3536 option = Printer->notify.option;
3539 info->notifies = NULL;
3542 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3543 sending a ffpcn() request first */
3546 return WERR_INVALID_HANDLE;
3548 for (i=0; i<option->count; i++) {
3549 option_type = option->types[i];
3551 if (option_type.type != PRINTER_NOTIFY_TYPE)
3554 for (snum = 0; snum < n_services; snum++) {
3555 if (!lp_browseable(snum) ||
3556 !lp_snum_ok(snum) ||
3557 !lp_printable(snum)) {
3558 continue; /* skip */
3561 /* Maybe we should use the SYSTEM session_info here... */
3562 result = winreg_get_printer_internal(mem_ctx,
3563 get_session_info_system(),
3565 lp_servicename(talloc_tos(), snum),
3567 if (!W_ERROR_IS_OK(result)) {
3568 DEBUG(4, ("printserver_notify_info: "
3569 "Failed to get printer [%s]\n",
3570 lp_servicename(talloc_tos(), snum)));
3575 construct_notify_printer_info(p->msg_ctx,
3581 TALLOC_FREE(pinfo2);
3587 * Debugging information, don't delete.
3590 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3591 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3592 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3594 for (i=0; i<info->count; i++) {
3595 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3596 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3597 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3604 /*******************************************************************
3606 * fill a notify_info struct with info asked
3608 ********************************************************************/
3610 static WERROR printer_notify_info(struct pipes_struct *p,
3611 struct policy_handle *hnd,
3612 struct spoolss_NotifyInfo *info,
3613 TALLOC_CTX *mem_ctx)
3616 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3619 struct spoolss_NotifyOption *option;
3620 struct spoolss_NotifyOptionType option_type;
3622 print_queue_struct *queue=NULL;
3623 print_status_struct status;
3624 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3626 struct tdb_print_db *pdb;
3628 DEBUG(4,("printer_notify_info\n"));
3631 return WERR_INVALID_HANDLE;
3633 option = Printer->notify.option;
3637 info->notifies = NULL;
3640 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3641 sending a ffpcn() request first */
3644 return WERR_INVALID_HANDLE;
3646 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3647 return WERR_INVALID_HANDLE;
3650 pdb = get_print_db_byname(Printer->sharename);
3652 return WERR_INVALID_HANDLE;
3655 /* Maybe we should use the SYSTEM session_info here... */
3656 result = winreg_get_printer_internal(mem_ctx,
3657 get_session_info_system(),
3659 lp_servicename(talloc_tos(), snum), &pinfo2);
3660 if (!W_ERROR_IS_OK(result)) {
3661 result = WERR_INVALID_HANDLE;
3666 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3667 * correct servername.
3669 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3670 if (pinfo2->servername == NULL) {
3671 result = WERR_NOT_ENOUGH_MEMORY;
3675 for (i = 0; i < option->count; i++) {
3676 option_type = option->types[i];
3678 switch (option_type.type) {
3679 case PRINTER_NOTIFY_TYPE:
3680 if (construct_notify_printer_info(p->msg_ctx,
3689 case JOB_NOTIFY_TYPE:
3691 count = print_queue_status(p->msg_ctx, snum, &queue,
3694 for (j = 0; j < count; j++) {
3696 jobid = sysjob_to_jobid_pdb(pdb,
3698 if (jobid == (uint32_t)-1) {
3699 DEBUG(2, ("ignoring untracked job %d\n",
3703 /* FIXME check return value */
3704 construct_notify_jobs_info(p->msg_ctx,
3718 * Debugging information, don't delete.
3721 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3722 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3723 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3725 for (i=0; i<info->count; i++) {
3726 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3727 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3728 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3732 talloc_free(pinfo2);
3735 release_print_db(pdb);
3739 /****************************************************************
3740 _spoolss_RouterRefreshPrinterChangeNotify
3741 ****************************************************************/
3743 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3744 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3746 struct spoolss_NotifyInfo *info;
3748 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3749 WERROR result = WERR_INVALID_HANDLE;
3751 /* we always have a spoolss_NotifyInfo struct */
3752 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3754 result = WERR_NOT_ENOUGH_MEMORY;
3758 *r->out.info = info;
3761 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3762 "Invalid handle (%s:%u:%u).\n",
3763 OUR_HANDLE(r->in.handle)));
3767 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3770 * We are now using the change value, and
3771 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3772 * I don't have a global notification system, I'm sending back all the
3773 * information even when _NOTHING_ has changed.
3776 /* We need to keep track of the change value to send back in
3777 RRPCN replies otherwise our updates are ignored. */
3779 Printer->notify.fnpcn = true;
3781 if (Printer->notify.cli_chan != NULL &&
3782 Printer->notify.cli_chan->active_connections > 0) {
3783 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3784 "Saving change value in request [%x]\n",
3786 Printer->notify.change = r->in.change_low;
3789 /* just ignore the spoolss_NotifyOption */
3791 switch (Printer->printer_type) {
3793 result = printserver_notify_info(p, r->in.handle,
3797 case SPLHND_PRINTER:
3798 result = printer_notify_info(p, r->in.handle,
3803 Printer->notify.fnpcn = false;
3809 /********************************************************************
3810 ********************************************************************/
3812 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3813 const char *servername,
3814 const char *printername,
3815 const char **printername_p)
3817 /* FIXME: add lp_force_printername() */
3819 if (servername == NULL) {
3820 *printername_p = talloc_strdup(mem_ctx, printername);
3821 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3825 if (servername[0] == '\\' && servername[1] == '\\') {
3829 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3830 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3835 /********************************************************************
3836 ********************************************************************/
3838 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3839 const char *printername)
3845 dm->devicename = talloc_strndup(dm, printername,
3846 MIN(strlen(printername), 31));
3849 /********************************************************************
3850 * construct_printer_info_0
3851 * fill a printer_info_0 struct
3852 ********************************************************************/
3854 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3855 const struct auth_session_info *session_info,
3856 struct messaging_context *msg_ctx,
3857 struct spoolss_PrinterInfo2 *info2,
3858 const char *servername,
3859 struct spoolss_PrinterInfo0 *r,
3863 struct printer_session_counter *session_counter;
3864 struct timeval setuptime;
3865 print_status_struct status;
3868 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3869 if (!W_ERROR_IS_OK(result)) {
3874 r->servername = talloc_strdup(mem_ctx, servername);
3875 W_ERROR_HAVE_NO_MEMORY(r->servername);
3877 r->servername = NULL;
3880 count = print_queue_length(msg_ctx, snum, &status);
3882 /* check if we already have a counter for this printer */
3883 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3884 if (session_counter->snum == snum)
3888 /* it's the first time, add it to the list */
3889 if (session_counter == NULL) {
3890 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3891 W_ERROR_HAVE_NO_MEMORY(session_counter);
3892 session_counter->snum = snum;
3893 session_counter->counter = 0;
3894 DLIST_ADD(counter_list, session_counter);
3898 session_counter->counter++;
3904 get_startup_time(&setuptime);
3905 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3908 * the global_counter should be stored in a TDB as it's common to all the clients
3909 * and should be zeroed on samba startup
3911 r->global_counter = session_counter->counter;
3913 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3914 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3915 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3916 r->free_build = SPOOLSS_RELEASE_BUILD;
3918 r->max_spooling = 0;
3919 r->session_counter = session_counter->counter;
3920 r->num_error_out_of_paper = 0x0;
3921 r->num_error_not_ready = 0x0; /* number of print failure */
3923 r->number_of_processors = 0x1;
3924 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3925 r->high_part_total_bytes = 0x0;
3927 /* ChangeID in milliseconds*/
3928 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3929 info2->sharename, &r->change_id);
3931 r->last_error = WERR_OK;
3932 r->status = nt_printq_status(status.status);
3933 r->enumerate_network_printers = 0x0;
3934 r->c_setprinter = 0x0;
3935 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3936 r->processor_level = 0x6; /* 6 ???*/
3945 /********************************************************************
3946 * construct_printer_info1
3947 * fill a spoolss_PrinterInfo1 struct
3948 ********************************************************************/
3950 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3951 const struct spoolss_PrinterInfo2 *info2,
3953 const char *servername,
3954 struct spoolss_PrinterInfo1 *r,
3961 if (info2->comment == NULL || info2->comment[0] == '\0') {
3962 r->comment = lp_comment(mem_ctx, snum);
3964 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3966 W_ERROR_HAVE_NO_MEMORY(r->comment);
3968 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3969 if (!W_ERROR_IS_OK(result)) {
3973 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3977 W_ERROR_HAVE_NO_MEMORY(r->description);
3982 /********************************************************************
3983 * construct_printer_info2
3984 * fill a spoolss_PrinterInfo2 struct
3985 ********************************************************************/
3987 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3988 struct messaging_context *msg_ctx,
3989 const struct spoolss_PrinterInfo2 *info2,
3990 const char *servername,
3991 struct spoolss_PrinterInfo2 *r,
3995 print_status_struct status;
3998 count = print_queue_length(msg_ctx, snum, &status);
4001 r->servername = talloc_strdup(mem_ctx, servername);
4002 W_ERROR_HAVE_NO_MEMORY(r->servername);
4004 r->servername = NULL;
4007 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4008 if (!W_ERROR_IS_OK(result)) {
4012 r->sharename = lp_servicename(mem_ctx, snum);
4013 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4014 r->portname = talloc_strdup(mem_ctx, info2->portname);
4015 W_ERROR_HAVE_NO_MEMORY(r->portname);
4016 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4017 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4019 if (info2->comment[0] == '\0') {
4020 r->comment = lp_comment(mem_ctx, snum);
4022 r->comment = talloc_strdup(mem_ctx, info2->comment);
4024 W_ERROR_HAVE_NO_MEMORY(r->comment);
4026 r->location = talloc_strdup(mem_ctx, info2->location);
4027 if (info2->location[0] == '\0') {
4028 const char *loc = NULL;
4031 nt_status = printer_list_get_printer(mem_ctx,
4036 if (NT_STATUS_IS_OK(nt_status)) {
4038 r->location = talloc_strdup(mem_ctx, loc);
4042 W_ERROR_HAVE_NO_MEMORY(r->location);
4044 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4045 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4046 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4047 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4048 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4049 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4050 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4051 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4053 r->attributes = info2->attributes;
4055 r->priority = info2->priority;
4056 r->defaultpriority = info2->defaultpriority;
4057 r->starttime = info2->starttime;
4058 r->untiltime = info2->untiltime;
4059 r->status = nt_printq_status(status.status);
4061 r->averageppm = info2->averageppm;
4063 if (info2->devmode != NULL) {
4064 result = copy_devicemode(mem_ctx,
4067 if (!W_ERROR_IS_OK(result)) {
4070 } else if (lp_default_devmode(snum)) {
4071 result = spoolss_create_default_devmode(mem_ctx,
4074 if (!W_ERROR_IS_OK(result)) {
4079 DEBUG(8,("Returning NULL Devicemode!\n"));
4082 compose_devicemode_devicename(r->devmode, r->printername);
4086 if (info2->secdesc != NULL) {
4087 /* don't use talloc_steal() here unless you do a deep steal of all
4088 the SEC_DESC members */
4090 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4091 if (r->secdesc == NULL) {
4092 return WERR_NOT_ENOUGH_MEMORY;
4099 /********************************************************************
4100 * construct_printer_info3
4101 * fill a spoolss_PrinterInfo3 struct
4102 ********************************************************************/
4104 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4105 const struct spoolss_PrinterInfo2 *info2,
4106 const char *servername,
4107 struct spoolss_PrinterInfo3 *r,
4110 /* These are the components of the SD we are returning. */
4112 if (info2->secdesc != NULL) {
4113 /* don't use talloc_steal() here unless you do a deep steal of all
4114 the SEC_DESC members */
4116 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4117 if (r->secdesc == NULL) {
4118 return WERR_NOT_ENOUGH_MEMORY;
4125 /********************************************************************
4126 * construct_printer_info4
4127 * fill a spoolss_PrinterInfo4 struct
4128 ********************************************************************/
4130 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4131 const struct spoolss_PrinterInfo2 *info2,
4132 const char *servername,
4133 struct spoolss_PrinterInfo4 *r,
4138 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4139 if (!W_ERROR_IS_OK(result)) {
4144 r->servername = talloc_strdup(mem_ctx, servername);
4145 W_ERROR_HAVE_NO_MEMORY(r->servername);
4147 r->servername = NULL;
4150 r->attributes = info2->attributes;
4155 /********************************************************************
4156 * construct_printer_info5
4157 * fill a spoolss_PrinterInfo5 struct
4158 ********************************************************************/
4160 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4161 const struct spoolss_PrinterInfo2 *info2,
4162 const char *servername,
4163 struct spoolss_PrinterInfo5 *r,
4168 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4169 if (!W_ERROR_IS_OK(result)) {
4173 r->portname = talloc_strdup(mem_ctx, info2->portname);
4174 W_ERROR_HAVE_NO_MEMORY(r->portname);
4176 r->attributes = info2->attributes;
4178 /* these two are not used by NT+ according to MSDN */
4179 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4180 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4185 /********************************************************************
4186 * construct_printer_info_6
4187 * fill a spoolss_PrinterInfo6 struct
4188 ********************************************************************/
4190 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4191 struct messaging_context *msg_ctx,
4192 const struct spoolss_PrinterInfo2 *info2,
4193 const char *servername,
4194 struct spoolss_PrinterInfo6 *r,
4197 print_status_struct status;
4199 print_queue_length(msg_ctx, snum, &status);
4201 r->status = nt_printq_status(status.status);
4206 /********************************************************************
4207 * construct_printer_info7
4208 * fill a spoolss_PrinterInfo7 struct
4209 ********************************************************************/
4211 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4212 struct messaging_context *msg_ctx,
4213 const char *servername,
4214 struct spoolss_PrinterInfo7 *r,
4217 const struct auth_session_info *session_info;
4220 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4221 if (tmp_ctx == NULL) {
4222 return WERR_NOT_ENOUGH_MEMORY;
4225 session_info = get_session_info_system();
4226 SMB_ASSERT(session_info != NULL);
4228 printer = lp_servicename(tmp_ctx, snum);
4229 if (printer == NULL) {
4230 DEBUG(0, ("invalid printer snum %d\n", snum));
4231 werr = WERR_INVALID_PARAMETER;
4235 if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4236 servername, printer, NULL)) {
4238 struct GUID_txt_buf guid_txt;
4239 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4241 if (!W_ERROR_IS_OK(werr)) {
4243 * If we do not have a GUID entry in the registry, then
4244 * try to retrieve it from AD and store it now.
4246 werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4248 if (!W_ERROR_IS_OK(werr)) {
4249 DEBUG(1, ("Failed to retrieve GUID for "
4250 "printer [%s] from AD - "
4251 "Is the the printer still "
4252 "published ?\n", printer));
4256 werr = nt_printer_guid_store(msg_ctx, printer, guid);
4257 if (!W_ERROR_IS_OK(werr)) {
4258 DEBUG(3, ("failed to store printer %s guid\n",
4262 r->guid = talloc_strdup_upper(mem_ctx,
4263 GUID_buf_string(&guid, &guid_txt));
4264 r->action = DSPRINT_PUBLISH;
4266 r->guid = talloc_strdup(mem_ctx, "");
4267 r->action = DSPRINT_UNPUBLISH;
4269 if (r->guid == NULL) {
4270 werr = WERR_NOT_ENOUGH_MEMORY;
4276 talloc_free(tmp_ctx);
4280 /********************************************************************
4281 * construct_printer_info8
4282 * fill a spoolss_PrinterInfo8 struct
4283 ********************************************************************/
4285 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4286 const struct spoolss_PrinterInfo2 *info2,
4287 const char *servername,
4288 struct spoolss_DeviceModeInfo *r,
4292 const char *printername;
4294 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4295 if (!W_ERROR_IS_OK(result)) {
4299 if (info2->devmode != NULL) {
4300 result = copy_devicemode(mem_ctx,
4303 if (!W_ERROR_IS_OK(result)) {
4306 } else if (lp_default_devmode(snum)) {
4307 result = spoolss_create_default_devmode(mem_ctx,
4310 if (!W_ERROR_IS_OK(result)) {
4315 DEBUG(8,("Returning NULL Devicemode!\n"));
4318 compose_devicemode_devicename(r->devmode, printername);
4323 /********************************************************************
4324 Spoolss_enumprinters.
4325 ********************************************************************/
4327 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4328 const struct auth_session_info *session_info,
4329 struct messaging_context *msg_ctx,
4330 const char *servername,
4333 union spoolss_PrinterInfo **info_p,
4338 union spoolss_PrinterInfo *info = NULL;
4340 WERROR result = WERR_OK;
4341 struct dcerpc_binding_handle *b = NULL;
4342 TALLOC_CTX *tmp_ctx = NULL;
4344 tmp_ctx = talloc_new(mem_ctx);
4346 return WERR_NOT_ENOUGH_MEMORY;
4350 * printer shares are updated on client enumeration. The background
4351 * printer process updates printer_list.tdb at regular intervals.
4354 delete_and_reload_printers(server_event_context(), msg_ctx);
4357 n_services = lp_numservices();
4361 for (snum = 0; snum < n_services; snum++) {
4363 const char *printer;
4364 struct spoolss_PrinterInfo2 *info2;
4366 if (!snum_is_shared_printer(snum)) {
4370 printer = lp_const_servicename(snum);
4372 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4376 result = winreg_printer_binding_handle(tmp_ctx,
4380 if (!W_ERROR_IS_OK(result)) {
4385 result = winreg_create_printer(tmp_ctx, b,
4387 if (!W_ERROR_IS_OK(result)) {
4391 info = talloc_realloc(tmp_ctx, info,
4392 union spoolss_PrinterInfo,
4395 result = WERR_NOT_ENOUGH_MEMORY;
4399 result = winreg_get_printer(tmp_ctx, b,
4401 if (!W_ERROR_IS_OK(result)) {
4407 result = construct_printer_info0(info, session_info,
4410 &info[count].info0, snum);
4413 result = construct_printer_info1(info, info2, flags,
4415 &info[count].info1, snum);
4418 result = construct_printer_info2(info, msg_ctx, info2,
4420 &info[count].info2, snum);
4423 result = construct_printer_info4(info, info2,
4425 &info[count].info4, snum);
4428 result = construct_printer_info5(info, info2,
4430 &info[count].info5, snum);
4434 result = WERR_INVALID_LEVEL;
4438 if (!W_ERROR_IS_OK(result)) {
4446 if (W_ERROR_IS_OK(result)) {
4447 *info_p = talloc_move(mem_ctx, &info);
4451 talloc_free(tmp_ctx);
4456 /********************************************************************
4457 * handle enumeration of printers at level 0
4458 ********************************************************************/
4460 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4461 const struct auth_session_info *session_info,
4462 struct messaging_context *msg_ctx,
4464 const char *servername,
4465 union spoolss_PrinterInfo **info,
4468 DEBUG(4,("enum_all_printers_info_0\n"));
4470 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4471 servername, 0, flags, info, count);
4475 /********************************************************************
4476 ********************************************************************/
4478 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4479 const struct auth_session_info *session_info,
4480 struct messaging_context *msg_ctx,
4481 const char *servername,
4483 union spoolss_PrinterInfo **info,
4486 DEBUG(4,("enum_all_printers_info_1\n"));
4488 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4489 servername, 1, flags, info, count);
4492 /********************************************************************
4493 enum_all_printers_info_1_local.
4494 *********************************************************************/
4496 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4497 const struct auth_session_info *session_info,
4498 struct messaging_context *msg_ctx,
4499 const char *servername,
4500 union spoolss_PrinterInfo **info,
4503 DEBUG(4,("enum_all_printers_info_1_local\n"));
4505 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4506 servername, PRINTER_ENUM_ICON8, info, count);
4509 /********************************************************************
4510 enum_all_printers_info_1_name.
4511 *********************************************************************/
4513 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4514 const struct auth_session_info *session_info,
4515 struct messaging_context *msg_ctx,
4516 const char *servername,
4517 union spoolss_PrinterInfo **info,
4520 const char *s = servername;
4522 DEBUG(4,("enum_all_printers_info_1_name\n"));
4524 if (servername != NULL &&
4525 (servername[0] == '\\') && (servername[1] == '\\')) {
4529 if (!is_myname_or_ipaddr(s)) {
4530 return WERR_INVALID_NAME;
4533 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4534 servername, PRINTER_ENUM_ICON8, info, count);
4537 /********************************************************************
4538 enum_all_printers_info_1_network.
4539 *********************************************************************/
4541 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4542 const struct auth_session_info *session_info,
4543 struct messaging_context *msg_ctx,
4544 const char *servername,
4545 union spoolss_PrinterInfo **info,
4548 const char *s = servername;
4550 DEBUG(4,("enum_all_printers_info_1_network\n"));
4552 /* If we respond to a enum_printers level 1 on our name with flags
4553 set to PRINTER_ENUM_REMOTE with a list of printers then these
4554 printers incorrectly appear in the APW browse list.
4555 Specifically the printers for the server appear at the workgroup
4556 level where all the other servers in the domain are
4557 listed. Windows responds to this call with a
4558 WERR_CAN_NOT_COMPLETE so we should do the same. */
4560 if (servername != NULL &&
4561 (servername[0] == '\\') && (servername[1] == '\\')) {
4565 if (is_myname_or_ipaddr(s)) {
4566 return WERR_CAN_NOT_COMPLETE;
4569 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4570 servername, PRINTER_ENUM_NAME, info, count);
4573 /********************************************************************
4574 * api_spoolss_enumprinters
4576 * called from api_spoolss_enumprinters (see this to understand)
4577 ********************************************************************/
4579 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4580 const struct auth_session_info *session_info,
4581 struct messaging_context *msg_ctx,
4582 const char *servername,
4583 union spoolss_PrinterInfo **info,
4586 DEBUG(4,("enum_all_printers_info_2\n"));
4588 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4589 servername, 2, 0, info, count);
4592 /********************************************************************
4593 * handle enumeration of printers at level 1
4594 ********************************************************************/
4596 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4597 const struct auth_session_info *session_info,
4598 struct messaging_context *msg_ctx,
4600 const char *servername,
4601 union spoolss_PrinterInfo **info,
4604 /* Not all the flags are equals */
4606 if (flags & PRINTER_ENUM_LOCAL) {
4607 return enum_all_printers_info_1_local(mem_ctx, session_info,
4608 msg_ctx, servername, info, count);
4611 if (flags & PRINTER_ENUM_NAME) {
4612 return enum_all_printers_info_1_name(mem_ctx, session_info,
4613 msg_ctx, servername, info,
4617 if (flags & PRINTER_ENUM_NETWORK) {
4618 return enum_all_printers_info_1_network(mem_ctx, session_info,
4619 msg_ctx, servername, info,
4623 return WERR_OK; /* NT4sp5 does that */
4626 /********************************************************************
4627 * handle enumeration of printers at level 2
4628 ********************************************************************/
4630 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4631 const struct auth_session_info *session_info,
4632 struct messaging_context *msg_ctx,
4634 const char *servername,
4635 union spoolss_PrinterInfo **info,
4638 if (flags & PRINTER_ENUM_LOCAL) {
4640 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4645 if (flags & PRINTER_ENUM_NAME) {
4646 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4647 return WERR_INVALID_NAME;
4650 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4655 if (flags & PRINTER_ENUM_REMOTE) {
4656 return WERR_INVALID_LEVEL;
4662 /********************************************************************
4663 * handle enumeration of printers at level 4
4664 ********************************************************************/
4666 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4667 const struct auth_session_info *session_info,
4668 struct messaging_context *msg_ctx,
4670 const char *servername,
4671 union spoolss_PrinterInfo **info,
4674 DEBUG(4,("enum_all_printers_info_4\n"));
4676 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4677 servername, 4, flags, info, count);
4681 /********************************************************************
4682 * handle enumeration of printers at level 5
4683 ********************************************************************/
4685 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4686 const struct auth_session_info *session_info,
4687 struct messaging_context *msg_ctx,
4689 const char *servername,
4690 union spoolss_PrinterInfo **info,
4693 DEBUG(4,("enum_all_printers_info_5\n"));
4695 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4696 servername, 5, flags, info, count);
4699 /****************************************************************
4700 _spoolss_EnumPrinters
4701 ****************************************************************/
4703 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4704 struct spoolss_EnumPrinters *r)
4706 const struct auth_session_info *session_info = get_session_info_system();
4709 /* that's an [in out] buffer */
4711 if (!r->in.buffer && (r->in.offered != 0)) {
4712 return WERR_INVALID_PARAMETER;
4715 DEBUG(4,("_spoolss_EnumPrinters\n"));
4719 *r->out.info = NULL;
4723 * flags==PRINTER_ENUM_NAME
4724 * if name=="" then enumerates all printers
4725 * if name!="" then enumerate the printer
4726 * flags==PRINTER_ENUM_REMOTE
4727 * name is NULL, enumerate printers
4728 * Level 2: name!="" enumerates printers, name can't be NULL
4729 * Level 3: doesn't exist
4730 * Level 4: does a local registry lookup
4731 * Level 5: same as Level 2
4734 if (r->in.server && r->in.server[0] == '\0') {
4735 r->in.server = NULL;
4738 switch (r->in.level) {
4740 result = enumprinters_level0(p->mem_ctx, session_info,
4741 p->msg_ctx, r->in.flags,
4743 r->out.info, r->out.count);
4746 result = enumprinters_level1(p->mem_ctx, session_info,
4747 p->msg_ctx, r->in.flags,
4749 r->out.info, r->out.count);
4752 result = enumprinters_level2(p->mem_ctx, session_info,
4753 p->msg_ctx, r->in.flags,
4755 r->out.info, r->out.count);
4758 result = enumprinters_level4(p->mem_ctx, session_info,
4759 p->msg_ctx, r->in.flags,
4761 r->out.info, r->out.count);
4764 result = enumprinters_level5(p->mem_ctx, session_info,
4765 p->msg_ctx, r->in.flags,
4767 r->out.info, r->out.count);
4770 return WERR_INVALID_LEVEL;
4773 if (!W_ERROR_IS_OK(result)) {
4777 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4778 spoolss_EnumPrinters,
4779 *r->out.info, r->in.level,
4781 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4782 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4784 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4787 /****************************************************************
4789 ****************************************************************/
4791 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4792 struct spoolss_GetPrinter *r)
4794 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4795 struct spoolss_PrinterInfo2 *info2 = NULL;
4796 WERROR result = WERR_OK;
4799 /* that's an [in out] buffer */
4801 if (!r->in.buffer && (r->in.offered != 0)) {
4802 result = WERR_INVALID_PARAMETER;
4808 if (Printer == NULL) {
4809 result = WERR_INVALID_HANDLE;
4813 if (Printer->printer_type == SPLHND_SERVER) {
4815 struct dcerpc_binding_handle *b;
4817 if (r->in.level != 3) {
4818 result = WERR_INVALID_LEVEL;
4822 result = winreg_printer_binding_handle(p->mem_ctx,
4823 get_session_info_system(),
4826 if (!W_ERROR_IS_OK(result)) {
4830 result = winreg_get_printserver_secdesc(p->mem_ctx,
4832 &r->out.info->info3.secdesc);
4833 if (!W_ERROR_IS_OK(result)) {
4840 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4841 result = WERR_INVALID_HANDLE;
4845 result = winreg_get_printer_internal(p->mem_ctx,
4846 get_session_info_system(),
4848 lp_const_servicename(snum),
4850 if (!W_ERROR_IS_OK(result)) {
4854 switch (r->in.level) {
4856 result = construct_printer_info0(p->mem_ctx,
4857 get_session_info_system(),
4860 Printer->servername,
4861 &r->out.info->info0,
4865 result = construct_printer_info1(p->mem_ctx, info2,
4867 Printer->servername,
4868 &r->out.info->info1, snum);
4871 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4872 Printer->servername,
4873 &r->out.info->info2, snum);
4876 result = construct_printer_info3(p->mem_ctx, info2,
4877 Printer->servername,
4878 &r->out.info->info3, snum);
4881 result = construct_printer_info4(p->mem_ctx, info2,
4882 Printer->servername,
4883 &r->out.info->info4, snum);
4886 result = construct_printer_info5(p->mem_ctx, info2,
4887 Printer->servername,
4888 &r->out.info->info5, snum);
4891 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4892 Printer->servername,
4893 &r->out.info->info6, snum);
4896 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4897 Printer->servername,
4898 &r->out.info->info7, snum);
4901 result = construct_printer_info8(p->mem_ctx, info2,
4902 Printer->servername,
4903 &r->out.info->info8, snum);
4906 result = WERR_INVALID_LEVEL;
4911 if (!W_ERROR_IS_OK(result)) {
4912 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4913 r->in.level, win_errstr(result)));
4917 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4918 r->out.info, r->in.level);
4919 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4921 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4924 TALLOC_FREE(r->out.info);
4928 /********************************************************************
4929 ********************************************************************/
4931 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4933 if (in && strlen(in)) { \
4934 out = talloc_strdup(mem_ctx, in); \
4936 out = talloc_strdup(mem_ctx, ""); \
4938 W_ERROR_HAVE_NO_MEMORY(out); \
4941 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4943 if (in && strlen(in)) { \
4944 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4946 out = talloc_strdup(mem_ctx, ""); \
4948 W_ERROR_HAVE_NO_MEMORY(out); \
4951 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4952 const char **string_array,
4953 const char ***presult,
4954 const char *cservername,
4959 size_t num_strings = 0;
4960 const char **array = NULL;
4962 if (string_array == NULL) {
4963 return WERR_INVALID_PARAMETER;
4966 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4967 const char *str = NULL;
4969 if (cservername == NULL || arch == NULL) {
4970 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4972 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4975 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4977 return WERR_NOT_ENOUGH_MEMORY;
4982 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4983 &array, &num_strings);
4986 if (presult != NULL) {
4995 /********************************************************************
4996 * fill a spoolss_DriverInfo1 struct
4997 ********************************************************************/
4999 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5000 struct spoolss_DriverInfo1 *r,
5001 const struct spoolss_DriverInfo8 *driver,
5002 const char *servername)
5004 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5005 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5010 /********************************************************************
5011 * fill a spoolss_DriverInfo2 struct
5012 ********************************************************************/
5014 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5015 struct spoolss_DriverInfo2 *r,
5016 const struct spoolss_DriverInfo8 *driver,
5017 const char *servername)
5020 const char *cservername = canon_servername(servername);
5022 r->version = driver->version;
5024 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5025 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5026 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5027 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5029 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5030 driver->architecture,
5032 driver->driver_path,
5035 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5036 driver->architecture,
5041 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5042 driver->architecture,
5044 driver->config_file,
5050 /********************************************************************
5051 * fill a spoolss_DriverInfo3 struct
5052 ********************************************************************/
5054 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5055 struct spoolss_DriverInfo3 *r,
5056 const struct spoolss_DriverInfo8 *driver,
5057 const char *servername)
5059 const char *cservername = canon_servername(servername);
5061 r->version = driver->version;
5063 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5064 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5065 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5066 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5068 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5069 driver->architecture,
5071 driver->driver_path,
5074 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5075 driver->architecture,
5080 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5081 driver->architecture,
5083 driver->config_file,
5086 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5087 driver->architecture,
5092 FILL_DRIVER_STRING(mem_ctx,
5093 driver->monitor_name,
5096 FILL_DRIVER_STRING(mem_ctx,
5097 driver->default_datatype,
5098 r->default_datatype);
5100 return string_array_from_driver_info(mem_ctx,
5101 driver->dependent_files,
5102 &r->dependent_files,
5104 driver->architecture,
5108 /********************************************************************
5109 * fill a spoolss_DriverInfo4 struct
5110 ********************************************************************/
5112 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5113 struct spoolss_DriverInfo4 *r,
5114 const struct spoolss_DriverInfo8 *driver,
5115 const char *servername)
5117 const char *cservername = canon_servername(servername);
5120 r->version = driver->version;
5122 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5123 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5124 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5125 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5127 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5128 driver->architecture,
5130 driver->driver_path,
5133 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5134 driver->architecture,
5139 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5140 driver->architecture,
5142 driver->config_file,
5145 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5146 driver->architecture,
5151 result = string_array_from_driver_info(mem_ctx,
5152 driver->dependent_files,
5153 &r->dependent_files,
5155 driver->architecture,
5157 if (!W_ERROR_IS_OK(result)) {
5161 FILL_DRIVER_STRING(mem_ctx,
5162 driver->monitor_name,
5165 FILL_DRIVER_STRING(mem_ctx,
5166 driver->default_datatype,
5167 r->default_datatype);
5170 result = string_array_from_driver_info(mem_ctx,
5171 driver->previous_names,
5178 /********************************************************************
5179 * fill a spoolss_DriverInfo5 struct
5180 ********************************************************************/
5182 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5183 struct spoolss_DriverInfo5 *r,
5184 const struct spoolss_DriverInfo8 *driver,
5185 const char *servername)
5187 const char *cservername = canon_servername(servername);
5189 r->version = driver->version;
5191 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5192 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5193 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5194 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5196 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5197 driver->architecture,
5199 driver->driver_path,
5202 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5203 driver->architecture,
5208 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5209 driver->architecture,
5211 driver->config_file,
5214 r->driver_attributes = 0;
5215 r->config_version = 0;
5216 r->driver_version = 0;
5220 /********************************************************************
5221 * fill a spoolss_DriverInfo6 struct
5222 ********************************************************************/
5224 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5225 struct spoolss_DriverInfo6 *r,
5226 const struct spoolss_DriverInfo8 *driver,
5227 const char *servername)
5229 const char *cservername = canon_servername(servername);
5232 r->version = driver->version;
5234 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5235 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5236 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5237 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5239 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5240 driver->architecture,
5242 driver->driver_path,
5245 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5246 driver->architecture,
5251 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5252 driver->architecture,
5254 driver->config_file,
5257 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5258 driver->architecture,
5263 FILL_DRIVER_STRING(mem_ctx,
5264 driver->monitor_name,
5267 FILL_DRIVER_STRING(mem_ctx,
5268 driver->default_datatype,
5269 r->default_datatype);
5271 result = string_array_from_driver_info(mem_ctx,
5272 driver->dependent_files,
5273 &r->dependent_files,
5275 driver->architecture,
5277 if (!W_ERROR_IS_OK(result)) {
5281 result = string_array_from_driver_info(mem_ctx,
5282 driver->previous_names,
5285 if (!W_ERROR_IS_OK(result)) {
5289 r->driver_date = driver->driver_date;
5290 r->driver_version = driver->driver_version;
5292 FILL_DRIVER_STRING(mem_ctx,
5293 driver->manufacturer_name,
5294 r->manufacturer_name);
5295 FILL_DRIVER_STRING(mem_ctx,
5296 driver->manufacturer_url,
5297 r->manufacturer_url);
5298 FILL_DRIVER_STRING(mem_ctx,
5299 driver->hardware_id,
5301 FILL_DRIVER_STRING(mem_ctx,
5308 /********************************************************************
5309 * fill a spoolss_DriverInfo8 struct
5310 ********************************************************************/
5312 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5313 struct spoolss_DriverInfo8 *r,
5314 const struct spoolss_DriverInfo8 *driver,
5315 const char *servername)
5317 const char *cservername = canon_servername(servername);
5320 r->version = driver->version;
5322 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5323 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5324 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5325 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5327 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5328 driver->architecture,
5330 driver->driver_path,
5333 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5334 driver->architecture,
5339 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5340 driver->architecture,
5342 driver->config_file,
5345 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5346 driver->architecture,
5351 FILL_DRIVER_STRING(mem_ctx,
5352 driver->monitor_name,
5355 FILL_DRIVER_STRING(mem_ctx,
5356 driver->default_datatype,
5357 r->default_datatype);
5359 result = string_array_from_driver_info(mem_ctx,
5360 driver->dependent_files,
5361 &r->dependent_files,
5363 driver->architecture,
5365 if (!W_ERROR_IS_OK(result)) {
5369 result = string_array_from_driver_info(mem_ctx,
5370 driver->previous_names,
5373 if (!W_ERROR_IS_OK(result)) {
5377 r->driver_date = driver->driver_date;
5378 r->driver_version = driver->driver_version;
5380 FILL_DRIVER_STRING(mem_ctx,
5381 driver->manufacturer_name,
5382 r->manufacturer_name);
5383 FILL_DRIVER_STRING(mem_ctx,
5384 driver->manufacturer_url,
5385 r->manufacturer_url);
5386 FILL_DRIVER_STRING(mem_ctx,
5387 driver->hardware_id,
5389 FILL_DRIVER_STRING(mem_ctx,
5393 FILL_DRIVER_STRING(mem_ctx,
5394 driver->print_processor,
5395 r->print_processor);
5396 FILL_DRIVER_STRING(mem_ctx,
5397 driver->vendor_setup,
5400 result = string_array_from_driver_info(mem_ctx,
5401 driver->color_profiles,
5404 if (!W_ERROR_IS_OK(result)) {
5408 FILL_DRIVER_STRING(mem_ctx,
5412 r->printer_driver_attributes = driver->printer_driver_attributes;
5414 result = string_array_from_driver_info(mem_ctx,
5415 driver->core_driver_dependencies,
5416 &r->core_driver_dependencies,
5418 if (!W_ERROR_IS_OK(result)) {
5422 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5423 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5428 #if 0 /* disabled until marshalling issues are resolved - gd */
5429 /********************************************************************
5430 ********************************************************************/
5432 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5433 struct spoolss_DriverFileInfo *r,
5434 const char *cservername,
5435 const char *file_name,
5436 enum spoolss_DriverFileType file_type,
5437 uint32_t file_version)
5439 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5440 cservername, file_name);
5441 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5442 r->file_type = file_type;
5443 r->file_version = file_version;
5448 /********************************************************************
5449 ********************************************************************/
5451 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5452 const struct spoolss_DriverInfo8 *driver,
5453 const char *cservername,
5454 struct spoolss_DriverFileInfo **info_p,
5457 struct spoolss_DriverFileInfo *info = NULL;
5465 if (strlen(driver->driver_path)) {
5466 info = talloc_realloc(mem_ctx, info,
5467 struct spoolss_DriverFileInfo,
5469 W_ERROR_HAVE_NO_MEMORY(info);
5470 result = fill_spoolss_DriverFileInfo(info,
5473 driver->driver_path,
5474 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5476 W_ERROR_NOT_OK_RETURN(result);
5480 if (strlen(driver->config_file)) {
5481 info = talloc_realloc(mem_ctx, info,
5482 struct spoolss_DriverFileInfo,
5484 W_ERROR_HAVE_NO_MEMORY(info);
5485 result = fill_spoolss_DriverFileInfo(info,
5488 driver->config_file,
5489 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5491 W_ERROR_NOT_OK_RETURN(result);
5495 if (strlen(driver->data_file)) {
5496 info = talloc_realloc(mem_ctx, info,
5497 struct spoolss_DriverFileInfo,
5499 W_ERROR_HAVE_NO_MEMORY(info);
5500 result = fill_spoolss_DriverFileInfo(info,
5504 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5506 W_ERROR_NOT_OK_RETURN(result);
5510 if (strlen(driver->help_file)) {
5511 info = talloc_realloc(mem_ctx, info,
5512 struct spoolss_DriverFileInfo,
5514 W_ERROR_HAVE_NO_MEMORY(info);
5515 result = fill_spoolss_DriverFileInfo(info,
5519 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5521 W_ERROR_NOT_OK_RETURN(result);
5525 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5526 info = talloc_realloc(mem_ctx, info,
5527 struct spoolss_DriverFileInfo,
5529 W_ERROR_HAVE_NO_MEMORY(info);
5530 result = fill_spoolss_DriverFileInfo(info,
5533 driver->dependent_files[i],
5534 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5536 W_ERROR_NOT_OK_RETURN(result);
5546 /********************************************************************
5547 * fill a spoolss_DriverInfo101 struct
5548 ********************************************************************/
5550 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5551 struct spoolss_DriverInfo101 *r,
5552 const struct spoolss_DriverInfo8 *driver,
5553 const char *servername)
5555 const char *cservername = canon_servername(servername);
5558 r->version = driver->version;
5560 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5561 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5562 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5563 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5565 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5569 if (!W_ERROR_IS_OK(result)) {
5573 FILL_DRIVER_STRING(mem_ctx,
5574 driver->monitor_name,
5577 FILL_DRIVER_STRING(mem_ctx,
5578 driver->default_datatype,
5579 r->default_datatype);
5581 result = string_array_from_driver_info(mem_ctx,
5582 driver->previous_names,
5585 if (!W_ERROR_IS_OK(result)) {
5589 r->driver_date = driver->driver_date;
5590 r->driver_version = driver->driver_version;
5592 FILL_DRIVER_STRING(mem_ctx,
5593 driver->manufacturer_name,
5594 r->manufacturer_name);
5595 FILL_DRIVER_STRING(mem_ctx,
5596 driver->manufacturer_url,
5597 r->manufacturer_url);
5598 FILL_DRIVER_STRING(mem_ctx,
5599 driver->hardware_id,
5601 FILL_DRIVER_STRING(mem_ctx,
5608 /********************************************************************
5609 ********************************************************************/
5611 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5612 const struct auth_session_info *session_info,
5613 struct messaging_context *msg_ctx,
5615 union spoolss_DriverInfo *r,
5617 const char *servername,
5618 const char *architecture,
5621 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5622 struct spoolss_DriverInfo8 *driver;
5624 struct dcerpc_binding_handle *b;
5625 TALLOC_CTX *tmp_ctx = NULL;
5628 return WERR_INVALID_LEVEL;
5631 tmp_ctx = talloc_new(mem_ctx);
5633 return WERR_NOT_ENOUGH_MEMORY;
5636 result = winreg_printer_binding_handle(tmp_ctx,
5640 if (!W_ERROR_IS_OK(result)) {
5644 result = winreg_get_printer(tmp_ctx, b,
5645 lp_const_servicename(snum),
5648 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5649 win_errstr(result)));
5651 if (!W_ERROR_IS_OK(result)) {
5652 result = WERR_INVALID_PRINTER_NAME;
5656 result = winreg_get_driver(tmp_ctx, b,
5658 pinfo2->drivername, version, &driver);
5660 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5661 win_errstr(result)));
5663 if (!W_ERROR_IS_OK(result)) {
5665 * Is this a W2k client ?
5669 result = WERR_UNKNOWN_PRINTER_DRIVER;
5673 /* Yes - try again with a WinNT driver. */
5675 result = winreg_get_driver(tmp_ctx, b,
5679 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5680 win_errstr(result)));
5681 if (!W_ERROR_IS_OK(result)) {
5682 result = WERR_UNKNOWN_PRINTER_DRIVER;
5687 /* these are allocated on mem_ctx and not tmp_ctx because they are
5688 * the 'return value' and need to utlive this call */
5691 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5694 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5697 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5700 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5703 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5706 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5709 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5711 #if 0 /* disabled until marshalling issues are resolved - gd */
5713 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5717 result = WERR_INVALID_LEVEL;
5722 talloc_free(tmp_ctx);
5726 /****************************************************************
5727 _spoolss_GetPrinterDriver2
5728 ****************************************************************/
5730 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5731 struct spoolss_GetPrinterDriver2 *r)
5733 struct printer_handle *printer;
5735 uint32_t version = r->in.client_major_version;
5739 /* that's an [in out] buffer */
5741 if (!r->in.buffer && (r->in.offered != 0)) {
5742 result = WERR_INVALID_PARAMETER;
5746 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5748 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5749 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5750 result = WERR_INVALID_PRINTER_NAME;
5755 *r->out.server_major_version = 0;
5756 *r->out.server_minor_version = 0;
5758 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5759 result = WERR_INVALID_HANDLE;
5763 if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5764 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5765 "downgrading to v3\n"));
5766 version = SPOOLSS_DRIVER_VERSION_200X;
5769 result = construct_printer_driver_info_level(p->mem_ctx,
5770 get_session_info_system(),
5772 r->in.level, r->out.info,
5773 snum, printer->servername,
5776 if (!W_ERROR_IS_OK(result)) {
5780 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5781 r->out.info, r->in.level);
5782 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5784 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5787 TALLOC_FREE(r->out.info);
5792 /****************************************************************
5793 _spoolss_StartPagePrinter
5794 ****************************************************************/
5796 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5797 struct spoolss_StartPagePrinter *r)
5799 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5802 DEBUG(3,("_spoolss_StartPagePrinter: "
5803 "Error in startpageprinter printer handle\n"));
5804 return WERR_INVALID_HANDLE;
5807 Printer->page_started = true;
5811 /****************************************************************
5812 _spoolss_EndPagePrinter
5813 ****************************************************************/
5815 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5816 struct spoolss_EndPagePrinter *r)
5820 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5823 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5824 OUR_HANDLE(r->in.handle)));
5825 return WERR_INVALID_HANDLE;
5828 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5829 return WERR_INVALID_HANDLE;
5831 Printer->page_started = false;
5832 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5837 /****************************************************************
5838 _spoolss_StartDocPrinter
5839 ****************************************************************/
5841 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5842 struct spoolss_StartDocPrinter *r)
5844 struct spoolss_DocumentInfo1 *info_1;
5846 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5852 DEBUG(2,("_spoolss_StartDocPrinter: "
5853 "Invalid handle (%s:%u:%u)\n",
5854 OUR_HANDLE(r->in.handle)));
5855 return WERR_INVALID_HANDLE;
5858 if (Printer->jobid) {
5859 DEBUG(2, ("_spoolss_StartDocPrinter: "
5860 "StartDocPrinter called twice! "
5861 "(existing jobid = %d)\n", Printer->jobid));
5862 return WERR_INVALID_HANDLE;
5865 if (r->in.info_ctr->level != 1) {
5866 return WERR_INVALID_LEVEL;
5869 info_1 = r->in.info_ctr->info.info1;
5872 * a nice thing with NT is it doesn't listen to what you tell it.
5873 * when asked to send _only_ RAW datas, it tries to send datas
5876 * So I add checks like in NT Server ...
5879 if (info_1->datatype) {
5881 * The v4 driver model used in Windows 8 declares print jobs
5882 * intended to bypass the XPS processing layer by setting
5883 * datatype to "XPS_PASS" instead of "RAW".
5885 if ((strcmp(info_1->datatype, "RAW") != 0)
5886 && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5888 return WERR_INVALID_DATATYPE;
5892 /* get the share number of the printer */
5893 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5894 return WERR_INVALID_HANDLE;
5897 rc = get_remote_hostname(p->remote_address,
5901 return WERR_NOT_ENOUGH_MEMORY;
5903 if (strequal(rhost,"UNKNOWN")) {
5904 rhost = tsocket_address_inet_addr_string(p->remote_address,
5906 if (rhost == NULL) {
5907 return WERR_NOT_ENOUGH_MEMORY;
5911 werr = print_job_start(p->session_info,
5915 info_1->document_name,
5916 info_1->output_file,
5920 /* An error occured in print_job_start() so return an appropriate
5923 if (!W_ERROR_IS_OK(werr)) {
5927 Printer->document_started = true;
5928 *r->out.job_id = Printer->jobid;
5933 /****************************************************************
5934 _spoolss_EndDocPrinter
5935 ****************************************************************/
5937 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5938 struct spoolss_EndDocPrinter *r)
5940 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5945 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5946 OUR_HANDLE(r->in.handle)));
5947 return WERR_INVALID_HANDLE;
5950 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5951 return WERR_INVALID_HANDLE;
5954 Printer->document_started = false;
5955 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5956 if (!NT_STATUS_IS_OK(status)) {
5957 DEBUG(2, ("_spoolss_EndDocPrinter: "
5958 "print_job_end failed [%s]\n",
5959 nt_errstr(status)));
5963 return ntstatus_to_werror(status);
5966 /****************************************************************
5967 _spoolss_WritePrinter
5968 ****************************************************************/
5970 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5971 struct spoolss_WritePrinter *r)
5973 ssize_t buffer_written;
5975 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5978 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5979 OUR_HANDLE(r->in.handle)));
5980 *r->out.num_written = r->in._data_size;
5981 return WERR_INVALID_HANDLE;
5984 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5985 return WERR_INVALID_HANDLE;
5987 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5988 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5989 snum, Printer->jobid,
5990 (const char *)r->in.data.data,
5991 (size_t)r->in._data_size);
5992 if (buffer_written == (ssize_t)-1) {
5993 *r->out.num_written = 0;
5994 if (errno == ENOSPC)
5995 return WERR_NO_SPOOL_SPACE;
5997 return WERR_ACCESS_DENIED;
6000 *r->out.num_written = r->in._data_size;
6005 /********************************************************************
6006 * api_spoolss_getprinter
6007 * called from the spoolss dispatcher
6009 ********************************************************************/
6011 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6012 struct pipes_struct *p)
6014 const struct auth_session_info *session_info = p->session_info;
6016 WERROR errcode = WERR_INVALID_FUNCTION;
6017 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6020 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6021 OUR_HANDLE(handle)));
6022 return WERR_INVALID_HANDLE;
6025 if (!get_printer_snum(p, handle, &snum, NULL))
6026 return WERR_INVALID_HANDLE;
6029 case SPOOLSS_PRINTER_CONTROL_PAUSE:
6030 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6032 case SPOOLSS_PRINTER_CONTROL_RESUME:
6033 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6034 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6036 case SPOOLSS_PRINTER_CONTROL_PURGE:
6037 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6040 return WERR_INVALID_LEVEL;
6047 /****************************************************************
6048 _spoolss_AbortPrinter
6049 * From MSDN: "Deletes printer's spool file if printer is configured
6051 ****************************************************************/
6053 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6054 struct spoolss_AbortPrinter *r)
6056 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6058 WERROR errcode = WERR_OK;
6061 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6062 OUR_HANDLE(r->in.handle)));
6063 return WERR_INVALID_HANDLE;
6066 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6067 return WERR_INVALID_HANDLE;
6069 if (!Printer->document_started) {
6070 return WERR_SPL_NO_STARTDOC;
6073 errcode = print_job_delete(p->session_info,
6081 /********************************************************************
6082 * called by spoolss_api_setprinter
6083 * when updating a printer description
6084 ********************************************************************/
6086 static WERROR update_printer_sec(struct policy_handle *handle,
6087 struct pipes_struct *p,
6088 struct sec_desc_buf *secdesc_ctr)
6090 struct spoolss_security_descriptor *new_secdesc = NULL;
6091 struct spoolss_security_descriptor *old_secdesc = NULL;
6092 const char *printer = NULL;
6095 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6096 struct dcerpc_binding_handle *b;
6097 TALLOC_CTX *tmp_ctx = NULL;
6101 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6102 OUR_HANDLE(handle)));
6104 result = WERR_INVALID_HANDLE;
6108 if (secdesc_ctr == NULL) {
6109 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6110 result = WERR_INVALID_PARAMETER;
6114 switch (Printer->printer_type) {
6117 case SPLHND_PRINTER:
6118 if (!get_printer_snum(p, handle, &snum, NULL)) {
6119 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6120 OUR_HANDLE(handle)));
6121 result = WERR_INVALID_HANDLE;
6124 printer = lp_const_servicename(snum);
6130 /* Check the user has permissions to change the security
6131 descriptor. By experimentation with two NT machines, the user
6132 requires Full Access to the printer to change security
6135 switch (Printer->printer_type) {
6137 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6139 case SPLHND_PRINTER:
6140 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6147 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6148 "(access_granted: 0x%08x)\n", Printer->access_granted));
6149 result = WERR_ACCESS_DENIED;
6153 tmp_ctx = talloc_new(p->mem_ctx);
6155 return WERR_NOT_ENOUGH_MEMORY;
6158 result = winreg_printer_binding_handle(tmp_ctx,
6159 get_session_info_system(),
6162 if (!W_ERROR_IS_OK(result)) {
6166 /* NT seems to like setting the security descriptor even though
6167 nothing may have actually changed. */
6169 if (printer != NULL) {
6170 result = winreg_get_printer_secdesc(tmp_ctx, b,
6174 result = winreg_get_printserver_secdesc(tmp_ctx, b,
6177 if (!W_ERROR_IS_OK(result)) {
6178 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6179 result = WERR_INVALID_HANDLE;
6183 if (DEBUGLEVEL >= 10) {
6184 struct security_acl *the_acl;
6187 the_acl = old_secdesc->dacl;
6188 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6189 printer, the_acl->num_aces));
6191 for (i = 0; i < the_acl->num_aces; i++) {
6192 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6193 &the_acl->aces[i].trustee),
6194 the_acl->aces[i].access_mask));
6197 the_acl = secdesc_ctr->sd->dacl;
6200 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6201 printer, the_acl->num_aces));
6203 for (i = 0; i < the_acl->num_aces; i++) {
6204 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6205 &the_acl->aces[i].trustee),
6206 the_acl->aces[i].access_mask));
6209 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6213 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6214 if (new_secdesc == NULL) {
6215 result = WERR_NOT_ENOUGH_MEMORY;
6219 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6224 if (printer != NULL) {
6225 result = winreg_set_printer_secdesc(tmp_ctx, b,
6229 result = winreg_set_printserver_secdesc(tmp_ctx, b,
6234 talloc_free(tmp_ctx);
6238 /********************************************************************
6239 Canonicalize printer info from a client
6240 ********************************************************************/
6242 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6243 struct spoolss_SetPrinterInfo2 *info2,
6246 fstring printername;
6249 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6250 "portname=%s drivername=%s comment=%s location=%s\n",
6251 info2->servername, info2->printername, info2->sharename,
6252 info2->portname, info2->drivername, info2->comment,
6255 /* we force some elements to "correct" values */
6256 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6257 if (info2->servername == NULL) {
6260 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6261 if (info2->sharename == NULL) {
6265 /* check to see if we allow printername != sharename */
6266 if (lp_force_printername(snum)) {
6267 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6268 lp_netbios_name(), info2->sharename);
6270 /* make sure printername is in \\server\printername format */
6271 fstrcpy(printername, info2->printername);
6273 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6274 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6278 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6279 lp_netbios_name(), p);
6281 if (info2->printername == NULL) {
6285 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6286 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6291 /****************************************************************************
6292 ****************************************************************************/
6294 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6296 char *cmd = lp_addport_command(talloc_tos());
6297 char *command = NULL;
6299 bool is_print_op = false;
6302 return WERR_ACCESS_DENIED;
6305 command = talloc_asprintf(ctx,
6306 "%s \"%s\" \"%s\"", cmd, portname, uri );
6308 return WERR_NOT_ENOUGH_MEMORY;
6312 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6314 DEBUG(10,("Running [%s]\n", command));
6316 /********* BEGIN SePrintOperatorPrivilege **********/
6321 ret = smbrun(command, NULL, NULL);
6326 /********* END SePrintOperatorPrivilege **********/
6328 DEBUGADD(10,("returned [%d]\n", ret));
6330 TALLOC_FREE(command);
6333 return WERR_ACCESS_DENIED;
6339 /****************************************************************************
6340 ****************************************************************************/
6342 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6346 * As we do not know if we are embedded in the file server process
6347 * or not, we have to pretend that all shares are in use.
6352 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6353 struct spoolss_SetPrinterInfo2 *info2,
6354 const char *remote_machine,
6355 struct messaging_context *msg_ctx)
6357 char *cmd = lp_addprinter_command(talloc_tos());
6359 char *command = NULL;
6363 bool is_print_op = false;
6365 if (!remote_machine) {
6369 command = talloc_asprintf(ctx,
6370 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6371 cmd, info2->printername, info2->sharename,
6372 info2->portname, info2->drivername,
6373 info2->location, info2->comment, remote_machine);
6379 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6381 DEBUG(10,("Running [%s]\n", command));
6383 /********* BEGIN SePrintOperatorPrivilege **********/
6388 ret = smbrun(command, &fd, NULL);
6390 /* Tell everyone we updated smb.conf. */
6391 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6397 /********* END SePrintOperatorPrivilege **********/
6399 DEBUGADD(10,("returned [%d]\n", ret));
6401 TALLOC_FREE(command);
6409 /* reload our services immediately */
6411 reload_services(NULL, spoolss_conn_snum_used, false);
6415 /* Get lines and convert them back to dos-codepage */
6416 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6417 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6420 /* Set the portname to what the script says the portname should be. */
6421 /* but don't require anything to be return from the script exit a good error code */
6424 /* Set the portname to what the script says the portname should be. */
6425 info2->portname = talloc_strdup(ctx, qlines[0]);
6426 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6429 TALLOC_FREE(qlines);
6433 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6434 const struct auth_session_info *session_info,
6435 struct messaging_context *msg_ctx,
6437 struct spoolss_SetPrinterInfo2 *printer,
6438 struct spoolss_PrinterInfo2 *old_printer)
6440 bool force_update = (old_printer == NULL);
6441 const char *dnsdomname;
6442 const char *longname;
6443 const char *uncname;
6444 const char *spooling;
6446 WERROR result = WERR_OK;
6447 struct dcerpc_binding_handle *b;
6448 TALLOC_CTX *tmp_ctx;
6451 tmp_ctx = talloc_new(mem_ctx);
6453 return WERR_NOT_ENOUGH_MEMORY;
6456 result = winreg_printer_binding_handle(tmp_ctx,
6460 if (!W_ERROR_IS_OK(result)) {
6464 if (printer->drivername != NULL &&
6466 !strequal(printer->drivername, old_printer->drivername))) {
6467 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6469 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6470 result = WERR_INVALID_DATA;
6473 result = winreg_set_printer_dataex(tmp_ctx, b,
6475 SPOOL_DSSPOOLER_KEY,
6476 SPOOL_REG_DRIVERNAME,
6480 if (!W_ERROR_IS_OK(result)) {
6481 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6485 if (!force_update) {
6486 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6487 printer->drivername));
6489 notify_printer_driver(server_event_context(), msg_ctx,
6490 snum, printer->drivername ?
6491 printer->drivername : "");
6495 if (printer->comment != NULL &&
6497 !strequal(printer->comment, old_printer->comment))) {
6498 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6500 DEBUG(0, ("comment data corrupted\n"));
6501 result = WERR_INVALID_DATA;
6504 result = winreg_set_printer_dataex(tmp_ctx, b,
6506 SPOOL_DSSPOOLER_KEY,
6507 SPOOL_REG_DESCRIPTION,
6511 if (!W_ERROR_IS_OK(result)) {
6512 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6516 if (!force_update) {
6517 notify_printer_comment(server_event_context(), msg_ctx,
6518 snum, printer->comment ?
6519 printer->comment : "");
6523 if (printer->sharename != NULL &&
6525 !strequal(printer->sharename, old_printer->sharename))) {
6526 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6528 DEBUG(0, ("sharename data corrupted\n"));
6529 result = WERR_INVALID_DATA;
6532 result = winreg_set_printer_dataex(tmp_ctx, b,
6534 SPOOL_DSSPOOLER_KEY,
6535 SPOOL_REG_PRINTSHARENAME,
6539 if (!W_ERROR_IS_OK(result)) {
6540 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6544 if (!force_update) {
6545 notify_printer_sharename(server_event_context(),
6547 snum, printer->sharename ?
6548 printer->sharename : "");
6551 /* name change, purge any cache entries for the old */
6552 prune_printername_cache();
6555 if (printer->printername != NULL &&
6557 !strequal(printer->printername, old_printer->printername))) {
6560 p = strrchr(printer->printername, '\\' );
6564 p = printer->printername;
6567 ok = push_reg_sz(tmp_ctx, &buffer, p);
6569 DEBUG(0, ("printername data corrupted\n"));
6570 result = WERR_INVALID_DATA;
6573 result = winreg_set_printer_dataex(tmp_ctx, b,
6575 SPOOL_DSSPOOLER_KEY,
6576 SPOOL_REG_PRINTERNAME,
6580 if (!W_ERROR_IS_OK(result)) {
6581 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6585 if (!force_update) {
6586 notify_printer_printername(server_event_context(),
6587 msg_ctx, snum, p ? p : "");
6590 /* name change, purge any cache entries for the old */
6591 prune_printername_cache();
6594 if (printer->portname != NULL &&
6596 !strequal(printer->portname, old_printer->portname))) {
6597 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6599 DEBUG(0, ("portname data corrupted\n"));
6600 result = WERR_INVALID_DATA;
6603 result = winreg_set_printer_dataex(tmp_ctx, b,
6605 SPOOL_DSSPOOLER_KEY,
6610 if (!W_ERROR_IS_OK(result)) {
6611 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6615 if (!force_update) {
6616 notify_printer_port(server_event_context(),
6617 msg_ctx, snum, printer->portname ?
6618 printer->portname : "");
6622 if (printer->location != NULL &&
6624 !strequal(printer->location, old_printer->location))) {
6625 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6627 DEBUG(0, ("location data corrupted\n"));
6628 result = WERR_INVALID_DATA;
6631 result = winreg_set_printer_dataex(tmp_ctx, b,
6633 SPOOL_DSSPOOLER_KEY,
6638 if (!W_ERROR_IS_OK(result)) {
6639 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6643 if (!force_update) {
6644 notify_printer_location(server_event_context(),
6647 printer->location : "");
6651 if (printer->sepfile != NULL &&
6653 !strequal(printer->sepfile, old_printer->sepfile))) {
6654 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6656 DEBUG(0, ("sepfile data corrupted\n"));
6657 result = WERR_INVALID_DATA;
6660 result = winreg_set_printer_dataex(tmp_ctx, b,
6662 SPOOL_DSSPOOLER_KEY,
6663 SPOOL_REG_PRINTSEPARATORFILE,
6667 if (!W_ERROR_IS_OK(result)) {
6668 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6672 if (!force_update) {
6673 notify_printer_sepfile(server_event_context(),
6676 printer->sepfile : "");
6680 if (printer->starttime != 0 &&
6682 printer->starttime != old_printer->starttime)) {
6683 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6684 SIVAL(buffer.data, 0, printer->starttime);
6685 result = winreg_set_printer_dataex(tmp_ctx, b,
6687 SPOOL_DSSPOOLER_KEY,
6688 SPOOL_REG_PRINTSTARTTIME,
6692 if (!W_ERROR_IS_OK(result)) {
6693 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6698 if (printer->untiltime != 0 &&
6700 printer->untiltime != old_printer->untiltime)) {
6701 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6702 SIVAL(buffer.data, 0, printer->untiltime);
6703 result = winreg_set_printer_dataex(tmp_ctx, b,
6705 SPOOL_DSSPOOLER_KEY,
6706 SPOOL_REG_PRINTENDTIME,
6710 if (!W_ERROR_IS_OK(result)) {
6711 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6716 if (force_update || printer->priority != old_printer->priority) {
6717 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6718 SIVAL(buffer.data, 0, printer->priority);
6719 result = winreg_set_printer_dataex(tmp_ctx, b,
6721 SPOOL_DSSPOOLER_KEY,
6726 if (!W_ERROR_IS_OK(result)) {
6727 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6732 if (force_update || printer->attributes != old_printer->attributes) {
6733 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6734 SIVAL(buffer.data, 0, (printer->attributes &
6735 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6736 result = winreg_set_printer_dataex(tmp_ctx, b,
6738 SPOOL_DSSPOOLER_KEY,
6739 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6743 if (!W_ERROR_IS_OK(result)) {
6744 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6748 switch (printer->attributes & 0x3) {
6750 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6753 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6756 spooling = SPOOL_REGVAL_PRINTDIRECT;
6759 spooling = "unknown";
6761 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6763 DEBUG(0, ("printSpooling data corrupted\n"));
6764 result = WERR_INVALID_DATA;
6767 winreg_set_printer_dataex(tmp_ctx, b,
6769 SPOOL_DSSPOOLER_KEY,
6770 SPOOL_REG_PRINTSPOOLING,
6776 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6778 DEBUG(0, ("shortServerName data corrupted\n"));
6779 result = WERR_INVALID_DATA;
6782 result = winreg_set_printer_dataex(tmp_ctx, b,
6784 SPOOL_DSSPOOLER_KEY,
6785 SPOOL_REG_SHORTSERVERNAME,
6789 if (!W_ERROR_IS_OK(result)) {
6790 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6794 dnsdomname = get_mydnsfullname();
6795 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6796 longname = talloc_strdup(tmp_ctx, dnsdomname);
6798 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6800 if (longname == NULL) {
6801 result = WERR_NOT_ENOUGH_MEMORY;
6805 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6807 DEBUG(0, ("longname data corrupted\n"));
6808 result = WERR_INVALID_DATA;
6811 result = winreg_set_printer_dataex(tmp_ctx, b,
6813 SPOOL_DSSPOOLER_KEY,
6814 SPOOL_REG_SERVERNAME,
6818 if (!W_ERROR_IS_OK(result)) {
6819 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6823 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6824 lp_netbios_name(), printer->sharename);
6825 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6827 DEBUG(0, ("uncName data corrupted\n"));
6828 result = WERR_INVALID_DATA;
6831 result = winreg_set_printer_dataex(tmp_ctx, b,
6833 SPOOL_DSSPOOLER_KEY,
6838 if (!W_ERROR_IS_OK(result)) {
6839 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6844 talloc_free(tmp_ctx);
6848 /********************************************************************
6849 * Called by spoolss_api_setprinter
6850 * when updating a printer description.
6851 ********************************************************************/
6853 static WERROR update_printer(struct pipes_struct *p,
6854 struct policy_handle *handle,
6855 struct spoolss_SetPrinterInfoCtr *info_ctr,
6856 struct spoolss_DeviceMode *devmode)
6858 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6859 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6860 struct spoolss_PrinterInfo2 *old_printer;
6861 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6863 WERROR result = WERR_OK;
6864 TALLOC_CTX *tmp_ctx;
6865 struct dcerpc_binding_handle *b;
6867 DEBUG(8,("update_printer\n"));
6869 tmp_ctx = talloc_new(p->mem_ctx);
6870 if (tmp_ctx == NULL) {
6871 return WERR_NOT_ENOUGH_MEMORY;
6875 result = WERR_INVALID_HANDLE;
6879 if (!get_printer_snum(p, handle, &snum, NULL)) {
6880 result = WERR_INVALID_HANDLE;
6884 result = winreg_printer_binding_handle(tmp_ctx,
6885 get_session_info_system(),
6888 if (!W_ERROR_IS_OK(result)) {
6892 result = winreg_get_printer(tmp_ctx, b,
6893 lp_const_servicename(snum),
6895 if (!W_ERROR_IS_OK(result)) {
6896 result = WERR_INVALID_HANDLE;
6900 /* Do sanity check on the requested changes for Samba */
6901 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6902 result = WERR_INVALID_PARAMETER;
6906 /* FIXME!!! If the driver has changed we really should verify that
6907 it is installed before doing much else --jerry */
6909 /* Check calling user has permission to update printer description */
6910 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6911 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6912 result = WERR_ACCESS_DENIED;
6916 /* Call addprinter hook */
6917 /* Check changes to see if this is really needed */
6919 if (*lp_addprinter_command(talloc_tos()) &&
6920 (!strequal(printer->drivername, old_printer->drivername) ||
6921 !strequal(printer->comment, old_printer->comment) ||
6922 !strequal(printer->portname, old_printer->portname) ||
6923 !strequal(printer->location, old_printer->location)) )
6927 raddr = tsocket_address_inet_addr_string(p->remote_address,
6929 if (raddr == NULL) {
6930 return WERR_NOT_ENOUGH_MEMORY;
6933 /* add_printer_hook() will call reload_services() */
6934 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6937 result = WERR_ACCESS_DENIED;
6942 result = update_dsspooler(tmp_ctx,
6943 get_session_info_system(),
6948 if (!W_ERROR_IS_OK(result)) {
6952 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6954 if (devmode == NULL) {
6955 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6957 result = winreg_update_printer(tmp_ctx, b,
6965 talloc_free(tmp_ctx);
6970 /****************************************************************************
6971 ****************************************************************************/
6972 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6973 struct policy_handle *handle,
6974 struct spoolss_SetPrinterInfo7 *info7)
6977 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6980 struct printer_handle *Printer;
6982 if ( lp_security() != SEC_ADS ) {
6983 return WERR_INVALID_LEVEL;
6986 Printer = find_printer_index_by_hnd(p, handle);
6988 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6991 return WERR_INVALID_HANDLE;
6993 if (!get_printer_snum(p, handle, &snum, NULL))
6994 return WERR_INVALID_HANDLE;
6996 result = winreg_get_printer_internal(p->mem_ctx,
6997 get_session_info_system(),
6999 lp_servicename(talloc_tos(), snum),
7001 if (!W_ERROR_IS_OK(result)) {
7002 return WERR_INVALID_HANDLE;
7005 nt_printer_publish(pinfo2,
7006 get_session_info_system(),
7011 TALLOC_FREE(pinfo2);
7014 return WERR_INVALID_LEVEL;
7018 /********************************************************************
7019 ********************************************************************/
7021 static WERROR update_printer_devmode(struct pipes_struct *p,
7022 struct policy_handle *handle,
7023 struct spoolss_DeviceMode *devmode)
7026 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7027 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7029 DEBUG(8,("update_printer_devmode\n"));
7032 return WERR_INVALID_HANDLE;
7035 if (!get_printer_snum(p, handle, &snum, NULL)) {
7036 return WERR_INVALID_HANDLE;
7039 /* Check calling user has permission to update printer description */
7040 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7041 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7042 return WERR_ACCESS_DENIED;
7045 return winreg_update_printer_internal(p->mem_ctx,
7046 get_session_info_system(),
7048 lp_const_servicename(snum),
7056 /****************************************************************
7058 ****************************************************************/
7060 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7061 struct spoolss_SetPrinter *r)
7065 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7068 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7069 OUR_HANDLE(r->in.handle)));
7070 return WERR_INVALID_HANDLE;
7073 /* check the level */
7074 switch (r->in.info_ctr->level) {
7076 return control_printer(r->in.handle, r->in.command, p);
7078 result = update_printer(p, r->in.handle,
7080 r->in.devmode_ctr->devmode);
7081 if (!W_ERROR_IS_OK(result))
7083 if (r->in.secdesc_ctr->sd)
7084 result = update_printer_sec(r->in.handle, p,
7088 return update_printer_sec(r->in.handle, p,
7091 struct spoolss_PrinterInfo2 *old_printer;
7092 struct spoolss_SetPrinterInfo2 *set_old_printer;
7093 struct spoolss_SetPrinterInfoCtr *info_ctr;
7094 struct dcerpc_binding_handle *b;
7096 TALLOC_CTX *tmp_ctx;
7098 tmp_ctx = talloc_new(p->mem_ctx);
7099 if (tmp_ctx == NULL) {
7100 return WERR_NOT_ENOUGH_MEMORY;
7103 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7104 TALLOC_FREE(tmp_ctx);
7105 return WERR_INVALID_HANDLE;
7108 result = winreg_printer_binding_handle(tmp_ctx,
7109 get_session_info_system(),
7112 if (!W_ERROR_IS_OK(result)) {
7113 TALLOC_FREE(tmp_ctx);
7117 result = winreg_get_printer(tmp_ctx, b,
7118 lp_const_servicename(snum),
7120 if (!W_ERROR_IS_OK(result)) {
7121 TALLOC_FREE(tmp_ctx);
7122 return WERR_INVALID_HANDLE;
7125 old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7126 if (old_printer->servername == NULL) {
7127 TALLOC_FREE(tmp_ctx);
7128 return WERR_NOT_ENOUGH_MEMORY;
7131 old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7132 if (old_printer->printername == NULL) {
7133 TALLOC_FREE(tmp_ctx);
7134 return WERR_NOT_ENOUGH_MEMORY;
7137 old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7139 set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7140 if (set_old_printer == NULL) {
7141 TALLOC_FREE(tmp_ctx);
7142 return WERR_NOT_ENOUGH_MEMORY;
7145 spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7147 info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7148 if (info_ctr == NULL) {
7149 TALLOC_FREE(tmp_ctx);
7150 return WERR_NOT_ENOUGH_MEMORY;
7153 info_ctr->level = 2;
7154 info_ctr->info.info2 = set_old_printer;
7156 result = update_printer(p, r->in.handle,
7158 r->in.devmode_ctr->devmode);
7160 if (!W_ERROR_IS_OK(result)) {
7161 TALLOC_FREE(tmp_ctx);
7165 if (r->in.secdesc_ctr->sd) {
7166 result = update_printer_sec(r->in.handle, p,
7170 TALLOC_FREE(tmp_ctx);
7174 return publish_or_unpublish_printer(p, r->in.handle,
7175 r->in.info_ctr->info.info7);
7177 return update_printer_devmode(p, r->in.handle,
7178 r->in.devmode_ctr->devmode);
7180 return WERR_INVALID_LEVEL;
7184 /****************************************************************
7185 _spoolss_FindClosePrinterNotify
7186 ****************************************************************/
7188 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7189 struct spoolss_FindClosePrinterNotify *r)
7191 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7194 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7195 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7196 return WERR_INVALID_HANDLE;
7199 if (Printer->notify.cli_chan != NULL &&
7200 Printer->notify.cli_chan->active_connections > 0) {
7203 if (Printer->printer_type == SPLHND_PRINTER) {
7204 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7205 return WERR_INVALID_HANDLE;
7209 srv_spoolss_replycloseprinter(snum, Printer);
7212 Printer->notify.flags=0;
7213 Printer->notify.options=0;
7214 Printer->notify.localmachine[0]='\0';
7215 Printer->notify.printerlocal=0;
7216 TALLOC_FREE(Printer->notify.option);
7221 /****************************************************************
7223 ****************************************************************/
7225 WERROR _spoolss_AddJob(struct pipes_struct *p,
7226 struct spoolss_AddJob *r)
7228 if (!r->in.buffer && (r->in.offered != 0)) {
7229 return WERR_INVALID_PARAMETER;
7232 /* this is what a NT server returns for AddJob. AddJob must fail on
7233 * non-local printers */
7235 if (r->in.level != 1) {
7236 return WERR_INVALID_LEVEL;
7239 return WERR_INVALID_PARAMETER;
7242 /****************************************************************************
7244 ****************************************************************************/
7246 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7247 struct spoolss_JobInfo1 *r,
7248 const print_queue_struct *queue,
7250 int position, int snum,
7251 struct spoolss_PrinterInfo2 *pinfo2)
7255 t = gmtime(&queue->time);
7259 r->printer_name = lp_servicename(mem_ctx, snum);
7260 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7261 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7262 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7263 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7264 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7265 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7266 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7267 r->data_type = talloc_strdup(mem_ctx, "RAW");
7268 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7269 r->text_status = talloc_strdup(mem_ctx, "");
7270 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7272 r->status = nt_printj_status(queue->status);
7273 r->priority = queue->priority;
7274 r->position = position;
7275 r->total_pages = queue->page_count;
7276 r->pages_printed = 0; /* ??? */
7278 init_systemtime(&r->submitted, t);
7283 /****************************************************************************
7285 ****************************************************************************/
7287 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7288 struct spoolss_JobInfo2 *r,
7289 const print_queue_struct *queue,
7291 int position, int snum,
7292 struct spoolss_PrinterInfo2 *pinfo2,
7293 struct spoolss_DeviceMode *devmode)
7297 t = gmtime(&queue->time);
7301 r->printer_name = lp_servicename(mem_ctx, snum);
7302 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7303 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7304 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7305 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7306 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7307 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7308 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7309 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7310 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7311 r->data_type = talloc_strdup(mem_ctx, "RAW");
7312 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7313 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7314 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7315 r->parameters = talloc_strdup(mem_ctx, "");
7316 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7317 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7318 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7320 r->devmode = devmode;
7322 r->text_status = talloc_strdup(mem_ctx, "");
7323 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7327 r->status = nt_printj_status(queue->status);
7328 r->priority = queue->priority;
7329 r->position = position;
7332 r->total_pages = queue->page_count;
7333 r->size = queue->size;
7334 init_systemtime(&r->submitted, t);
7336 r->pages_printed = 0; /* ??? */
7341 /****************************************************************************
7342 Enumjobs at level 1.
7343 ****************************************************************************/
7345 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7346 const print_queue_struct *queue,
7347 uint32_t num_queues, int snum,
7348 struct spoolss_PrinterInfo2 *pinfo2,
7349 union spoolss_JobInfo **info_p,
7352 union spoolss_JobInfo *info;
7354 WERROR result = WERR_OK;
7355 uint32_t num_filled;
7356 struct tdb_print_db *pdb;
7358 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7360 result = WERR_NOT_ENOUGH_MEMORY;
7364 pdb = get_print_db_byname(pinfo2->sharename);
7366 result = WERR_INVALID_PARAMETER;
7371 for (i = 0; i < num_queues; i++) {
7372 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7373 if (jobid == (uint32_t)-1) {
7374 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7378 result = fill_job_info1(info,
7379 &info[num_filled].info1,
7385 if (!W_ERROR_IS_OK(result)) {
7392 release_print_db(pdb);
7394 *count = num_filled;
7399 release_print_db(pdb);
7407 /****************************************************************************
7408 Enumjobs at level 2.
7409 ****************************************************************************/
7411 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7412 const print_queue_struct *queue,
7413 uint32_t num_queues, int snum,
7414 struct spoolss_PrinterInfo2 *pinfo2,
7415 union spoolss_JobInfo **info_p,
7418 union spoolss_JobInfo *info;
7420 WERROR result = WERR_OK;
7421 uint32_t num_filled;
7422 struct tdb_print_db *pdb;
7424 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7426 result = WERR_NOT_ENOUGH_MEMORY;
7430 pdb = get_print_db_byname(pinfo2->sharename);
7432 result = WERR_INVALID_PARAMETER;
7437 for (i = 0; i< num_queues; i++) {
7438 struct spoolss_DeviceMode *devmode;
7439 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7440 if (jobid == (uint32_t)-1) {
7441 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7445 result = spoolss_create_default_devmode(info,
7446 pinfo2->printername,
7448 if (!W_ERROR_IS_OK(result)) {
7449 DEBUG(3, ("Can't proceed w/o a devmode!"));
7453 result = fill_job_info2(info,
7454 &info[num_filled].info2,
7461 if (!W_ERROR_IS_OK(result)) {
7467 release_print_db(pdb);
7469 *count = num_filled;
7474 release_print_db(pdb);
7482 /****************************************************************************
7483 Enumjobs at level 3.
7484 ****************************************************************************/
7486 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7487 const print_queue_struct *queue,
7488 uint32_t num_queues, int snum,
7489 struct spoolss_PrinterInfo2 *pinfo2,
7490 union spoolss_JobInfo **info_p,
7493 union spoolss_JobInfo *info;
7495 WERROR result = WERR_OK;
7496 uint32_t num_filled;
7497 struct tdb_print_db *pdb;
7499 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7501 result = WERR_NOT_ENOUGH_MEMORY;
7505 pdb = get_print_db_byname(pinfo2->sharename);
7507 result = WERR_INVALID_PARAMETER;
7512 for (i = 0; i < num_queues; i++) {
7513 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7514 if (jobid == (uint32_t)-1) {
7515 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7519 info[num_filled].info3.job_id = jobid;
7520 /* next_job_id is overwritten on next iteration */
7521 info[num_filled].info3.next_job_id = 0;
7522 info[num_filled].info3.reserved = 0;
7524 if (num_filled > 0) {
7525 info[num_filled - 1].info3.next_job_id = jobid;
7530 release_print_db(pdb);
7532 *count = num_filled;
7543 /****************************************************************
7545 ****************************************************************/
7547 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7548 struct spoolss_EnumJobs *r)
7551 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7553 print_status_struct prt_status;
7554 print_queue_struct *queue = NULL;
7557 /* that's an [in out] buffer */
7559 if (!r->in.buffer && (r->in.offered != 0)) {
7560 return WERR_INVALID_PARAMETER;
7563 if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7564 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7565 return WERR_INVALID_LEVEL;
7568 DEBUG(4,("_spoolss_EnumJobs\n"));
7572 *r->out.info = NULL;
7574 /* lookup the printer snum and tdb entry */
7576 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7577 return WERR_INVALID_HANDLE;
7580 result = winreg_get_printer_internal(p->mem_ctx,
7581 get_session_info_system(),
7583 lp_const_servicename(snum),
7585 if (!W_ERROR_IS_OK(result)) {
7589 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7590 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7591 count, prt_status.status, prt_status.message));
7595 TALLOC_FREE(pinfo2);
7599 switch (r->in.level) {
7601 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7602 pinfo2, r->out.info, r->out.count);
7605 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7606 pinfo2, r->out.info, r->out.count);
7609 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7610 pinfo2, r->out.info, r->out.count);
7613 SMB_ASSERT(false); /* level checked on entry */
7618 TALLOC_FREE(pinfo2);
7620 if (!W_ERROR_IS_OK(result)) {
7624 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7626 *r->out.info, r->in.level,
7628 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7629 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7631 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7634 /****************************************************************
7635 _spoolss_ScheduleJob
7636 ****************************************************************/
7638 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7639 struct spoolss_ScheduleJob *r)
7644 /****************************************************************
7645 ****************************************************************/
7647 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7648 struct messaging_context *msg_ctx,
7649 const char *printer_name,
7651 struct spoolss_SetJobInfo1 *r)
7655 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7656 return WERR_INVALID_HANDLE;
7659 if (strequal(old_doc_name, r->document_name)) {
7663 if (!print_job_set_name(server_event_context(), msg_ctx,
7664 printer_name, job_id, r->document_name)) {
7665 return WERR_INVALID_HANDLE;
7671 /****************************************************************
7673 ****************************************************************/
7675 WERROR _spoolss_SetJob(struct pipes_struct *p,
7676 struct spoolss_SetJob *r)
7678 const struct auth_session_info *session_info = p->session_info;
7680 WERROR errcode = WERR_INVALID_FUNCTION;
7682 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7683 return WERR_INVALID_HANDLE;
7686 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7687 return WERR_INVALID_PRINTER_NAME;
7690 switch (r->in.command) {
7691 case SPOOLSS_JOB_CONTROL_CANCEL:
7692 case SPOOLSS_JOB_CONTROL_DELETE:
7693 errcode = print_job_delete(session_info, p->msg_ctx,
7694 snum, r->in.job_id);
7695 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7699 case SPOOLSS_JOB_CONTROL_PAUSE:
7700 errcode = print_job_pause(session_info, p->msg_ctx,
7701 snum, r->in.job_id);
7703 case SPOOLSS_JOB_CONTROL_RESTART:
7704 case SPOOLSS_JOB_CONTROL_RESUME:
7705 errcode = print_job_resume(session_info, p->msg_ctx,
7706 snum, r->in.job_id);
7708 case SPOOLSS_JOB_CONTROL_NOOP:
7712 return WERR_INVALID_LEVEL;
7715 if (!W_ERROR_IS_OK(errcode)) {
7719 if (r->in.ctr == NULL) {
7723 switch (r->in.ctr->level) {
7725 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7726 lp_const_servicename(snum),
7728 r->in.ctr->info.info1);
7734 return WERR_INVALID_LEVEL;
7740 /****************************************************************************
7741 Enumerates all printer drivers by level and architecture.
7742 ****************************************************************************/
7744 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7745 const struct auth_session_info *session_info,
7746 struct messaging_context *msg_ctx,
7747 const char *servername,
7748 const char *architecture,
7750 union spoolss_DriverInfo **info_p,
7755 struct spoolss_DriverInfo8 *driver;
7756 union spoolss_DriverInfo *info = NULL;
7758 WERROR result = WERR_OK;
7759 uint32_t num_drivers;
7760 const char **drivers;
7761 struct dcerpc_binding_handle *b;
7762 TALLOC_CTX *tmp_ctx = NULL;
7767 tmp_ctx = talloc_new(mem_ctx);
7769 return WERR_NOT_ENOUGH_MEMORY;
7772 result = winreg_printer_binding_handle(tmp_ctx,
7776 if (!W_ERROR_IS_OK(result)) {
7780 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7781 result = winreg_get_driver_list(tmp_ctx, b,
7782 architecture, version,
7783 &num_drivers, &drivers);
7784 if (!W_ERROR_IS_OK(result)) {
7787 DEBUG(4, ("we have:[%d] drivers in environment"
7788 " [%s] and version [%d]\n",
7789 num_drivers, architecture, version));
7791 if (num_drivers != 0) {
7792 info = talloc_realloc(tmp_ctx, info,
7793 union spoolss_DriverInfo,
7794 count + num_drivers);
7796 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7797 "failed to enlarge driver info buffer!\n"));
7798 result = WERR_NOT_ENOUGH_MEMORY;
7803 for (i = 0; i < num_drivers; i++) {
7804 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7806 result = winreg_get_driver(tmp_ctx, b,
7807 architecture, drivers[i],
7809 if (!W_ERROR_IS_OK(result)) {
7815 result = fill_printer_driver_info1(info, &info[count+i].info1,
7816 driver, servername);
7819 result = fill_printer_driver_info2(info, &info[count+i].info2,
7820 driver, servername);
7823 result = fill_printer_driver_info3(info, &info[count+i].info3,
7824 driver, servername);
7827 result = fill_printer_driver_info4(info, &info[count+i].info4,
7828 driver, servername);
7831 result = fill_printer_driver_info5(info, &info[count+i].info5,
7832 driver, servername);
7835 result = fill_printer_driver_info6(info, &info[count+i].info6,
7836 driver, servername);
7839 result = fill_printer_driver_info8(info, &info[count+i].info8,
7840 driver, servername);
7843 result = WERR_INVALID_LEVEL;
7847 TALLOC_FREE(driver);
7849 if (!W_ERROR_IS_OK(result)) {
7854 count += num_drivers;
7855 TALLOC_FREE(drivers);
7859 if (W_ERROR_IS_OK(result)) {
7860 *info_p = talloc_move(mem_ctx, &info);
7864 talloc_free(tmp_ctx);
7868 /****************************************************************************
7869 Enumerates all printer drivers by level.
7870 ****************************************************************************/
7872 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7873 const struct auth_session_info *session_info,
7874 struct messaging_context *msg_ctx,
7875 const char *servername,
7876 const char *architecture,
7878 union spoolss_DriverInfo **info_p,
7882 WERROR result = WERR_OK;
7884 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7886 for (a=0; archi_table[a].long_archi != NULL; a++) {
7888 union spoolss_DriverInfo *info = NULL;
7891 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7895 archi_table[a].long_archi,
7899 if (!W_ERROR_IS_OK(result)) {
7903 for (i=0; i < count; i++) {
7904 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7905 info[i], info_p, count_p);
7912 return enumprinterdrivers_level_by_architecture(mem_ctx,
7922 /****************************************************************
7923 _spoolss_EnumPrinterDrivers
7924 ****************************************************************/
7926 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7927 struct spoolss_EnumPrinterDrivers *r)
7929 const char *cservername;
7932 /* that's an [in out] buffer */
7934 if (!r->in.buffer && (r->in.offered != 0)) {
7935 return WERR_INVALID_PARAMETER;
7938 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7942 *r->out.info = NULL;
7944 cservername = canon_servername(r->in.server);
7946 if (!is_myname_or_ipaddr(cservername)) {
7947 return WERR_UNKNOWN_PRINTER_DRIVER;
7950 result = enumprinterdrivers_level(p->mem_ctx,
7951 get_session_info_system(),
7958 if (!W_ERROR_IS_OK(result)) {
7962 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7963 spoolss_EnumPrinterDrivers,
7964 *r->out.info, r->in.level,
7966 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7967 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7969 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7972 /****************************************************************
7974 ****************************************************************/
7976 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7977 struct spoolss_EnumForms *r)
7983 *r->out.info = NULL;
7985 /* that's an [in out] buffer */
7987 if (!r->in.buffer && (r->in.offered != 0) ) {
7988 return WERR_INVALID_PARAMETER;
7991 DEBUG(4,("_spoolss_EnumForms\n"));
7992 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7993 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7995 switch (r->in.level) {
7997 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7998 get_session_info_system(),
8004 result = WERR_INVALID_LEVEL;
8008 if (!W_ERROR_IS_OK(result)) {
8012 if (*r->out.count == 0) {
8013 return WERR_NO_MORE_ITEMS;
8016 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8018 *r->out.info, r->in.level,
8020 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8021 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8023 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8026 /****************************************************************
8028 ****************************************************************/
8030 WERROR _spoolss_GetForm(struct pipes_struct *p,
8031 struct spoolss_GetForm *r)
8035 /* that's an [in out] buffer */
8037 if (!r->in.buffer && (r->in.offered != 0)) {
8038 TALLOC_FREE(r->out.info);
8039 return WERR_INVALID_PARAMETER;
8042 DEBUG(4,("_spoolss_GetForm\n"));
8043 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8044 DEBUGADD(5,("Info level [%d]\n", r->in.level));
8046 switch (r->in.level) {
8048 result = winreg_printer_getform1_internal(p->mem_ctx,
8049 get_session_info_system(),
8052 &r->out.info->info1);
8055 result = WERR_INVALID_LEVEL;
8059 if (!W_ERROR_IS_OK(result)) {
8060 TALLOC_FREE(r->out.info);
8064 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8065 r->out.info, r->in.level);
8066 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8068 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8071 /****************************************************************************
8072 ****************************************************************************/
8074 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8075 struct spoolss_PortInfo1 *r,
8078 r->port_name = talloc_strdup(mem_ctx, name);
8079 W_ERROR_HAVE_NO_MEMORY(r->port_name);
8084 /****************************************************************************
8085 TODO: This probably needs distinguish between TCP/IP and Local ports
8087 ****************************************************************************/
8089 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8090 struct spoolss_PortInfo2 *r,
8093 r->port_name = talloc_strdup(mem_ctx, name);
8094 W_ERROR_HAVE_NO_MEMORY(r->port_name);
8096 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8097 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8099 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8100 W_ERROR_HAVE_NO_MEMORY(r->description);
8102 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8109 /****************************************************************************
8110 wrapper around the enumer ports command
8111 ****************************************************************************/
8113 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8115 char *cmd = lp_enumports_command(talloc_tos());
8116 char **qlines = NULL;
8117 char *command = NULL;
8125 /* if no hook then just fill in the default port */
8128 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8129 return WERR_NOT_ENOUGH_MEMORY;
8131 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8132 TALLOC_FREE(qlines);
8133 return WERR_NOT_ENOUGH_MEMORY;
8139 /* we have a valid enumport command */
8141 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8143 return WERR_NOT_ENOUGH_MEMORY;
8146 DEBUG(10,("Running [%s]\n", command));
8147 ret = smbrun(command, &fd, NULL);
8148 DEBUG(10,("Returned [%d]\n", ret));
8149 TALLOC_FREE(command);
8154 return WERR_ACCESS_DENIED;
8158 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8159 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8169 /****************************************************************************
8171 ****************************************************************************/
8173 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8174 union spoolss_PortInfo **info_p,
8177 union spoolss_PortInfo *info = NULL;
8179 WERROR result = WERR_OK;
8180 char **qlines = NULL;
8183 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8184 if (!W_ERROR_IS_OK(result)) {
8189 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8191 DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8192 result = WERR_NOT_ENOUGH_MEMORY;
8196 for (i=0; i<numlines; i++) {
8197 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8198 result = fill_port_1(info, &info[i].info1, qlines[i]);
8199 if (!W_ERROR_IS_OK(result)) {
8204 TALLOC_FREE(qlines);
8207 if (!W_ERROR_IS_OK(result)) {
8209 TALLOC_FREE(qlines);
8221 /****************************************************************************
8223 ****************************************************************************/
8225 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8226 union spoolss_PortInfo **info_p,
8229 union spoolss_PortInfo *info = NULL;
8231 WERROR result = WERR_OK;
8232 char **qlines = NULL;
8235 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8236 if (!W_ERROR_IS_OK(result)) {
8241 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8243 DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8244 result = WERR_NOT_ENOUGH_MEMORY;
8248 for (i=0; i<numlines; i++) {
8249 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8250 result = fill_port_2(info, &info[i].info2, qlines[i]);
8251 if (!W_ERROR_IS_OK(result)) {
8256 TALLOC_FREE(qlines);
8259 if (!W_ERROR_IS_OK(result)) {
8261 TALLOC_FREE(qlines);
8273 /****************************************************************
8275 ****************************************************************/
8277 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8278 struct spoolss_EnumPorts *r)
8282 /* that's an [in out] buffer */
8284 if (!r->in.buffer && (r->in.offered != 0)) {
8285 return WERR_INVALID_PARAMETER;
8288 DEBUG(4,("_spoolss_EnumPorts\n"));
8292 *r->out.info = NULL;
8294 switch (r->in.level) {
8296 result = enumports_level_1(p->mem_ctx, r->out.info,
8300 result = enumports_level_2(p->mem_ctx, r->out.info,
8304 return WERR_INVALID_LEVEL;
8307 if (!W_ERROR_IS_OK(result)) {
8311 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8313 *r->out.info, r->in.level,
8315 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8316 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8318 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8321 /****************************************************************************
8322 ****************************************************************************/
8324 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8326 struct spoolss_SetPrinterInfoCtr *info_ctr,
8327 struct spoolss_DeviceMode *devmode,
8328 struct security_descriptor *secdesc,
8329 struct spoolss_UserLevelCtr *user_ctr,
8330 struct policy_handle *handle)
8332 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8333 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8335 WERROR err = WERR_OK;
8337 /* samba does not have a concept of local, non-shared printers yet, so
8338 * make sure we always setup sharename - gd */
8339 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8340 (info2->printername != NULL && info2->printername[0] != '\0')) {
8341 DEBUG(5, ("spoolss_addprinterex_level_2: "
8342 "no sharename has been set, setting printername %s as sharename\n",
8343 info2->printername));
8344 info2->sharename = info2->printername;
8347 /* check to see if the printer already exists */
8348 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8349 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8351 return WERR_PRINTER_ALREADY_EXISTS;
8354 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8355 if ((snum = print_queue_snum(info2->printername)) != -1) {
8356 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8357 info2->printername));
8358 return WERR_PRINTER_ALREADY_EXISTS;
8362 /* validate printer info struct */
8363 if (!info2->printername || strlen(info2->printername) == 0) {
8364 return WERR_INVALID_PRINTER_NAME;
8366 if (!info2->portname || strlen(info2->portname) == 0) {
8367 return WERR_UNKNOWN_PORT;
8369 if (!info2->drivername || strlen(info2->drivername) == 0) {
8370 return WERR_UNKNOWN_PRINTER_DRIVER;
8372 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8373 return WERR_UNKNOWN_PRINTPROCESSOR;
8376 /* FIXME!!! smbd should check to see if the driver is installed before
8377 trying to add a printer like this --jerry */
8379 if (*lp_addprinter_command(talloc_tos()) ) {
8382 raddr = tsocket_address_inet_addr_string(p->remote_address,
8384 if (raddr == NULL) {
8385 return WERR_NOT_ENOUGH_MEMORY;
8388 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8391 return WERR_ACCESS_DENIED;
8394 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8395 "smb.conf parameter \"addprinter command\" is defined. This "
8396 "parameter must exist for this call to succeed\n",
8397 info2->sharename ));
8400 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8401 return WERR_ACCESS_DENIED;
8404 /* you must be a printer admin to add a new printer */
8405 if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8408 PRINTER_ACCESS_ADMINISTER))) {
8409 return WERR_ACCESS_DENIED;
8413 * Do sanity check on the requested changes for Samba.
8416 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8417 return WERR_INVALID_PARAMETER;
8420 if (devmode == NULL) {
8421 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8424 err = update_dsspooler(p->mem_ctx,
8425 get_session_info_system(),
8430 if (!W_ERROR_IS_OK(err)) {
8434 err = winreg_update_printer_internal(p->mem_ctx,
8435 get_session_info_system(),
8442 if (!W_ERROR_IS_OK(err)) {
8446 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8447 if (!W_ERROR_IS_OK(err)) {
8448 /* Handle open failed - remove addition. */
8449 ZERO_STRUCTP(handle);
8456 /****************************************************************
8457 _spoolss_AddPrinterEx
8458 ****************************************************************/
8460 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8461 struct spoolss_AddPrinterEx *r)
8463 switch (r->in.info_ctr->level) {
8465 /* we don't handle yet */
8466 /* but I know what to do ... */
8467 return WERR_INVALID_LEVEL;
8469 return spoolss_addprinterex_level_2(p, r->in.server,
8471 r->in.devmode_ctr->devmode,
8472 r->in.secdesc_ctr->sd,
8473 r->in.userlevel_ctr,
8476 return WERR_INVALID_LEVEL;
8480 /****************************************************************
8482 ****************************************************************/
8484 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8485 struct spoolss_AddPrinter *r)
8487 struct spoolss_AddPrinterEx a;
8488 struct spoolss_UserLevelCtr userlevel_ctr;
8490 ZERO_STRUCT(userlevel_ctr);
8492 userlevel_ctr.level = 1;
8494 a.in.server = r->in.server;
8495 a.in.info_ctr = r->in.info_ctr;
8496 a.in.devmode_ctr = r->in.devmode_ctr;
8497 a.in.secdesc_ctr = r->in.secdesc_ctr;
8498 a.in.userlevel_ctr = &userlevel_ctr;
8499 a.out.handle = r->out.handle;
8501 return _spoolss_AddPrinterEx(p, &a);
8504 /****************************************************************
8505 _spoolss_AddPrinterDriverEx
8506 ****************************************************************/
8508 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8509 struct spoolss_AddPrinterDriverEx *r)
8511 WERROR err = WERR_OK;
8512 const char *driver_name = NULL;
8515 * we only support the semantics of AddPrinterDriver()
8516 * i.e. only copy files that are newer than existing ones
8519 if (r->in.flags == 0) {
8520 return WERR_INVALID_PARAMETER;
8523 if (r->in.flags != APD_COPY_NEW_FILES) {
8524 return WERR_ACCESS_DENIED;
8528 if (r->in.info_ctr->level != 3 &&
8529 r->in.info_ctr->level != 6 &&
8530 r->in.info_ctr->level != 8) {
8531 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8532 r->in.info_ctr->level));
8533 return WERR_INVALID_LEVEL;
8536 DEBUG(5,("Cleaning driver's information\n"));
8537 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8538 if (!W_ERROR_IS_OK(err))
8541 DEBUG(5,("Moving driver to final destination\n"));
8542 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8543 if (!W_ERROR_IS_OK(err)) {
8547 err = winreg_add_driver_internal(p->mem_ctx,
8548 get_session_info_system(),
8553 if (!W_ERROR_IS_OK(err)) {
8558 * I think this is where he DrvUpgradePrinter() hook would be
8559 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8560 * server. Right now, we just need to send ourselves a message
8561 * to update each printer bound to this driver. --jerry
8564 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8565 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8566 __func__, driver_name));
8573 /****************************************************************
8574 _spoolss_AddPrinterDriver
8575 ****************************************************************/
8577 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8578 struct spoolss_AddPrinterDriver *r)
8580 struct spoolss_AddPrinterDriverEx a;
8582 switch (r->in.info_ctr->level) {
8589 return WERR_INVALID_LEVEL;
8592 a.in.servername = r->in.servername;
8593 a.in.info_ctr = r->in.info_ctr;
8594 a.in.flags = APD_COPY_NEW_FILES;
8596 return _spoolss_AddPrinterDriverEx(p, &a);
8599 /****************************************************************************
8600 ****************************************************************************/
8602 struct _spoolss_paths {
8608 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8610 static const struct _spoolss_paths spoolss_paths[]= {
8611 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8612 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8615 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8616 const char *servername,
8617 const char *environment,
8621 const char *pservername = NULL;
8622 const char *long_archi;
8623 const char *short_archi;
8627 /* environment may be empty */
8628 if (environment && strlen(environment)) {
8629 long_archi = environment;
8631 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8632 "spoolss", "architecture",
8633 SPOOLSS_ARCHITECTURE_NT_X86);
8636 /* servername may be empty */
8637 if (servername && strlen(servername)) {
8638 pservername = canon_servername(servername);
8640 if (!is_myname_or_ipaddr(pservername)) {
8641 return WERR_INVALID_PARAMETER;
8645 if (!(short_archi = get_short_archi(long_archi))) {
8646 return WERR_INVALID_ENVIRONMENT;
8649 switch (component) {
8650 case SPOOLSS_PRTPROCS_PATH:
8651 case SPOOLSS_DRIVER_PATH:
8653 *path = talloc_asprintf(mem_ctx,
8656 spoolss_paths[component].share,
8659 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8660 SPOOLSS_DEFAULT_SERVER_PATH,
8661 spoolss_paths[component].dir,
8666 return WERR_INVALID_PARAMETER;
8670 return WERR_NOT_ENOUGH_MEMORY;
8676 /****************************************************************************
8677 ****************************************************************************/
8679 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8680 const char *servername,
8681 const char *environment,
8682 struct spoolss_DriverDirectoryInfo1 *r)
8687 werr = compose_spoolss_server_path(mem_ctx,
8690 SPOOLSS_DRIVER_PATH,
8692 if (!W_ERROR_IS_OK(werr)) {
8696 DEBUG(4,("printer driver directory: [%s]\n", path));
8698 r->directory_name = path;
8703 /****************************************************************
8704 _spoolss_GetPrinterDriverDirectory
8705 ****************************************************************/
8707 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8708 struct spoolss_GetPrinterDriverDirectory *r)
8712 /* that's an [in out] buffer */
8714 if (!r->in.buffer && (r->in.offered != 0)) {
8715 TALLOC_FREE(r->out.info);
8716 return WERR_INVALID_PARAMETER;
8719 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8724 /* r->in.level is ignored */
8726 werror = getprinterdriverdir_level_1(p->mem_ctx,
8729 &r->out.info->info1);
8730 if (!W_ERROR_IS_OK(werror)) {
8731 TALLOC_FREE(r->out.info);
8735 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8736 r->out.info, r->in.level);
8737 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8739 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8742 /****************************************************************
8743 _spoolss_EnumPrinterData
8744 ****************************************************************/
8746 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8747 struct spoolss_EnumPrinterData *r)
8750 struct spoolss_EnumPrinterDataEx r2;
8752 struct spoolss_PrinterEnumValues *info, *val = NULL;
8755 r2.in.handle = r->in.handle;
8756 r2.in.key_name = "PrinterDriverData";
8758 r2.out.count = &count;
8759 r2.out.info = &info;
8760 r2.out.needed = &needed;
8762 result = _spoolss_EnumPrinterDataEx(p, &r2);
8763 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8764 r2.in.offered = needed;
8765 result = _spoolss_EnumPrinterDataEx(p, &r2);
8767 if (!W_ERROR_IS_OK(result)) {
8772 * The NT machine wants to know the biggest size of value and data
8774 * cf: MSDN EnumPrinterData remark section
8777 if (!r->in.value_offered && !r->in.data_offered) {
8778 uint32_t biggest_valuesize = 0;
8779 uint32_t biggest_datasize = 0;
8782 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8784 for (i=0; i<count; i++) {
8786 name_length = strlen(info[i].value_name);
8787 if (strlen(info[i].value_name) > biggest_valuesize) {
8788 biggest_valuesize = name_length;
8791 if (info[i].data_length > biggest_datasize) {
8792 biggest_datasize = info[i].data_length;
8795 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8799 /* the value is an UNICODE string but real_value_size is the length
8800 in bytes including the trailing 0 */
8802 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8803 *r->out.data_needed = biggest_datasize;
8805 DEBUG(6,("final values: [%d], [%d]\n",
8806 *r->out.value_needed, *r->out.data_needed));
8811 if (r->in.enum_index < count) {
8812 val = &info[r->in.enum_index];
8816 /* out_value should default to "" or else NT4 has
8817 problems unmarshalling the response */
8819 if (r->in.value_offered) {
8820 *r->out.value_needed = 1;
8821 r->out.value_name = talloc_strdup(r, "");
8822 if (!r->out.value_name) {
8823 return WERR_NOT_ENOUGH_MEMORY;
8826 r->out.value_name = NULL;
8827 *r->out.value_needed = 0;
8830 /* the data is counted in bytes */
8832 *r->out.data_needed = r->in.data_offered;
8834 result = WERR_NO_MORE_ITEMS;
8838 * - counted in bytes in the request
8839 * - counted in UNICODE chars in the max reply
8840 * - counted in bytes in the real size
8842 * take a pause *before* coding not *during* coding
8846 if (r->in.value_offered) {
8847 r->out.value_name = talloc_strdup(r, val->value_name);
8848 if (!r->out.value_name) {
8849 return WERR_NOT_ENOUGH_MEMORY;
8851 *r->out.value_needed = val->value_name_len;
8853 r->out.value_name = NULL;
8854 *r->out.value_needed = 0;
8859 *r->out.type = val->type;
8861 /* data - counted in bytes */
8864 * See the section "Dynamically Typed Query Parameters"
8868 if (r->out.data && val->data && val->data->data &&
8869 val->data_length && r->in.data_offered) {
8870 memcpy(r->out.data, val->data->data,
8871 MIN(val->data_length,r->in.data_offered));
8874 *r->out.data_needed = val->data_length;
8882 /****************************************************************
8883 _spoolss_SetPrinterData
8884 ****************************************************************/
8886 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8887 struct spoolss_SetPrinterData *r)
8889 struct spoolss_SetPrinterDataEx r2;
8891 r2.in.handle = r->in.handle;
8892 r2.in.key_name = "PrinterDriverData";
8893 r2.in.value_name = r->in.value_name;
8894 r2.in.type = r->in.type;
8895 r2.in.data = r->in.data;
8896 r2.in.offered = r->in.offered;
8898 return _spoolss_SetPrinterDataEx(p, &r2);
8901 /****************************************************************
8902 _spoolss_ResetPrinter
8903 ****************************************************************/
8905 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8906 struct spoolss_ResetPrinter *r)
8908 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8911 DEBUG(5,("_spoolss_ResetPrinter\n"));
8914 * All we do is to check to see if the handle and queue is valid.
8915 * This call really doesn't mean anything to us because we only
8916 * support RAW printing. --jerry
8920 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8921 OUR_HANDLE(r->in.handle)));
8922 return WERR_INVALID_HANDLE;
8925 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8926 return WERR_INVALID_HANDLE;
8929 /* blindly return success */
8933 /****************************************************************
8934 _spoolss_DeletePrinterData
8935 ****************************************************************/
8937 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8938 struct spoolss_DeletePrinterData *r)
8940 struct spoolss_DeletePrinterDataEx r2;
8942 r2.in.handle = r->in.handle;
8943 r2.in.key_name = "PrinterDriverData";
8944 r2.in.value_name = r->in.value_name;
8946 return _spoolss_DeletePrinterDataEx(p, &r2);
8949 /****************************************************************
8951 ****************************************************************/
8953 WERROR _spoolss_AddForm(struct pipes_struct *p,
8954 struct spoolss_AddForm *r)
8956 struct spoolss_AddFormInfo1 *form;
8958 WERROR status = WERR_OK;
8959 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8960 struct dcerpc_binding_handle *b;
8961 TALLOC_CTX *tmp_ctx = NULL;
8963 DEBUG(5,("_spoolss_AddForm\n"));
8966 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8967 OUR_HANDLE(r->in.handle)));
8968 return WERR_INVALID_HANDLE;
8971 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8972 and not a printer admin, then fail */
8974 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8975 !security_token_has_privilege(p->session_info->security_token,
8976 SEC_PRIV_PRINT_OPERATOR)) {
8977 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8978 return WERR_ACCESS_DENIED;
8981 if (r->in.info_ctr->level != 1) {
8982 return WERR_INVALID_LEVEL;
8985 form = r->in.info_ctr->info.info1;
8987 return WERR_INVALID_PARAMETER;
8990 switch (form->flags) {
8991 case SPOOLSS_FORM_USER:
8992 case SPOOLSS_FORM_BUILTIN:
8993 case SPOOLSS_FORM_PRINTER:
8996 return WERR_INVALID_PARAMETER;
8999 tmp_ctx = talloc_new(p->mem_ctx);
9001 return WERR_NOT_ENOUGH_MEMORY;
9004 status = winreg_printer_binding_handle(tmp_ctx,
9005 get_session_info_system(),
9008 if (!W_ERROR_IS_OK(status)) {
9012 status = winreg_printer_addform1(tmp_ctx, b, form);
9013 if (!W_ERROR_IS_OK(status)) {
9018 * ChangeID must always be set if this is a printer
9020 if (Printer->printer_type == SPLHND_PRINTER) {
9021 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9022 status = WERR_INVALID_HANDLE;
9026 status = winreg_printer_update_changeid(tmp_ctx, b,
9027 lp_const_servicename(snum));
9031 talloc_free(tmp_ctx);
9035 /****************************************************************
9037 ****************************************************************/
9039 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9040 struct spoolss_DeleteForm *r)
9042 const char *form_name = r->in.form_name;
9043 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9045 WERROR status = WERR_OK;
9046 struct dcerpc_binding_handle *b;
9047 TALLOC_CTX *tmp_ctx = NULL;
9049 DEBUG(5,("_spoolss_DeleteForm\n"));
9052 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9053 OUR_HANDLE(r->in.handle)));
9054 return WERR_INVALID_HANDLE;
9057 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9058 !security_token_has_privilege(p->session_info->security_token,
9059 SEC_PRIV_PRINT_OPERATOR)) {
9060 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9061 return WERR_ACCESS_DENIED;
9064 tmp_ctx = talloc_new(p->mem_ctx);
9066 return WERR_NOT_ENOUGH_MEMORY;
9069 status = winreg_printer_binding_handle(tmp_ctx,
9070 get_session_info_system(),
9073 if (!W_ERROR_IS_OK(status)) {
9077 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9078 if (!W_ERROR_IS_OK(status)) {
9083 * ChangeID must always be set if this is a printer
9085 if (Printer->printer_type == SPLHND_PRINTER) {
9086 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9087 status = WERR_INVALID_HANDLE;
9091 status = winreg_printer_update_changeid(tmp_ctx, b,
9092 lp_const_servicename(snum));
9096 talloc_free(tmp_ctx);
9100 /****************************************************************
9102 ****************************************************************/
9104 WERROR _spoolss_SetForm(struct pipes_struct *p,
9105 struct spoolss_SetForm *r)
9107 struct spoolss_AddFormInfo1 *form;
9108 const char *form_name = r->in.form_name;
9110 WERROR status = WERR_OK;
9111 struct dcerpc_binding_handle *b;
9112 TALLOC_CTX *tmp_ctx = NULL;
9114 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9116 DEBUG(5,("_spoolss_SetForm\n"));
9119 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9120 OUR_HANDLE(r->in.handle)));
9121 return WERR_INVALID_HANDLE;
9124 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9125 and not a printer admin, then fail */
9127 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9128 !security_token_has_privilege(p->session_info->security_token,
9129 SEC_PRIV_PRINT_OPERATOR)) {
9130 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9131 return WERR_ACCESS_DENIED;
9134 if (r->in.info_ctr->level != 1) {
9135 return WERR_INVALID_LEVEL;
9138 form = r->in.info_ctr->info.info1;
9140 return WERR_INVALID_PARAMETER;
9143 tmp_ctx = talloc_new(p->mem_ctx);
9145 return WERR_NOT_ENOUGH_MEMORY;
9148 status = winreg_printer_binding_handle(tmp_ctx,
9149 get_session_info_system(),
9152 if (!W_ERROR_IS_OK(status)) {
9156 status = winreg_printer_setform1(tmp_ctx, b,
9159 if (!W_ERROR_IS_OK(status)) {
9164 * ChangeID must always be set if this is a printer
9166 if (Printer->printer_type == SPLHND_PRINTER) {
9167 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9168 status = WERR_INVALID_HANDLE;
9172 status = winreg_printer_update_changeid(tmp_ctx, b,
9173 lp_const_servicename(snum));
9177 talloc_free(tmp_ctx);
9181 /****************************************************************************
9182 fill_print_processor1
9183 ****************************************************************************/
9185 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9186 struct spoolss_PrintProcessorInfo1 *r,
9187 const char *print_processor_name)
9189 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9190 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9195 /****************************************************************************
9196 enumprintprocessors level 1.
9197 ****************************************************************************/
9199 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9200 union spoolss_PrintProcessorInfo **info_p,
9203 union spoolss_PrintProcessorInfo *info;
9206 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9207 W_ERROR_HAVE_NO_MEMORY(info);
9211 result = fill_print_processor1(info, &info[0].info1, "winprint");
9212 if (!W_ERROR_IS_OK(result)) {
9217 if (!W_ERROR_IS_OK(result)) {
9228 /****************************************************************
9229 _spoolss_EnumPrintProcessors
9230 ****************************************************************/
9232 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9233 struct spoolss_EnumPrintProcessors *r)
9237 /* that's an [in out] buffer */
9239 if (!r->in.buffer && (r->in.offered != 0)) {
9240 return WERR_INVALID_PARAMETER;
9243 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9246 * Enumerate the print processors ...
9248 * Just reply with "winprint", to keep NT happy
9249 * and I can use my nice printer checker.
9254 *r->out.info = NULL;
9256 if (!get_short_archi(r->in.environment)) {
9257 return WERR_INVALID_ENVIRONMENT;
9260 switch (r->in.level) {
9262 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9266 return WERR_INVALID_LEVEL;
9269 if (!W_ERROR_IS_OK(result)) {
9273 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9274 spoolss_EnumPrintProcessors,
9275 *r->out.info, r->in.level,
9277 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9278 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9280 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9283 /****************************************************************************
9284 fill_printprocdatatype1
9285 ****************************************************************************/
9287 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9288 struct spoolss_PrintProcDataTypesInfo1 *r,
9289 const char *name_array)
9291 r->name_array = talloc_strdup(mem_ctx, name_array);
9292 W_ERROR_HAVE_NO_MEMORY(r->name_array);
9297 /****************************************************************************
9298 enumprintprocdatatypes level 1.
9299 ****************************************************************************/
9301 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9302 union spoolss_PrintProcDataTypesInfo **info_p,
9306 union spoolss_PrintProcDataTypesInfo *info;
9308 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9309 W_ERROR_HAVE_NO_MEMORY(info);
9313 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9314 if (!W_ERROR_IS_OK(result)) {
9319 if (!W_ERROR_IS_OK(result)) {
9330 /****************************************************************
9331 _spoolss_EnumPrintProcessorDataTypes
9332 ****************************************************************/
9334 WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9335 struct spoolss_EnumPrintProcessorDataTypes *r)
9339 /* that's an [in out] buffer */
9341 if (!r->in.buffer && (r->in.offered != 0)) {
9342 return WERR_INVALID_PARAMETER;
9345 DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9349 *r->out.info = NULL;
9351 if (r->in.print_processor_name == NULL ||
9352 !strequal(r->in.print_processor_name, "winprint")) {
9353 return WERR_UNKNOWN_PRINTPROCESSOR;
9356 switch (r->in.level) {
9358 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9362 return WERR_INVALID_LEVEL;
9365 if (!W_ERROR_IS_OK(result)) {
9369 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9370 spoolss_EnumPrintProcessorDataTypes,
9371 *r->out.info, r->in.level,
9373 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9374 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9376 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9379 /****************************************************************************
9381 ****************************************************************************/
9383 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9384 struct spoolss_MonitorInfo1 *r,
9385 const char *monitor_name)
9387 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9388 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9393 /****************************************************************************
9395 ****************************************************************************/
9397 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9398 struct spoolss_MonitorInfo2 *r,
9399 const char *monitor_name,
9400 const char *environment,
9401 const char *dll_name)
9403 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9404 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9405 r->environment = talloc_strdup(mem_ctx, environment);
9406 W_ERROR_HAVE_NO_MEMORY(r->environment);
9407 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9408 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9413 /****************************************************************************
9414 enumprintmonitors level 1.
9415 ****************************************************************************/
9417 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9418 union spoolss_MonitorInfo **info_p,
9421 union spoolss_MonitorInfo *info;
9422 WERROR result = WERR_OK;
9424 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9425 W_ERROR_HAVE_NO_MEMORY(info);
9429 result = fill_monitor_1(info, &info[0].info1,
9431 if (!W_ERROR_IS_OK(result)) {
9435 result = fill_monitor_1(info, &info[1].info1,
9437 if (!W_ERROR_IS_OK(result)) {
9442 if (!W_ERROR_IS_OK(result)) {
9453 /****************************************************************************
9454 enumprintmonitors level 2.
9455 ****************************************************************************/
9457 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9458 union spoolss_MonitorInfo **info_p,
9461 union spoolss_MonitorInfo *info;
9462 WERROR result = WERR_OK;
9464 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9465 W_ERROR_HAVE_NO_MEMORY(info);
9469 result = fill_monitor_2(info, &info[0].info2,
9471 "Windows NT X86", /* FIXME */
9473 if (!W_ERROR_IS_OK(result)) {
9477 result = fill_monitor_2(info, &info[1].info2,
9479 "Windows NT X86", /* FIXME */
9481 if (!W_ERROR_IS_OK(result)) {
9486 if (!W_ERROR_IS_OK(result)) {
9497 /****************************************************************
9498 _spoolss_EnumMonitors
9499 ****************************************************************/
9501 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9502 struct spoolss_EnumMonitors *r)
9506 /* that's an [in out] buffer */
9508 if (!r->in.buffer && (r->in.offered != 0)) {
9509 return WERR_INVALID_PARAMETER;
9512 DEBUG(5,("_spoolss_EnumMonitors\n"));
9515 * Enumerate the print monitors ...
9517 * Just reply with "Local Port", to keep NT happy
9518 * and I can use my nice printer checker.
9523 *r->out.info = NULL;
9525 switch (r->in.level) {
9527 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9531 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9535 return WERR_INVALID_LEVEL;
9538 if (!W_ERROR_IS_OK(result)) {
9542 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9543 spoolss_EnumMonitors,
9544 *r->out.info, r->in.level,
9546 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9547 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9549 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9552 /****************************************************************************
9553 ****************************************************************************/
9555 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9556 const print_queue_struct *queue,
9557 int count, int snum,
9558 struct spoolss_PrinterInfo2 *pinfo2,
9561 struct spoolss_JobInfo1 *r)
9566 for (i=0; i<count; i++) {
9567 if (queue[i].sysjob == sysjob) {
9573 if (found == false) {
9574 /* NT treats not found as bad param... yet another bad choice */
9575 return WERR_INVALID_PARAMETER;
9578 return fill_job_info1(mem_ctx,
9587 /****************************************************************************
9588 ****************************************************************************/
9590 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9591 const print_queue_struct *queue,
9592 int count, int snum,
9593 struct spoolss_PrinterInfo2 *pinfo2,
9596 struct spoolss_JobInfo2 *r)
9600 struct spoolss_DeviceMode *devmode;
9603 for (i=0; i<count; i++) {
9604 if (queue[i].sysjob == sysjob) {
9610 if (found == false) {
9611 /* NT treats not found as bad param... yet another bad
9613 return WERR_INVALID_PARAMETER;
9617 * if the print job does not have a DEVMODE associated with it,
9618 * just use the one for the printer. A NULL devicemode is not
9619 * a failure condition
9622 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9624 result = spoolss_create_default_devmode(mem_ctx,
9625 pinfo2->printername,
9627 if (!W_ERROR_IS_OK(result)) {
9628 DEBUG(3, ("Can't proceed w/o a devmode!"));
9633 return fill_job_info2(mem_ctx,
9643 /****************************************************************
9645 ****************************************************************/
9647 WERROR _spoolss_GetJob(struct pipes_struct *p,
9648 struct spoolss_GetJob *r)
9650 WERROR result = WERR_OK;
9651 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9652 const char *svc_name;
9656 struct tdb_print_db *pdb;
9657 print_queue_struct *queue = NULL;
9658 print_status_struct prt_status;
9660 /* that's an [in out] buffer */
9662 if (!r->in.buffer && (r->in.offered != 0)) {
9663 result = WERR_INVALID_PARAMETER;
9664 goto err_jinfo_free;
9667 DEBUG(5,("_spoolss_GetJob\n"));
9671 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9672 result = WERR_INVALID_HANDLE;
9673 goto err_jinfo_free;
9676 svc_name = lp_const_servicename(snum);
9677 if (svc_name == NULL) {
9678 result = WERR_INVALID_PARAMETER;
9679 goto err_jinfo_free;
9682 result = winreg_get_printer_internal(p->mem_ctx,
9683 get_session_info_system(),
9687 if (!W_ERROR_IS_OK(result)) {
9688 goto err_jinfo_free;
9691 pdb = get_print_db_byname(svc_name);
9693 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9694 result = WERR_INVALID_PARAMETER;
9695 goto err_pinfo_free;
9698 sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9699 release_print_db(pdb);
9701 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9702 result = WERR_INVALID_PARAMETER;
9703 goto err_pinfo_free;
9706 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9708 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9709 count, prt_status.status, prt_status.message));
9711 switch (r->in.level) {
9713 result = getjob_level_1(p->mem_ctx,
9714 queue, count, snum, pinfo2,
9715 r->in.job_id, sysjob,
9716 &r->out.info->info1);
9719 result = getjob_level_2(p->mem_ctx,
9720 queue, count, snum, pinfo2,
9721 r->in.job_id, sysjob,
9722 &r->out.info->info2);
9725 result = WERR_INVALID_LEVEL;
9730 TALLOC_FREE(pinfo2);
9732 if (!W_ERROR_IS_OK(result)) {
9733 goto err_jinfo_free;
9736 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9738 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9740 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9743 TALLOC_FREE(pinfo2);
9745 TALLOC_FREE(r->out.info);
9749 /****************************************************************
9750 _spoolss_GetPrinterDataEx
9751 ****************************************************************/
9753 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9754 struct spoolss_GetPrinterDataEx *r)
9757 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9758 const char *printer;
9760 WERROR result = WERR_OK;
9762 enum winreg_Type val_type = REG_NONE;
9763 uint8_t *val_data = NULL;
9764 uint32_t val_size = 0;
9765 struct dcerpc_binding_handle *b;
9766 TALLOC_CTX *tmp_ctx;
9768 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9770 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9771 r->in.key_name, r->in.value_name));
9773 /* in case of problem, return some default values */
9776 *r->out.type = REG_NONE;
9778 tmp_ctx = talloc_new(p->mem_ctx);
9780 return WERR_NOT_ENOUGH_MEMORY;
9784 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9785 OUR_HANDLE(r->in.handle)));
9786 result = WERR_INVALID_HANDLE;
9790 /* Is the handle to a printer or to the server? */
9792 if (Printer->printer_type == SPLHND_SERVER) {
9794 union spoolss_PrinterData data;
9796 result = getprinterdata_printer_server(tmp_ctx,
9800 if (!W_ERROR_IS_OK(result)) {
9804 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9805 *r->out.type, &data);
9806 if (!W_ERROR_IS_OK(result)) {
9810 *r->out.needed = blob.length;
9812 if (r->in.offered >= *r->out.needed) {
9813 memcpy(r->out.data, blob.data, blob.length);
9820 /* check to see if the keyname is valid */
9821 if (!strlen(r->in.key_name)) {
9822 result = WERR_INVALID_PARAMETER;
9826 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9827 result = WERR_INVALID_HANDLE;
9830 printer = lp_const_servicename(snum);
9832 result = winreg_printer_binding_handle(tmp_ctx,
9833 get_session_info_system(),
9836 if (!W_ERROR_IS_OK(result)) {
9840 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9841 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9842 strequal(r->in.value_name, "ChangeId")) {
9843 *r->out.type = REG_DWORD;
9845 if (r->in.offered >= *r->out.needed) {
9846 uint32_t changeid = 0;
9848 result = winreg_printer_get_changeid(tmp_ctx, b,
9851 if (!W_ERROR_IS_OK(result)) {
9855 SIVAL(r->out.data, 0, changeid);
9861 result = winreg_get_printer_dataex(tmp_ctx, b,
9868 if (!W_ERROR_IS_OK(result)) {
9872 *r->out.needed = val_size;
9873 *r->out.type = val_type;
9875 if (r->in.offered >= *r->out.needed) {
9876 memcpy(r->out.data, val_data, val_size);
9880 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9882 if (W_ERROR_IS_OK(result)) {
9883 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9886 talloc_free(tmp_ctx);
9890 /****************************************************************
9891 _spoolss_SetPrinterDataEx
9892 ****************************************************************/
9894 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9895 struct spoolss_SetPrinterDataEx *r)
9897 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9899 WERROR result = WERR_OK;
9900 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9902 struct dcerpc_binding_handle *b;
9903 TALLOC_CTX *tmp_ctx;
9905 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9907 /* From MSDN documentation of SetPrinterDataEx: pass request to
9908 SetPrinterData if key is "PrinterDriverData" */
9911 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9912 OUR_HANDLE(r->in.handle)));
9913 return WERR_INVALID_HANDLE;
9916 if (Printer->printer_type == SPLHND_SERVER) {
9917 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9918 "Not implemented for server handles yet\n"));
9919 return WERR_INVALID_PARAMETER;
9922 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9923 return WERR_INVALID_HANDLE;
9927 * Access check : NT returns "access denied" if you make a
9928 * SetPrinterData call without the necessary privildge.
9929 * we were originally returning OK if nothing changed
9930 * which made Win2k issue **a lot** of SetPrinterData
9931 * when connecting to a printer --jerry
9934 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9935 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9936 "change denied by handle access permissions\n"));
9937 return WERR_ACCESS_DENIED;
9940 tmp_ctx = talloc_new(p->mem_ctx);
9942 return WERR_NOT_ENOUGH_MEMORY;
9945 result = winreg_printer_binding_handle(tmp_ctx,
9946 get_session_info_system(),
9949 if (!W_ERROR_IS_OK(result)) {
9953 result = winreg_get_printer(tmp_ctx, b,
9954 lp_servicename(talloc_tos(), snum),
9956 if (!W_ERROR_IS_OK(result)) {
9960 /* check for OID in valuename */
9962 oid_string = strchr(r->in.value_name, ',');
9968 /* save the registry data */
9970 result = winreg_set_printer_dataex(tmp_ctx, b,
9978 if (W_ERROR_IS_OK(result)) {
9979 /* save the OID if one was specified */
9981 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9982 r->in.key_name, SPOOL_OID_KEY);
9984 result = WERR_NOT_ENOUGH_MEMORY;
9989 * I'm not checking the status here on purpose. Don't know
9990 * if this is right, but I'm returning the status from the
9991 * previous set_printer_dataex() call. I have no idea if
9992 * this is right. --jerry
9994 winreg_set_printer_dataex(tmp_ctx, b,
9999 (uint8_t *) oid_string,
10000 strlen(oid_string) + 1);
10003 result = winreg_printer_update_changeid(tmp_ctx, b,
10004 lp_const_servicename(snum));
10009 talloc_free(tmp_ctx);
10013 /****************************************************************
10014 _spoolss_DeletePrinterDataEx
10015 ****************************************************************/
10017 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10018 struct spoolss_DeletePrinterDataEx *r)
10020 const char *printer;
10022 WERROR status = WERR_OK;
10023 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10025 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10028 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10029 "Invalid handle (%s:%u:%u).\n",
10030 OUR_HANDLE(r->in.handle)));
10031 return WERR_INVALID_HANDLE;
10034 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10035 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10036 "printer properties change denied by handle\n"));
10037 return WERR_ACCESS_DENIED;
10040 if (!r->in.value_name || !r->in.key_name) {
10041 return WERR_NOT_ENOUGH_MEMORY;
10044 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10045 return WERR_INVALID_HANDLE;
10047 printer = lp_const_servicename(snum);
10049 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10050 get_session_info_system(),
10055 if (W_ERROR_IS_OK(status)) {
10056 status = winreg_printer_update_changeid_internal(p->mem_ctx,
10057 get_session_info_system(),
10065 /****************************************************************
10066 _spoolss_EnumPrinterKey
10067 ****************************************************************/
10069 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10070 struct spoolss_EnumPrinterKey *r)
10073 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10075 WERROR result = WERR_FILE_NOT_FOUND;
10076 const char **array = NULL;
10079 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10082 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10083 OUR_HANDLE(r->in.handle)));
10084 return WERR_INVALID_HANDLE;
10087 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10088 return WERR_INVALID_HANDLE;
10091 result = winreg_enum_printer_key_internal(p->mem_ctx,
10092 get_session_info_system(),
10094 lp_const_servicename(snum),
10098 if (!W_ERROR_IS_OK(result)) {
10102 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10103 result = WERR_NOT_ENOUGH_MEMORY;
10107 *r->out._ndr_size = r->in.offered / 2;
10108 *r->out.needed = blob.length;
10110 if (r->in.offered < *r->out.needed) {
10111 result = WERR_MORE_DATA;
10114 r->out.key_buffer->string_array = array;
10118 if (!W_ERROR_IS_OK(result)) {
10119 TALLOC_FREE(array);
10120 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10121 *r->out.needed = 0;
10128 /****************************************************************
10129 _spoolss_DeletePrinterKey
10130 ****************************************************************/
10132 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10133 struct spoolss_DeletePrinterKey *r)
10135 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10138 const char *printer;
10139 struct dcerpc_binding_handle *b;
10140 TALLOC_CTX *tmp_ctx;
10142 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10145 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10146 OUR_HANDLE(r->in.handle)));
10147 return WERR_INVALID_HANDLE;
10150 /* if keyname == NULL, return error */
10151 if ( !r->in.key_name )
10152 return WERR_INVALID_PARAMETER;
10154 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10155 return WERR_INVALID_HANDLE;
10158 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10159 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10160 "printer properties change denied by handle\n"));
10161 return WERR_ACCESS_DENIED;
10164 printer = lp_const_servicename(snum);
10166 tmp_ctx = talloc_new(p->mem_ctx);
10168 return WERR_NOT_ENOUGH_MEMORY;
10171 status = winreg_printer_binding_handle(tmp_ctx,
10172 get_session_info_system(),
10175 if (!W_ERROR_IS_OK(status)) {
10179 /* delete the key and all subkeys */
10180 status = winreg_delete_printer_key(tmp_ctx, b,
10183 if (W_ERROR_IS_OK(status)) {
10184 status = winreg_printer_update_changeid(tmp_ctx, b,
10189 talloc_free(tmp_ctx);
10193 /****************************************************************
10194 _spoolss_EnumPrinterDataEx
10195 ****************************************************************/
10197 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10198 struct spoolss_EnumPrinterDataEx *r)
10200 uint32_t count = 0;
10201 struct spoolss_PrinterEnumValues *info = NULL;
10202 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10206 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10209 *r->out.needed = 0;
10210 *r->out.info = NULL;
10213 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10214 OUR_HANDLE(r->in.handle)));
10215 return WERR_INVALID_HANDLE;
10219 * first check for a keyname of NULL or "". Win2k seems to send
10220 * this a lot and we should send back WERR_INVALID_PARAMETER
10221 * no need to spend time looking up the printer in this case.
10225 if (!strlen(r->in.key_name)) {
10226 result = WERR_INVALID_PARAMETER;
10230 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10231 return WERR_INVALID_HANDLE;
10234 /* now look for a match on the key name */
10235 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10236 get_session_info_system(),
10238 lp_const_servicename(snum),
10242 if (!W_ERROR_IS_OK(result)) {
10246 #if 0 /* FIXME - gd */
10247 /* housekeeping information in the reply */
10249 /* Fix from Martin Zielinski <mz@seh.de> - ensure
10250 * the hand marshalled container size is a multiple
10251 * of 4 bytes for RPC alignment.
10255 needed += 4-(needed % 4);
10258 *r->out.count = count;
10259 *r->out.info = info;
10262 if (!W_ERROR_IS_OK(result)) {
10266 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10267 spoolss_EnumPrinterDataEx,
10270 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10271 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10273 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10276 /****************************************************************************
10277 ****************************************************************************/
10279 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10280 const char *servername,
10281 const char *environment,
10282 struct spoolss_PrintProcessorDirectoryInfo1 *r)
10287 werr = compose_spoolss_server_path(mem_ctx,
10290 SPOOLSS_PRTPROCS_PATH,
10292 if (!W_ERROR_IS_OK(werr)) {
10296 DEBUG(4,("print processor directory: [%s]\n", path));
10298 r->directory_name = path;
10303 /****************************************************************
10304 _spoolss_GetPrintProcessorDirectory
10305 ****************************************************************/
10307 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10308 struct spoolss_GetPrintProcessorDirectory *r)
10311 char *prnproc_share = NULL;
10312 bool prnproc_share_exists = false;
10315 /* that's an [in out] buffer */
10317 if (!r->in.buffer && (r->in.offered != 0)) {
10318 result = WERR_INVALID_PARAMETER;
10319 goto err_info_free;
10322 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10325 *r->out.needed = 0;
10327 /* r->in.level is ignored */
10329 /* We always should reply with a local print processor directory so that
10330 * users are not forced to have a [prnproc$] share on the Samba spoolss
10331 * server, if users decide to do so, lets announce it though - Guenther */
10333 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10334 if (!prnproc_share) {
10335 result = WERR_NOT_ENOUGH_MEMORY;
10336 goto err_info_free;
10339 prnproc_share_exists = true;
10342 result = getprintprocessordirectory_level_1(p->mem_ctx,
10343 prnproc_share_exists ? r->in.server : NULL,
10345 &r->out.info->info1);
10346 if (!W_ERROR_IS_OK(result)) {
10347 goto err_info_free;
10350 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10351 r->out.info, r->in.level);
10352 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10354 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10357 TALLOC_FREE(r->out.info);
10361 /*******************************************************************
10362 ********************************************************************/
10364 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10365 const char *dllname)
10367 enum ndr_err_code ndr_err;
10368 struct spoolss_MonitorUi ui;
10370 ui.dll_name = dllname;
10372 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10373 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10374 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10375 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10377 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10380 /*******************************************************************
10381 Streams the monitor UI DLL name in UNICODE
10382 *******************************************************************/
10384 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10385 struct security_token *token, DATA_BLOB *in,
10386 DATA_BLOB *out, uint32_t *needed)
10388 const char *dllname = "tcpmonui.dll";
10390 *needed = (strlen(dllname)+1) * 2;
10392 if (out->length < *needed) {
10393 return WERR_INSUFFICIENT_BUFFER;
10396 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10397 return WERR_NOT_ENOUGH_MEMORY;
10403 /*******************************************************************
10404 ********************************************************************/
10406 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10407 struct spoolss_PortData1 *port1,
10408 const DATA_BLOB *buf)
10410 enum ndr_err_code ndr_err;
10411 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10412 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10413 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10414 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10416 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10419 /*******************************************************************
10420 ********************************************************************/
10422 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10423 struct spoolss_PortData2 *port2,
10424 const DATA_BLOB *buf)
10426 enum ndr_err_code ndr_err;
10427 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10428 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10429 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10430 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10432 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10435 /*******************************************************************
10436 Create a new TCP/IP port
10437 *******************************************************************/
10439 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10440 struct security_token *token, DATA_BLOB *in,
10441 DATA_BLOB *out, uint32_t *needed)
10443 struct spoolss_PortData1 port1;
10444 struct spoolss_PortData2 port2;
10445 char *device_uri = NULL;
10448 const char *portname;
10449 const char *hostaddress;
10451 uint32_t port_number;
10454 /* peek for spoolss_PortData version */
10456 if (!in || (in->length < (128 + 4))) {
10457 return WERR_GEN_FAILURE;
10460 version = IVAL(in->data, 128);
10464 ZERO_STRUCT(port1);
10466 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10467 return WERR_NOT_ENOUGH_MEMORY;
10470 portname = port1.portname;
10471 hostaddress = port1.hostaddress;
10472 queue = port1.queue;
10473 protocol = port1.protocol;
10474 port_number = port1.port_number;
10478 ZERO_STRUCT(port2);
10480 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10481 return WERR_NOT_ENOUGH_MEMORY;
10484 portname = port2.portname;
10485 hostaddress = port2.hostaddress;
10486 queue = port2.queue;
10487 protocol = port2.protocol;
10488 port_number = port2.port_number;
10492 DEBUG(1,("xcvtcp_addport: "
10493 "unknown version of port_data: %d\n", version));
10494 return WERR_UNKNOWN_PORT;
10497 /* create the device URI and call the add_port_hook() */
10499 switch (protocol) {
10500 case PROTOCOL_RAWTCP_TYPE:
10501 device_uri = talloc_asprintf(mem_ctx,
10502 "socket://%s:%d/", hostaddress,
10506 case PROTOCOL_LPR_TYPE:
10507 device_uri = talloc_asprintf(mem_ctx,
10508 "lpr://%s/%s", hostaddress, queue );
10512 return WERR_UNKNOWN_PORT;
10516 return WERR_NOT_ENOUGH_MEMORY;
10519 return add_port_hook(mem_ctx, token, portname, device_uri);
10522 /*******************************************************************
10523 *******************************************************************/
10525 struct xcv_api_table xcvtcp_cmds[] = {
10526 { "MonitorUI", xcvtcp_monitorui },
10527 { "AddPort", xcvtcp_addport},
10531 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10532 struct security_token *token, const char *command,
10539 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10541 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10542 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10543 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10546 return WERR_INVALID_FUNCTION;
10549 /*******************************************************************
10550 *******************************************************************/
10551 #if 0 /* don't support management using the "Local Port" monitor */
10553 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10554 struct security_token *token, DATA_BLOB *in,
10555 DATA_BLOB *out, uint32_t *needed)
10557 const char *dllname = "localui.dll";
10559 *needed = (strlen(dllname)+1) * 2;
10561 if (out->length < *needed) {
10562 return WERR_INSUFFICIENT_BUFFER;
10565 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10566 return WERR_NOT_ENOUGH_MEMORY;
10572 /*******************************************************************
10573 *******************************************************************/
10575 struct xcv_api_table xcvlocal_cmds[] = {
10576 { "MonitorUI", xcvlocal_monitorui },
10580 struct xcv_api_table xcvlocal_cmds[] = {
10587 /*******************************************************************
10588 *******************************************************************/
10590 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10591 struct security_token *token, const char *command,
10592 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10597 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10599 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10600 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10601 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10603 return WERR_INVALID_FUNCTION;
10606 /****************************************************************
10608 ****************************************************************/
10610 WERROR _spoolss_XcvData(struct pipes_struct *p,
10611 struct spoolss_XcvData *r)
10613 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10614 DATA_BLOB out_data = data_blob_null;
10618 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10619 OUR_HANDLE(r->in.handle)));
10620 return WERR_INVALID_HANDLE;
10623 /* Has to be a handle to the TCP/IP port monitor */
10625 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10626 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10627 return WERR_INVALID_HANDLE;
10630 /* requires administrative access to the server */
10632 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10633 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10634 return WERR_ACCESS_DENIED;
10637 /* Allocate the outgoing buffer */
10639 if (r->in.out_data_size) {
10640 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10641 if (out_data.data == NULL) {
10642 return WERR_NOT_ENOUGH_MEMORY;
10646 switch ( Printer->printer_type ) {
10647 case SPLHND_PORTMON_TCP:
10648 werror = process_xcvtcp_command(p->mem_ctx,
10649 p->session_info->security_token,
10650 r->in.function_name,
10651 &r->in.in_data, &out_data,
10654 case SPLHND_PORTMON_LOCAL:
10655 werror = process_xcvlocal_command(p->mem_ctx,
10656 p->session_info->security_token,
10657 r->in.function_name,
10658 &r->in.in_data, &out_data,
10662 werror = WERR_INVALID_PRINT_MONITOR;
10665 if (!W_ERROR_IS_OK(werror)) {
10669 *r->out.status_code = 0;
10671 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10672 memcpy(r->out.out_data, out_data.data,
10673 MIN(r->in.out_data_size, out_data.length));
10679 /****************************************************************
10680 _spoolss_AddPrintProcessor
10681 ****************************************************************/
10683 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10684 struct spoolss_AddPrintProcessor *r)
10686 /* for now, just indicate success and ignore the add. We'll
10687 automatically set the winprint processor for printer
10688 entries later. Used to debug the LexMark Optra S 1855 PCL
10694 /****************************************************************
10696 ****************************************************************/
10698 WERROR _spoolss_AddPort(struct pipes_struct *p,
10699 struct spoolss_AddPort *r)
10701 /* do what w2k3 does */
10703 return WERR_NOT_SUPPORTED;
10706 /****************************************************************
10707 _spoolss_GetPrinterDriver
10708 ****************************************************************/
10710 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10711 struct spoolss_GetPrinterDriver *r)
10713 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10714 return WERR_NOT_SUPPORTED;
10717 /****************************************************************
10718 _spoolss_ReadPrinter
10719 ****************************************************************/
10721 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10722 struct spoolss_ReadPrinter *r)
10724 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10725 return WERR_NOT_SUPPORTED;
10728 /****************************************************************
10729 _spoolss_WaitForPrinterChange
10730 ****************************************************************/
10732 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10733 struct spoolss_WaitForPrinterChange *r)
10735 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10736 return WERR_NOT_SUPPORTED;
10739 /****************************************************************
10740 _spoolss_ConfigurePort
10741 ****************************************************************/
10743 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10744 struct spoolss_ConfigurePort *r)
10746 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10747 return WERR_NOT_SUPPORTED;
10750 /****************************************************************
10751 _spoolss_DeletePort
10752 ****************************************************************/
10754 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10755 struct spoolss_DeletePort *r)
10757 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10758 return WERR_NOT_SUPPORTED;
10761 /****************************************************************
10762 _spoolss_CreatePrinterIC
10763 ****************************************************************/
10765 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10766 struct spoolss_CreatePrinterIC *r)
10768 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10769 return WERR_NOT_SUPPORTED;
10772 /****************************************************************
10773 _spoolss_PlayGDIScriptOnPrinterIC
10774 ****************************************************************/
10776 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10777 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10779 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10780 return WERR_NOT_SUPPORTED;
10783 /****************************************************************
10784 _spoolss_DeletePrinterIC
10785 ****************************************************************/
10787 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10788 struct spoolss_DeletePrinterIC *r)
10790 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10791 return WERR_NOT_SUPPORTED;
10794 /****************************************************************
10795 _spoolss_AddPrinterConnection
10796 ****************************************************************/
10798 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10799 struct spoolss_AddPrinterConnection *r)
10801 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10802 return WERR_NOT_SUPPORTED;
10805 /****************************************************************
10806 _spoolss_DeletePrinterConnection
10807 ****************************************************************/
10809 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10810 struct spoolss_DeletePrinterConnection *r)
10812 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10813 return WERR_NOT_SUPPORTED;
10816 /****************************************************************
10817 _spoolss_PrinterMessageBox
10818 ****************************************************************/
10820 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10821 struct spoolss_PrinterMessageBox *r)
10823 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10824 return WERR_NOT_SUPPORTED;
10827 /****************************************************************
10828 _spoolss_AddMonitor
10829 ****************************************************************/
10831 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10832 struct spoolss_AddMonitor *r)
10834 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10835 return WERR_NOT_SUPPORTED;
10838 /****************************************************************
10839 _spoolss_DeleteMonitor
10840 ****************************************************************/
10842 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10843 struct spoolss_DeleteMonitor *r)
10845 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10846 return WERR_NOT_SUPPORTED;
10849 /****************************************************************
10850 _spoolss_DeletePrintProcessor
10851 ****************************************************************/
10853 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10854 struct spoolss_DeletePrintProcessor *r)
10856 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10857 return WERR_NOT_SUPPORTED;
10860 /****************************************************************
10861 _spoolss_AddPrintProvidor
10862 ****************************************************************/
10864 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10865 struct spoolss_AddPrintProvidor *r)
10867 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10868 return WERR_NOT_SUPPORTED;
10871 /****************************************************************
10872 _spoolss_DeletePrintProvidor
10873 ****************************************************************/
10875 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10876 struct spoolss_DeletePrintProvidor *r)
10878 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10879 return WERR_NOT_SUPPORTED;
10882 /****************************************************************
10883 _spoolss_FindFirstPrinterChangeNotification
10884 ****************************************************************/
10886 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10887 struct spoolss_FindFirstPrinterChangeNotification *r)
10889 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10890 return WERR_NOT_SUPPORTED;
10893 /****************************************************************
10894 _spoolss_FindNextPrinterChangeNotification
10895 ****************************************************************/
10897 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10898 struct spoolss_FindNextPrinterChangeNotification *r)
10900 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10901 return WERR_NOT_SUPPORTED;
10904 /****************************************************************
10905 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10906 ****************************************************************/
10908 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10909 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10911 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10912 return WERR_NOT_SUPPORTED;
10915 /****************************************************************
10916 _spoolss_ReplyOpenPrinter
10917 ****************************************************************/
10919 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10920 struct spoolss_ReplyOpenPrinter *r)
10922 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10923 return WERR_NOT_SUPPORTED;
10926 /****************************************************************
10927 _spoolss_RouterReplyPrinter
10928 ****************************************************************/
10930 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10931 struct spoolss_RouterReplyPrinter *r)
10933 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10934 return WERR_NOT_SUPPORTED;
10937 /****************************************************************
10938 _spoolss_ReplyClosePrinter
10939 ****************************************************************/
10941 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10942 struct spoolss_ReplyClosePrinter *r)
10944 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10945 return WERR_NOT_SUPPORTED;
10948 /****************************************************************
10950 ****************************************************************/
10952 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10953 struct spoolss_AddPortEx *r)
10955 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10956 return WERR_NOT_SUPPORTED;
10959 /****************************************************************
10960 _spoolss_RouterFindFirstPrinterChangeNotification
10961 ****************************************************************/
10963 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10964 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10966 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10967 return WERR_NOT_SUPPORTED;
10970 /****************************************************************
10971 _spoolss_SpoolerInit
10972 ****************************************************************/
10974 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10975 struct spoolss_SpoolerInit *r)
10977 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10978 return WERR_NOT_SUPPORTED;
10981 /****************************************************************
10982 _spoolss_ResetPrinterEx
10983 ****************************************************************/
10985 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10986 struct spoolss_ResetPrinterEx *r)
10988 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10989 return WERR_NOT_SUPPORTED;
10992 /****************************************************************
10993 _spoolss_RouterReplyPrinterEx
10994 ****************************************************************/
10996 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10997 struct spoolss_RouterReplyPrinterEx *r)
10999 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11000 return WERR_NOT_SUPPORTED;
11003 /****************************************************************
11005 ****************************************************************/
11007 WERROR _spoolss_44(struct pipes_struct *p,
11008 struct spoolss_44 *r)
11010 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11011 return WERR_NOT_SUPPORTED;
11014 /****************************************************************
11016 ****************************************************************/
11018 WERROR _spoolss_SetPort(struct pipes_struct *p,
11019 struct spoolss_SetPort *r)
11021 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11022 return WERR_NOT_SUPPORTED;
11025 /****************************************************************
11027 ****************************************************************/
11029 WERROR _spoolss_4a(struct pipes_struct *p,
11030 struct spoolss_4a *r)
11032 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11033 return WERR_NOT_SUPPORTED;
11036 /****************************************************************
11038 ****************************************************************/
11040 WERROR _spoolss_4b(struct pipes_struct *p,
11041 struct spoolss_4b *r)
11043 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11044 return WERR_NOT_SUPPORTED;
11047 /****************************************************************
11049 ****************************************************************/
11051 WERROR _spoolss_4c(struct pipes_struct *p,
11052 struct spoolss_4c *r)
11054 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11055 return WERR_NOT_SUPPORTED;
11058 /****************************************************************
11060 ****************************************************************/
11062 WERROR _spoolss_53(struct pipes_struct *p,
11063 struct spoolss_53 *r)
11065 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11066 return WERR_NOT_SUPPORTED;
11069 /****************************************************************
11070 _spoolss_AddPerMachineConnection
11071 ****************************************************************/
11073 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11074 struct spoolss_AddPerMachineConnection *r)
11076 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11077 return WERR_NOT_SUPPORTED;
11080 /****************************************************************
11081 _spoolss_DeletePerMachineConnection
11082 ****************************************************************/
11084 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11085 struct spoolss_DeletePerMachineConnection *r)
11087 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11088 return WERR_NOT_SUPPORTED;
11091 /****************************************************************
11092 _spoolss_EnumPerMachineConnections
11093 ****************************************************************/
11095 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11096 struct spoolss_EnumPerMachineConnections *r)
11098 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11099 return WERR_NOT_SUPPORTED;
11102 /****************************************************************
11104 ****************************************************************/
11106 WERROR _spoolss_5a(struct pipes_struct *p,
11107 struct spoolss_5a *r)
11109 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11110 return WERR_NOT_SUPPORTED;
11113 /****************************************************************
11115 ****************************************************************/
11117 WERROR _spoolss_5b(struct pipes_struct *p,
11118 struct spoolss_5b *r)
11120 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11121 return WERR_NOT_SUPPORTED;
11124 /****************************************************************
11126 ****************************************************************/
11128 WERROR _spoolss_5c(struct pipes_struct *p,
11129 struct spoolss_5c *r)
11131 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11132 return WERR_NOT_SUPPORTED;
11135 /****************************************************************
11137 ****************************************************************/
11139 WERROR _spoolss_5d(struct pipes_struct *p,
11140 struct spoolss_5d *r)
11142 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11143 return WERR_NOT_SUPPORTED;
11146 /****************************************************************
11148 ****************************************************************/
11150 WERROR _spoolss_5e(struct pipes_struct *p,
11151 struct spoolss_5e *r)
11153 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11154 return WERR_NOT_SUPPORTED;
11157 /****************************************************************
11159 ****************************************************************/
11161 WERROR _spoolss_5f(struct pipes_struct *p,
11162 struct spoolss_5f *r)
11164 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11165 return WERR_NOT_SUPPORTED;
11168 /****************************************************************
11170 ****************************************************************/
11172 WERROR _spoolss_60(struct pipes_struct *p,
11173 struct spoolss_60 *r)
11175 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11176 return WERR_NOT_SUPPORTED;
11179 /****************************************************************
11180 _spoolss_SendRecvBidiData
11181 ****************************************************************/
11183 WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11184 struct spoolss_SendRecvBidiData *r)
11186 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11187 return WERR_NOT_SUPPORTED;
11190 /****************************************************************
11192 ****************************************************************/
11194 WERROR _spoolss_62(struct pipes_struct *p,
11195 struct spoolss_62 *r)
11197 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11198 return WERR_NOT_SUPPORTED;
11201 /****************************************************************
11203 ****************************************************************/
11205 WERROR _spoolss_63(struct pipes_struct *p,
11206 struct spoolss_63 *r)
11208 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11209 return WERR_NOT_SUPPORTED;
11212 /****************************************************************
11214 ****************************************************************/
11216 WERROR _spoolss_64(struct pipes_struct *p,
11217 struct spoolss_64 *r)
11219 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11220 return WERR_NOT_SUPPORTED;
11223 /****************************************************************
11225 ****************************************************************/
11227 WERROR _spoolss_65(struct pipes_struct *p,
11228 struct spoolss_65 *r)
11230 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11231 return WERR_NOT_SUPPORTED;
11234 /****************************************************************
11235 _spoolss_GetCorePrinterDrivers
11236 ****************************************************************/
11238 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11239 struct spoolss_GetCorePrinterDrivers *r)
11241 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11242 return HRES_ERROR_NOT_SUPPORTED;
11245 /****************************************************************
11247 ****************************************************************/
11249 WERROR _spoolss_67(struct pipes_struct *p,
11250 struct spoolss_67 *r)
11252 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11253 return WERR_NOT_SUPPORTED;
11256 /****************************************************************
11257 _spoolss_GetPrinterDriverPackagePath
11258 ****************************************************************/
11260 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11261 struct spoolss_GetPrinterDriverPackagePath *r)
11263 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11264 return HRES_ERROR_NOT_SUPPORTED;
11267 /****************************************************************
11269 ****************************************************************/
11271 WERROR _spoolss_69(struct pipes_struct *p,
11272 struct spoolss_69 *r)
11274 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11275 return WERR_NOT_SUPPORTED;
11278 /****************************************************************
11280 ****************************************************************/
11282 WERROR _spoolss_6a(struct pipes_struct *p,
11283 struct spoolss_6a *r)
11285 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11286 return WERR_NOT_SUPPORTED;
11289 /****************************************************************
11291 ****************************************************************/
11293 WERROR _spoolss_6b(struct pipes_struct *p,
11294 struct spoolss_6b *r)
11296 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11297 return WERR_NOT_SUPPORTED;
11300 /****************************************************************
11302 ****************************************************************/
11304 WERROR _spoolss_6c(struct pipes_struct *p,
11305 struct spoolss_6c *r)
11307 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11308 return WERR_NOT_SUPPORTED;
11311 /****************************************************************
11313 ****************************************************************/
11315 WERROR _spoolss_6d(struct pipes_struct *p,
11316 struct spoolss_6d *r)
11318 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11319 return WERR_NOT_SUPPORTED;
11322 /****************************************************************
11323 _spoolss_GetJobNamedPropertyValue
11324 ****************************************************************/
11326 WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11327 struct spoolss_GetJobNamedPropertyValue *r)
11329 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11330 return WERR_NOT_SUPPORTED;
11333 /****************************************************************
11334 _spoolss_SetJobNamedProperty
11335 ****************************************************************/
11337 WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11338 struct spoolss_SetJobNamedProperty *r)
11340 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11341 return WERR_NOT_SUPPORTED;
11344 /****************************************************************
11345 _spoolss_DeleteJobNamedProperty
11346 ****************************************************************/
11348 WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11349 struct spoolss_DeleteJobNamedProperty *r)
11351 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11352 return WERR_NOT_SUPPORTED;
11355 /****************************************************************
11356 _spoolss_EnumJobNamedProperties
11357 ****************************************************************/
11359 WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11360 struct spoolss_EnumJobNamedProperties *r)
11362 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11363 return WERR_NOT_SUPPORTED;
11366 /****************************************************************
11368 ****************************************************************/
11370 WERROR _spoolss_72(struct pipes_struct *p,
11371 struct spoolss_72 *r)
11373 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11374 return WERR_NOT_SUPPORTED;
11377 /****************************************************************
11379 ****************************************************************/
11381 WERROR _spoolss_73(struct pipes_struct *p,
11382 struct spoolss_73 *r)
11384 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11385 return WERR_NOT_SUPPORTED;
11388 /****************************************************************
11389 _spoolss_RpcLogJobInfoForBranchOffice
11390 ****************************************************************/
11392 WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11393 struct spoolss_LogJobInfoForBranchOffice *r)
11395 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11396 return WERR_NOT_SUPPORTED;