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"
59 #include "rpc_server/spoolss/srv_spoolss_handle.h"
61 /* macros stolen from s4 spoolss server */
62 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
63 ((info)?ndr_size_##fn(info, level, 0):0)
65 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
66 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
68 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
69 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
71 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
74 #define DBGC_CLASS DBGC_RPC_SRV
76 #ifndef MAX_OPEN_PRINTER_EXS
77 #define MAX_OPEN_PRINTER_EXS 50
80 #define GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT 5
81 #define GLOBAL_SPOOLSS_OS_MINOR_DEFAULT 2
82 #define GLOBAL_SPOOLSS_OS_BUILD_DEFAULT 3790
83 #define GLOBAL_SPOOLSS_ARCHITECTURE SPOOLSS_ARCHITECTURE_x64
85 static struct printer_handle *printers_list;
87 struct printer_session_counter {
88 struct printer_session_counter *next;
89 struct printer_session_counter *prev;
95 static struct printer_session_counter *counter_list;
97 struct notify_back_channel {
98 struct notify_back_channel *prev, *next;
100 /* associated client */
101 struct sockaddr_storage client_address;
103 /* print notify back-channel pipe handle*/
104 struct rpc_pipe_client *cli_pipe;
105 struct cli_state *cli;
106 uint32_t active_connections;
109 static struct notify_back_channel *back_channels;
111 /* Map generic permissions to printer object specific permissions */
113 const struct standard_mapping printer_std_mapping = {
120 /* Map generic permissions to print server object specific permissions */
122 const struct standard_mapping printserver_std_mapping = {
129 /* API table for Xcv Monitor functions */
131 struct xcv_api_table {
133 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
136 static void prune_printername_cache(void);
138 /********************************************************************
139 * Canonicalize servername.
140 ********************************************************************/
142 static const char *canon_servername(const char *servername)
144 const char *pservername = servername;
145 while (*pservername == '\\') {
151 /* translate between internal status numbers and NT status numbers */
152 static int nt_printj_status(int v)
158 return JOB_STATUS_PAUSED;
160 return JOB_STATUS_SPOOLING;
162 return JOB_STATUS_PRINTING;
164 return JOB_STATUS_ERROR;
166 return JOB_STATUS_DELETING;
168 return JOB_STATUS_OFFLINE;
170 return JOB_STATUS_PAPEROUT;
172 return JOB_STATUS_PRINTED;
174 return JOB_STATUS_DELETED;
176 return JOB_STATUS_BLOCKED_DEVQ;
177 case LPQ_USER_INTERVENTION:
178 return JOB_STATUS_USER_INTERVENTION;
183 static int nt_printq_status(int v)
187 return PRINTER_STATUS_PAUSED;
196 /***************************************************************************
197 Disconnect from the client
198 ****************************************************************************/
200 static void srv_spoolss_replycloseprinter(int snum,
201 struct printer_handle *prn_hnd)
207 * Tell the specific printing tdb we no longer want messages for this printer
208 * by deregistering our PID.
211 if (!print_notify_deregister_pid(snum)) {
212 DEBUG(0, ("Failed to register our pid for printer %s\n",
213 lp_const_servicename(snum)));
216 /* weird if the test succeeds !!! */
217 if (prn_hnd->notify.cli_chan == NULL ||
218 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
219 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
220 prn_hnd->notify.cli_chan->active_connections == 0) {
221 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
222 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
223 TALLOC_FREE(prn_hnd->notify.cli_chan);
227 status = dcerpc_spoolss_ReplyClosePrinter(
228 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
230 &prn_hnd->notify.cli_hnd,
232 if (!NT_STATUS_IS_OK(status)) {
233 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
235 result = ntstatus_to_werror(status);
236 } else if (!W_ERROR_IS_OK(result)) {
237 DEBUG(0, ("reply_close_printer failed [%s].\n",
238 win_errstr(result)));
241 /* if it's the last connection, deconnect the IPC$ share */
242 if (prn_hnd->notify.cli_chan->active_connections == 1) {
244 cli_shutdown(prn_hnd->notify.cli_chan->cli);
245 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
246 TALLOC_FREE(prn_hnd->notify.cli_chan);
248 if (prn_hnd->notify.msg_ctx != NULL) {
249 messaging_deregister(prn_hnd->notify.msg_ctx,
250 MSG_PRINTER_NOTIFY2, NULL);
254 if (prn_hnd->notify.cli_chan) {
255 prn_hnd->notify.cli_chan->active_connections--;
256 prn_hnd->notify.cli_chan = NULL;
260 /****************************************************************************
261 Functions to free a printer entry datastruct.
262 ****************************************************************************/
264 static int printer_entry_destructor(struct printer_handle *Printer)
266 if (Printer->notify.cli_chan != NULL &&
267 Printer->notify.cli_chan->active_connections > 0) {
270 switch(Printer->printer_type) {
272 srv_spoolss_replycloseprinter(snum, Printer);
276 snum = print_queue_snum(Printer->sharename);
278 srv_spoolss_replycloseprinter(snum, Printer);
286 Printer->notify.flags=0;
287 Printer->notify.options=0;
288 Printer->notify.localmachine[0]='\0';
289 Printer->notify.printerlocal=0;
290 TALLOC_FREE(Printer->notify.option);
291 TALLOC_FREE(Printer->devmode);
293 /* Remove from the internal list. */
294 DLIST_REMOVE(printers_list, Printer);
298 /****************************************************************************
299 find printer index by handle
300 ****************************************************************************/
302 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
303 struct policy_handle *hnd)
305 struct printer_handle *find_printer = NULL;
307 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
308 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
315 /****************************************************************************
316 Close printer index by handle.
317 ****************************************************************************/
319 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
321 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
324 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
329 close_policy_hnd(p, hnd);
334 /****************************************************************************
335 Delete a printer given a handle.
336 ****************************************************************************/
338 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
339 const char *sharename,
340 struct messaging_context *msg_ctx)
342 char *cmd = lp_deleteprinter_command(talloc_tos());
343 char *command = NULL;
345 bool is_print_op = false;
347 /* can't fail if we don't try */
352 command = talloc_asprintf(ctx,
356 return WERR_NOT_ENOUGH_MEMORY;
359 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
361 DEBUG(10,("Running [%s]\n", command));
363 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
368 ret = smbrun(command, NULL, NULL);
370 /* Tell everyone we updated smb.conf. */
371 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
377 /********** END SePrintOperatorPrivlege BLOCK **********/
379 DEBUGADD(10,("returned [%d]\n", ret));
381 TALLOC_FREE(command);
384 return WERR_INVALID_HANDLE; /* What to return here? */
389 /****************************************************************************
390 Delete a printer given a handle.
391 ****************************************************************************/
393 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
395 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
399 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
401 return WERR_INVALID_HANDLE;
405 * It turns out that Windows allows delete printer on a handle
406 * opened by an admin user, then used on a pipe handle created
407 * by an anonymous user..... but they're working on security.... riiight !
411 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
412 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
413 return WERR_ACCESS_DENIED;
416 /* this does not need a become root since the access check has been
417 done on the handle already */
419 result = winreg_delete_printer_key_internal(p->mem_ctx,
420 get_session_info_system(),
424 if (!W_ERROR_IS_OK(result)) {
425 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
426 return WERR_INVALID_HANDLE;
429 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
430 Printer->sharename, p->msg_ctx);
431 if (!W_ERROR_IS_OK(result)) {
434 prune_printername_cache();
438 /****************************************************************************
439 Return the snum of a printer corresponding to an handle.
440 ****************************************************************************/
442 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
443 int *number, struct share_params **params)
445 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
448 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
453 switch (Printer->printer_type) {
455 DEBUG(4,("short name:%s\n", Printer->sharename));
456 *number = print_queue_snum(Printer->sharename);
457 return (*number != -1);
465 /****************************************************************************
466 Set printer handle type.
467 Check if it's \\server or \\server\printer
468 ****************************************************************************/
470 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
472 DEBUG(3,("Setting printer type=%s\n", handlename));
474 /* it's a print server */
475 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
476 DEBUGADD(4,("Printer is a print server\n"));
477 Printer->printer_type = SPLHND_SERVER;
479 /* it's a printer (set_printer_hnd_name() will handle port monitors */
481 DEBUGADD(4,("Printer is a printer\n"));
482 Printer->printer_type = SPLHND_PRINTER;
488 static void prune_printername_cache_fn(const char *key, const char *value,
489 time_t timeout, void *private_data)
494 static void prune_printername_cache(void)
496 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
499 /****************************************************************************
500 Set printer handle name.. Accept names like \\server, \\server\printer,
501 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
502 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
503 XcvDataPort() interface.
504 ****************************************************************************/
506 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
507 const struct auth_session_info *session_info,
508 struct messaging_context *msg_ctx,
509 struct printer_handle *Printer,
510 const char *handlename)
513 int n_services=lp_numservices();
515 const char *printername;
516 const char *servername = NULL;
519 struct spoolss_PrinterInfo2 *info2 = NULL;
524 * Hopefully nobody names his printers like this. Maybe \ or ,
525 * are illegal in printer names even?
527 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
531 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
532 (unsigned long)strlen(handlename)));
534 aprinter = discard_const_p(char, handlename);
535 if ( *handlename == '\\' ) {
536 servername = canon_servername(handlename);
537 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
541 if (!is_myname_or_ipaddr(servername)) {
542 return WERR_INVALID_PRINTER_NAME;
544 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
545 if (Printer->servername == NULL) {
546 return WERR_NOT_ENOUGH_MEMORY;
550 if (Printer->printer_type == SPLHND_SERVER) {
554 if (Printer->printer_type != SPLHND_PRINTER) {
555 return WERR_INVALID_HANDLE;
558 DEBUGADD(5, ("searching for [%s]\n", aprinter));
560 p = strchr(aprinter, ',');
567 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
569 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
575 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
578 /* check for the Port Monitor Interface */
579 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
580 Printer->printer_type = SPLHND_PORTMON_TCP;
581 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
584 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
585 Printer->printer_type = SPLHND_PORTMON_LOCAL;
586 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
590 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s", aprinter);
591 if (cache_key == NULL) {
592 return WERR_NOT_ENOUGH_MEMORY;
596 * With hundreds of printers, the "for" loop iterating all
597 * shares can be quite expensive, as it is done on every
598 * OpenPrinter. The loop maps "aprinter" to "sname", the
599 * result of which we cache in gencache.
601 if (gencache_get(cache_key, talloc_tos(), &tmp, NULL)) {
602 found = (strcmp(tmp, printer_not_found) != 0);
604 DEBUG(4, ("Printer %s not found\n", aprinter));
606 return WERR_INVALID_PRINTER_NAME;
612 /* Search all sharenames first as this is easier than pulling
613 the printer_info_2 off of disk. Don't use find_service() since
614 that calls out to map_username() */
616 /* do another loop to look for printernames */
617 for (snum = 0; !found && snum < n_services; snum++) {
618 const char *printer = lp_const_servicename(snum);
620 /* no point going on if this is not a printer */
621 if (!(lp_snum_ok(snum) && lp_printable(snum))) {
625 /* ignore [printers] share */
626 if (strequal(printer, "printers")) {
630 fstrcpy(sname, printer);
631 if (strequal(aprinter, printer)) {
636 /* no point looking up the printer object if
637 we aren't allowing printername != sharename */
638 if (lp_force_printername(snum)) {
642 result = winreg_get_printer_internal(mem_ctx,
647 if ( !W_ERROR_IS_OK(result) ) {
648 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
649 sname, win_errstr(result)));
653 printername = strrchr(info2->printername, '\\');
654 if (printername == NULL) {
655 printername = info2->printername;
660 if (strequal(printername, aprinter)) {
665 DEBUGADD(10, ("printername: %s\n", printername));
671 gencache_set(cache_key, printer_not_found,
673 TALLOC_FREE(cache_key);
674 DEBUGADD(4,("Printer not found\n"));
675 return WERR_INVALID_PRINTER_NAME;
678 gencache_set(cache_key, sname, time(NULL) + 300);
679 TALLOC_FREE(cache_key);
681 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
683 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
688 /****************************************************************************
689 Find first available printer slot. creates a printer handle for you.
690 ****************************************************************************/
692 static WERROR open_printer_hnd(struct pipes_struct *p,
693 struct policy_handle *hnd,
695 uint32_t access_granted)
697 struct printer_handle *new_printer;
700 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
702 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
703 if (new_printer == NULL) {
704 return WERR_NOT_ENOUGH_MEMORY;
706 talloc_set_destructor(new_printer, printer_entry_destructor);
708 /* This also steals the printer_handle on the policy_handle */
709 if (!create_policy_hnd(p, hnd, new_printer)) {
710 TALLOC_FREE(new_printer);
711 return WERR_INVALID_HANDLE;
714 /* Add to the internal list. */
715 DLIST_ADD(printers_list, new_printer);
717 new_printer->notify.option=NULL;
719 if (!set_printer_hnd_printertype(new_printer, name)) {
720 close_printer_handle(p, hnd);
721 return WERR_INVALID_HANDLE;
724 result = set_printer_hnd_name(p->mem_ctx,
725 get_session_info_system(),
728 if (!W_ERROR_IS_OK(result)) {
729 close_printer_handle(p, hnd);
733 new_printer->access_granted = access_granted;
735 DEBUG(5, ("%d printer handles active\n",
736 (int)num_pipe_handles(p)));
741 /***************************************************************************
742 check to see if the client motify handle is monitoring the notification
743 given by (notify_type, notify_field).
744 **************************************************************************/
746 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
747 uint16_t notify_field)
752 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
753 uint16_t notify_field)
755 struct spoolss_NotifyOption *option = p->notify.option;
759 * Flags should always be zero when the change notify
760 * is registered by the client's spooler. A user Win32 app
761 * might use the flags though instead of the NOTIFY_OPTION_INFO
770 return is_monitoring_event_flags(
771 p->notify.flags, notify_type, notify_field);
773 for (i = 0; i < option->count; i++) {
775 /* Check match for notify_type */
777 if (option->types[i].type != notify_type)
780 /* Check match for field */
782 for (j = 0; j < option->types[i].count; j++) {
783 if (option->types[i].fields[j].field == notify_field) {
789 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
790 p->servername, p->sharename, notify_type, notify_field));
795 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
796 _data->data.integer[0] = _integer; \
797 _data->data.integer[1] = 0;
800 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
801 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
802 if (!_data->data.string.string) {\
803 _data->data.string.size = 0; \
805 _data->data.string.size = strlen_m_term(_p) * 2;
807 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
808 _data->data.devmode.devmode = _devmode;
810 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
815 struct spoolss_Time st;
819 if (!init_systemtime(&st, t)) {
823 p = talloc_array(mem_ctx, char, len);
829 * Systemtime must be linearized as a set of UINT16's.
830 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
833 SSVAL(p, 0, st.year);
834 SSVAL(p, 2, st.month);
835 SSVAL(p, 4, st.day_of_week);
837 SSVAL(p, 8, st.hour);
838 SSVAL(p, 10, st.minute);
839 SSVAL(p, 12, st.second);
840 SSVAL(p, 14, st.millisecond);
846 /* Convert a notification message to a struct spoolss_Notify */
848 static void notify_one_value(struct spoolss_notify_msg *msg,
849 struct spoolss_Notify *data,
852 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
855 static void notify_string(struct spoolss_notify_msg *msg,
856 struct spoolss_Notify *data,
859 /* The length of the message includes the trailing \0 */
861 data->data.string.size = msg->len * 2;
862 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
863 if (!data->data.string.string) {
864 data->data.string.size = 0;
869 static void notify_system_time(struct spoolss_notify_msg *msg,
870 struct spoolss_Notify *data,
873 data->data.string.string = NULL;
874 data->data.string.size = 0;
876 if (msg->len != sizeof(time_t)) {
877 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
882 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
883 &data->data.string.string,
884 &data->data.string.size);
887 struct notify2_message_table {
889 void (*fn)(struct spoolss_notify_msg *msg,
890 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
893 static struct notify2_message_table printer_notify_table[] = {
894 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
895 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
896 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
897 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
898 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
899 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
900 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
901 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
902 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
903 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
904 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
905 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
906 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
907 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
908 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
909 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
910 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
911 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
912 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
915 static struct notify2_message_table job_notify_table[] = {
916 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
917 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
918 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
919 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
920 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
921 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
922 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
923 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
924 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
925 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
926 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
927 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
928 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
929 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
930 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
931 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
932 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
933 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
934 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
935 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
936 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
937 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
938 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
939 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
943 /***********************************************************************
944 Allocate talloc context for container object
945 **********************************************************************/
947 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
952 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
957 /***********************************************************************
958 release all allocated memory and zero out structure
959 **********************************************************************/
961 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
967 talloc_destroy(ctr->ctx);
974 /***********************************************************************
975 **********************************************************************/
977 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
985 /***********************************************************************
986 **********************************************************************/
988 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
990 if ( !ctr || !ctr->msg_groups )
993 if ( idx >= ctr->num_groups )
996 return &ctr->msg_groups[idx];
1000 /***********************************************************************
1001 How many groups of change messages do we have ?
1002 **********************************************************************/
1004 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1009 return ctr->num_groups;
1012 /***********************************************************************
1013 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1014 **********************************************************************/
1016 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1018 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1019 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1020 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1026 /* loop over all groups looking for a matching printer name */
1028 for ( i=0; i<ctr->num_groups; i++ ) {
1029 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1033 /* add a new group? */
1035 if ( i == ctr->num_groups ) {
1038 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1039 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1042 ctr->msg_groups = groups;
1044 /* clear the new entry and set the printer name */
1046 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1047 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1050 /* add the change messages; 'i' is the correct index now regardless */
1052 msg_grp = &ctr->msg_groups[i];
1054 msg_grp->num_msgs++;
1056 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1057 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1060 msg_grp->msgs = msg_list;
1062 new_slot = msg_grp->num_msgs-1;
1063 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1065 /* need to allocate own copy of data */
1067 if ( msg->len != 0 )
1068 msg_grp->msgs[new_slot].notify.data = (char *)
1069 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1071 return ctr->num_groups;
1074 static void construct_info_data(struct spoolss_Notify *info_data,
1075 enum spoolss_NotifyType type,
1076 uint16_t field, int id);
1078 /***********************************************************************
1079 Send a change notication message on all handles which have a call
1081 **********************************************************************/
1083 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1084 struct printer_handle *prn_hnd,
1085 SPOOLSS_NOTIFY_MSG *messages,
1087 struct spoolss_Notify **_notifies,
1090 struct spoolss_Notify *notifies;
1091 SPOOLSS_NOTIFY_MSG *msg;
1096 notifies = talloc_zero_array(mem_ctx,
1097 struct spoolss_Notify, num_msgs);
1102 for (i = 0; i < num_msgs; i++) {
1106 /* Are we monitoring this event? */
1108 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1112 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1113 "for printer [%s]\n",
1114 msg->type, msg->field, prn_hnd->sharename));
1117 * if the is a printer notification handle and not a job
1118 * notification type, then set the id to 0.
1119 * Otherwise just use what was specified in the message.
1121 * When registering change notification on a print server
1122 * handle we always need to send back the id (snum) matching
1123 * the printer for which the change took place.
1124 * For change notify registered on a printer handle,
1125 * this does not matter and the id should be 0.
1130 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1131 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1137 /* Convert unix jobid to smb jobid */
1139 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1140 id = sysjob_to_jobid(msg->id);
1143 DEBUG(3, ("no such unix jobid %d\n",
1149 construct_info_data(¬ifies[count],
1150 msg->type, msg->field, id);
1153 case PRINTER_NOTIFY_TYPE:
1154 if (printer_notify_table[msg->field].fn) {
1155 printer_notify_table[msg->field].fn(msg,
1156 ¬ifies[count], mem_ctx);
1160 case JOB_NOTIFY_TYPE:
1161 if (job_notify_table[msg->field].fn) {
1162 job_notify_table[msg->field].fn(msg,
1163 ¬ifies[count], mem_ctx);
1168 DEBUG(5, ("Unknown notification type %d\n",
1176 *_notifies = notifies;
1182 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1183 struct printer_handle *prn_hnd,
1184 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1186 struct spoolss_Notify *notifies;
1188 union spoolss_ReplyPrinterInfo info;
1189 struct spoolss_NotifyInfo info0;
1190 uint32_t reply_result;
1195 /* Is there notification on this handle? */
1196 if (prn_hnd->notify.cli_chan == NULL ||
1197 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1198 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1199 prn_hnd->notify.cli_chan->active_connections == 0) {
1203 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1204 prn_hnd->servername, prn_hnd->sharename));
1206 /* For this printer? Print servers always receive notifications. */
1207 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1208 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1212 DEBUG(10,("Our printer\n"));
1214 /* build the array of change notifications */
1215 ret = build_notify2_messages(mem_ctx, prn_hnd,
1217 msg_group->num_msgs,
1223 info0.version = 0x2;
1224 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1225 info0.count = count;
1226 info0.notifies = notifies;
1228 info.info0 = &info0;
1230 status = dcerpc_spoolss_RouterReplyPrinterEx(
1231 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1233 &prn_hnd->notify.cli_hnd,
1234 prn_hnd->notify.change, /* color */
1235 prn_hnd->notify.flags,
1237 0, /* reply_type, must be 0 */
1239 if (!NT_STATUS_IS_OK(status)) {
1240 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1242 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1243 nt_errstr(status)));
1244 werr = ntstatus_to_werror(status);
1245 } else if (!W_ERROR_IS_OK(werr)) {
1246 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1248 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1251 switch (reply_result) {
1254 case PRINTER_NOTIFY_INFO_DISCARDED:
1255 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1256 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1265 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1267 struct printer_handle *p;
1268 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1269 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1273 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1277 if (!msg_group->msgs) {
1278 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1282 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1284 /* loop over all printers */
1286 for (p = printers_list; p; p = p->next) {
1287 ret = send_notify2_printer(mem_ctx, p, msg_group);
1294 DEBUG(8,("send_notify2_changes: Exit...\n"));
1298 /***********************************************************************
1299 **********************************************************************/
1301 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1304 uint32_t tv_sec, tv_usec;
1307 /* Unpack message */
1309 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1312 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1314 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1317 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1318 &msg->notify.value[0], &msg->notify.value[1]);
1320 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1321 &msg->len, &msg->notify.data);
1323 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1324 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1326 tv->tv_sec = tv_sec;
1327 tv->tv_usec = tv_usec;
1330 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1331 msg->notify.value[1]));
1333 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1338 /********************************************************************
1339 Receive a notify2 message list
1340 ********************************************************************/
1342 static void receive_notify2_message_list(struct messaging_context *msg,
1345 struct server_id server_id,
1348 size_t msg_count, i;
1349 char *buf = (char *)data->data;
1352 SPOOLSS_NOTIFY_MSG notify;
1353 SPOOLSS_NOTIFY_MSG_CTR messages;
1356 if (data->length < 4) {
1357 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1361 msg_count = IVAL(buf, 0);
1364 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1366 if (msg_count == 0) {
1367 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1371 /* initialize the container */
1373 ZERO_STRUCT( messages );
1374 notify_msg_ctr_init( &messages );
1377 * build message groups for each printer identified
1378 * in a change_notify msg. Remember that a PCN message
1379 * includes the handle returned for the srv_spoolss_replyopenprinter()
1380 * call. Therefore messages are grouped according to printer handle.
1383 for ( i=0; i<msg_count; i++ ) {
1384 struct timeval msg_tv;
1386 if (msg_ptr + 4 - buf > data->length) {
1387 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1391 msg_len = IVAL(msg_ptr,0);
1394 if (msg_ptr + msg_len - buf > data->length) {
1395 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1399 /* unpack messages */
1401 ZERO_STRUCT( notify );
1402 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1405 /* add to correct list in container */
1407 notify_msg_ctr_addmsg( &messages, ¬ify );
1409 /* free memory that might have been allocated by notify2_unpack_msg() */
1411 if ( notify.len != 0 )
1412 SAFE_FREE( notify.notify.data );
1415 /* process each group of messages */
1417 num_groups = notify_msg_ctr_numgroups( &messages );
1418 for ( i=0; i<num_groups; i++ )
1419 send_notify2_changes( &messages, i );
1424 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1425 (uint32_t)msg_count ));
1427 notify_msg_ctr_destroy( &messages );
1432 /********************************************************************
1433 Send a message to ourself about new driver being installed
1434 so we can upgrade the information for each printer bound to this
1436 ********************************************************************/
1438 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1439 struct messaging_context *msg_ctx)
1441 int len = strlen(drivername);
1446 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1449 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1450 MSG_PRINTER_DRVUPGRADE,
1451 (const uint8_t *)drivername, len+1);
1456 void srv_spoolss_cleanup(void)
1458 struct printer_session_counter *session_counter;
1460 for (session_counter = counter_list;
1461 session_counter != NULL;
1462 session_counter = counter_list) {
1463 DLIST_REMOVE(counter_list, session_counter);
1464 TALLOC_FREE(session_counter);
1468 /**********************************************************************
1469 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1470 over all printers, upgrading ones as necessary
1471 This is now *ONLY* called inside the background lpq updater. JRA.
1472 **********************************************************************/
1474 void do_drv_upgrade_printer(struct messaging_context *msg,
1477 struct server_id server_id,
1480 TALLOC_CTX *tmp_ctx;
1481 const struct auth_session_info *session_info = get_session_info_system();
1482 struct spoolss_PrinterInfo2 *pinfo2;
1484 const char *drivername;
1486 int n_services = lp_numservices();
1487 struct dcerpc_binding_handle *b = NULL;
1489 tmp_ctx = talloc_new(NULL);
1490 if (!tmp_ctx) return;
1492 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1494 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1498 DEBUG(10, ("do_drv_upgrade_printer: "
1499 "Got message for new driver [%s]\n", drivername));
1501 /* Iterate the printer list */
1503 for (snum = 0; snum < n_services; snum++) {
1504 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
1508 /* ignore [printers] share */
1509 if (strequal(lp_const_servicename(snum), "printers")) {
1514 result = winreg_printer_binding_handle(tmp_ctx,
1518 if (!W_ERROR_IS_OK(result)) {
1523 result = winreg_get_printer(tmp_ctx, b,
1524 lp_const_servicename(snum),
1527 if (!W_ERROR_IS_OK(result)) {
1531 if (!pinfo2->drivername) {
1535 if (strcmp(drivername, pinfo2->drivername) != 0) {
1539 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1541 /* all we care about currently is the change_id */
1542 result = winreg_printer_update_changeid(tmp_ctx, b,
1543 pinfo2->printername);
1545 if (!W_ERROR_IS_OK(result)) {
1546 DEBUG(3, ("do_drv_upgrade_printer: "
1547 "Failed to update changeid [%s]\n",
1548 win_errstr(result)));
1554 talloc_free(tmp_ctx);
1557 /********************************************************************
1558 Update the cache for all printq's with a registered client
1560 ********************************************************************/
1562 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1564 struct printer_handle *printer = printers_list;
1567 /* loop through all printers and update the cache where
1568 a client is connected */
1570 if ((printer->printer_type == SPLHND_PRINTER) &&
1571 ((printer->notify.cli_chan != NULL) &&
1572 (printer->notify.cli_chan->active_connections > 0))) {
1573 snum = print_queue_snum(printer->sharename);
1574 print_queue_status(msg_ctx, snum, NULL, NULL);
1577 printer = printer->next;
1583 /****************************************************************
1584 _spoolss_OpenPrinter
1585 ****************************************************************/
1587 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1588 struct spoolss_OpenPrinter *r)
1590 struct spoolss_OpenPrinterEx e;
1591 struct spoolss_UserLevel1 level1;
1594 ZERO_STRUCT(level1);
1596 e.in.printername = r->in.printername;
1597 e.in.datatype = r->in.datatype;
1598 e.in.devmode_ctr = r->in.devmode_ctr;
1599 e.in.access_mask = r->in.access_mask;
1600 e.in.userlevel_ctr.level = 1;
1601 e.in.userlevel_ctr.user_info.level1 = &level1;
1603 e.out.handle = r->out.handle;
1605 werr = _spoolss_OpenPrinterEx(p, &e);
1607 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAMETER)) {
1608 /* OpenPrinterEx returns this for a bad
1609 * printer name. We must return WERR_INVALID_PRINTER_NAME
1612 werr = WERR_INVALID_PRINTER_NAME;
1618 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1619 struct spoolss_DeviceMode *orig,
1620 struct spoolss_DeviceMode **dest)
1622 struct spoolss_DeviceMode *dm;
1624 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1626 return WERR_NOT_ENOUGH_MEMORY;
1629 /* copy all values, then duplicate strings and structs */
1632 dm->devicename = talloc_strdup(dm, orig->devicename);
1633 if (!dm->devicename) {
1634 return WERR_NOT_ENOUGH_MEMORY;
1636 dm->formname = talloc_strdup(dm, orig->formname);
1637 if (!dm->formname) {
1638 return WERR_NOT_ENOUGH_MEMORY;
1640 if (orig->driverextra_data.data) {
1641 dm->driverextra_data.data =
1642 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1643 orig->driverextra_data.length);
1644 if (!dm->driverextra_data.data) {
1645 return WERR_NOT_ENOUGH_MEMORY;
1653 /****************************************************************
1654 _spoolss_OpenPrinterEx
1655 ****************************************************************/
1657 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1658 struct spoolss_OpenPrinterEx *r)
1663 struct printer_handle *Printer=NULL;
1667 if (!r->in.printername) {
1668 return WERR_INVALID_PARAMETER;
1671 if (!*r->in.printername) {
1672 return WERR_INVALID_PARAMETER;
1675 if (r->in.userlevel_ctr.level > 3) {
1676 return WERR_INVALID_PARAMETER;
1678 if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1679 (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1680 (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1681 return WERR_INVALID_PARAMETER;
1685 * The printcap printer share inventory is updated on client
1686 * enumeration. For clients that do not perform enumeration prior to
1687 * access, such as cupssmbadd, we reinitialise the printer share
1688 * inventory on open as well.
1691 delete_and_reload_printers(server_event_context(), p->msg_ctx);
1694 /* some sanity check because you can open a printer or a print server */
1695 /* aka: \\server\printer or \\server */
1697 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1699 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1700 if (!W_ERROR_IS_OK(result)) {
1701 DEBUG(3,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1702 "for printer %s\n", r->in.printername));
1703 ZERO_STRUCTP(r->out.handle);
1707 Printer = find_printer_index_by_hnd(p, r->out.handle);
1709 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1710 "handle we created for printer %s\n", r->in.printername));
1711 close_printer_handle(p, r->out.handle);
1712 ZERO_STRUCTP(r->out.handle);
1713 return WERR_INVALID_PARAMETER;
1717 * First case: the user is opening the print server:
1719 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1720 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1722 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1723 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1724 * or if the user is listed in the smb.conf printer admin parameter.
1726 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1727 * client view printer folder, but does not show the MSAPW.
1729 * Note: this test needs code to check access rights here too. Jeremy
1730 * could you look at this?
1732 * Second case: the user is opening a printer:
1733 * NT doesn't let us connect to a printer if the connecting user
1734 * doesn't have print permission.
1736 * Third case: user is opening a Port Monitor
1737 * access checks same as opening a handle to the print server.
1740 switch (Printer->printer_type )
1743 case SPLHND_PORTMON_TCP:
1744 case SPLHND_PORTMON_LOCAL:
1745 /* Printserver handles use global struct... */
1749 if (r->in.access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
1750 r->in.access_mask |= SERVER_ACCESS_ADMINISTER;
1751 r->in.access_mask |= SERVER_ACCESS_ENUMERATE;
1754 /* Map standard access rights to object specific access rights */
1756 se_map_standard(&r->in.access_mask,
1757 &printserver_std_mapping);
1759 /* Deny any object specific bits that don't apply to print
1760 servers (i.e printer and job specific bits) */
1762 r->in.access_mask &= SEC_MASK_SPECIFIC;
1764 if (r->in.access_mask &
1765 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1766 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1767 close_printer_handle(p, r->out.handle);
1768 ZERO_STRUCTP(r->out.handle);
1769 return WERR_ACCESS_DENIED;
1772 /* Allow admin access */
1774 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1776 if (!lp_show_add_printer_wizard()) {
1777 close_printer_handle(p, r->out.handle);
1778 ZERO_STRUCTP(r->out.handle);
1779 return WERR_ACCESS_DENIED;
1782 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1783 and not a printer admin, then fail */
1785 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1786 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1787 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1788 p->session_info->security_token)) {
1789 close_printer_handle(p, r->out.handle);
1790 ZERO_STRUCTP(r->out.handle);
1791 DEBUG(3,("access DENIED as user is not root, "
1792 "has no printoperator privilege and is "
1793 "not a member of the printoperator builtin group\n"));
1794 return WERR_ACCESS_DENIED;
1797 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1801 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1804 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1805 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1807 /* We fall through to return WERR_OK */
1810 case SPLHND_PRINTER:
1811 /* NT doesn't let us connect to a printer if the connecting user
1812 doesn't have print permission. */
1814 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1815 close_printer_handle(p, r->out.handle);
1816 ZERO_STRUCTP(r->out.handle);
1817 return WERR_INVALID_HANDLE;
1820 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1821 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1824 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1826 /* map an empty access mask to the minimum access mask */
1827 if (r->in.access_mask == 0x0)
1828 r->in.access_mask = PRINTER_ACCESS_USE;
1831 * If we are not serving the printer driver for this printer,
1832 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1833 * will keep NT clients happy --jerry
1836 if (lp_use_client_driver(snum)
1837 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1839 r->in.access_mask = PRINTER_ACCESS_USE;
1842 /* check smb.conf parameters and the the sec_desc */
1843 raddr = tsocket_address_inet_addr_string(p->remote_address,
1845 if (raddr == NULL) {
1846 return WERR_NOT_ENOUGH_MEMORY;
1849 rc = get_remote_hostname(p->remote_address,
1853 return WERR_NOT_ENOUGH_MEMORY;
1855 if (strequal(rhost, "UNKNOWN")) {
1859 if (!allow_access(lp_hosts_deny(snum), lp_hosts_allow(snum),
1861 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1862 ZERO_STRUCTP(r->out.handle);
1863 return WERR_ACCESS_DENIED;
1866 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1867 p->session_info->security_token, snum) ||
1868 !W_ERROR_IS_OK(print_access_check(p->session_info,
1871 r->in.access_mask))) {
1872 DEBUG(3, ("access DENIED for printer open\n"));
1873 close_printer_handle(p, r->out.handle);
1874 ZERO_STRUCTP(r->out.handle);
1875 return WERR_ACCESS_DENIED;
1878 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1879 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1880 close_printer_handle(p, r->out.handle);
1881 ZERO_STRUCTP(r->out.handle);
1882 return WERR_ACCESS_DENIED;
1885 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1886 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1888 r->in.access_mask = PRINTER_ACCESS_USE;
1890 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1891 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1893 winreg_create_printer_internal(p->mem_ctx,
1894 get_session_info_system(),
1896 lp_const_servicename(snum));
1901 /* sanity check to prevent programmer error */
1902 ZERO_STRUCTP(r->out.handle);
1903 return WERR_INVALID_HANDLE;
1906 Printer->access_granted = r->in.access_mask;
1909 * If the client sent a devmode in the OpenPrinter() call, then
1910 * save it here in case we get a job submission on this handle
1913 if ((Printer->printer_type != SPLHND_SERVER)
1914 && (r->in.devmode_ctr.devmode != NULL)) {
1915 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1922 /****************************************************************
1923 _spoolss_ClosePrinter
1924 ****************************************************************/
1926 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1927 struct spoolss_ClosePrinter *r)
1929 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1931 if (Printer && Printer->document_started) {
1932 struct spoolss_EndDocPrinter e;
1934 e.in.handle = r->in.handle;
1936 _spoolss_EndDocPrinter(p, &e);
1939 if (!close_printer_handle(p, r->in.handle))
1940 return WERR_INVALID_HANDLE;
1942 /* clear the returned printer handle. Observed behavior
1943 from Win2k server. Don't think this really matters.
1944 Previous code just copied the value of the closed
1947 ZERO_STRUCTP(r->out.handle);
1952 /****************************************************************
1953 _spoolss_DeletePrinter
1954 ****************************************************************/
1956 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1957 struct spoolss_DeletePrinter *r)
1959 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1963 if (Printer && Printer->document_started) {
1964 struct spoolss_EndDocPrinter e;
1966 e.in.handle = r->in.handle;
1968 _spoolss_EndDocPrinter(p, &e);
1971 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
1972 winreg_delete_printer_key_internal(p->mem_ctx,
1973 get_session_info_system(),
1975 lp_const_servicename(snum),
1979 result = delete_printer_handle(p, r->in.handle);
1984 /*******************************************************************
1985 * static function to lookup the version id corresponding to an
1986 * long architecture string
1987 ******************************************************************/
1989 static const struct print_architecture_table_node archi_table[]= {
1991 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1992 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1993 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1994 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1995 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1996 {"Windows IA64", SPL_ARCH_IA64, 3 },
1997 {"Windows x64", SPL_ARCH_X64, 3 },
2001 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2002 SPOOLSS_DRIVER_VERSION_NT35,
2003 SPOOLSS_DRIVER_VERSION_NT4,
2004 SPOOLSS_DRIVER_VERSION_200X,
2007 static int get_version_id(const char *arch)
2011 for (i=0; archi_table[i].long_archi != NULL; i++)
2013 if (strcmp(arch, archi_table[i].long_archi) == 0)
2014 return (archi_table[i].version);
2020 /****************************************************************
2021 _spoolss_DeletePrinterDriver
2022 ****************************************************************/
2024 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2025 struct spoolss_DeletePrinterDriver *r)
2028 struct spoolss_DriverInfo8 *info = NULL;
2031 struct dcerpc_binding_handle *b;
2032 TALLOC_CTX *tmp_ctx = NULL;
2036 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2037 and not a printer admin, then fail */
2039 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2040 !security_token_has_privilege(p->session_info->security_token,
2041 SEC_PRIV_PRINT_OPERATOR)) {
2042 return WERR_ACCESS_DENIED;
2045 /* check that we have a valid driver name first */
2047 if ((version = get_version_id(r->in.architecture)) == -1) {
2048 return WERR_INVALID_ENVIRONMENT;
2051 tmp_ctx = talloc_new(p->mem_ctx);
2053 return WERR_NOT_ENOUGH_MEMORY;
2056 status = winreg_printer_binding_handle(tmp_ctx,
2057 get_session_info_system(),
2060 if (!W_ERROR_IS_OK(status)) {
2064 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2065 status = winreg_get_driver(tmp_ctx, b,
2066 r->in.architecture, r->in.driver,
2067 drv_cversion[i], &info);
2068 if (!W_ERROR_IS_OK(status)) {
2069 DEBUG(5, ("skipping del of driver with version %d\n",
2075 if (printer_driver_in_use(tmp_ctx, b, info)) {
2076 status = WERR_PRINTER_DRIVER_IN_USE;
2080 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2081 if (!W_ERROR_IS_OK(status)) {
2082 DEBUG(0, ("failed del of driver with version %d\n",
2087 if (found == false) {
2088 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2089 status = WERR_UNKNOWN_PRINTER_DRIVER;
2095 talloc_free(tmp_ctx);
2100 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2101 struct pipes_struct *p,
2102 struct spoolss_DeletePrinterDriverEx *r,
2103 struct dcerpc_binding_handle *b,
2104 struct spoolss_DriverInfo8 *info)
2109 if (printer_driver_in_use(mem_ctx, b, info)) {
2110 status = WERR_PRINTER_DRIVER_IN_USE;
2115 * we have a couple of cases to consider.
2116 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2117 * then the delete should fail if **any** files overlap with
2119 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2120 * non-overlapping files
2121 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2122 * are set, then do not delete any files
2123 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2126 delete_files = r->in.delete_flags
2127 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2131 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2132 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2133 status = WERR_PRINTER_DRIVER_IN_USE;
2137 * printer_driver_files_in_use() has trimmed overlapping files
2138 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2143 status = winreg_del_driver(mem_ctx, b, info, info->version);
2144 if (!W_ERROR_IS_OK(status)) {
2149 * now delete any associated files if delete_files is
2150 * true. Even if this part failes, we return succes
2151 * because the driver doesn not exist any more
2154 delete_driver_files(p->session_info, info);
2161 /****************************************************************
2162 _spoolss_DeletePrinterDriverEx
2163 ****************************************************************/
2165 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2166 struct spoolss_DeletePrinterDriverEx *r)
2168 struct spoolss_DriverInfo8 *info = NULL;
2170 struct dcerpc_binding_handle *b;
2171 TALLOC_CTX *tmp_ctx = NULL;
2175 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2176 and not a printer admin, then fail */
2178 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2179 !security_token_has_privilege(p->session_info->security_token,
2180 SEC_PRIV_PRINT_OPERATOR)) {
2181 return WERR_ACCESS_DENIED;
2184 /* check that we have a valid driver name first */
2185 if (get_version_id(r->in.architecture) == -1) {
2186 /* this is what NT returns */
2187 return WERR_INVALID_ENVIRONMENT;
2190 tmp_ctx = talloc_new(p->mem_ctx);
2192 return WERR_NOT_ENOUGH_MEMORY;
2195 status = winreg_printer_binding_handle(tmp_ctx,
2196 get_session_info_system(),
2199 if (!W_ERROR_IS_OK(status)) {
2203 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2204 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2205 && (drv_cversion[i] != r->in.version)) {
2209 /* check if a driver with this version exists before delete */
2210 status = winreg_get_driver(tmp_ctx, b,
2211 r->in.architecture, r->in.driver,
2212 drv_cversion[i], &info);
2213 if (!W_ERROR_IS_OK(status)) {
2214 DEBUG(5, ("skipping del of driver with version %d\n",
2220 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2221 if (!W_ERROR_IS_OK(status)) {
2222 DEBUG(0, ("failed to delete driver with version %d\n",
2227 if (found == false) {
2228 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2229 status = WERR_UNKNOWN_PRINTER_DRIVER;
2235 talloc_free(tmp_ctx);
2240 /********************************************************************
2241 GetPrinterData on a printer server Handle.
2242 ********************************************************************/
2244 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2246 enum winreg_Type *type,
2247 union spoolss_PrinterData *data)
2249 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2251 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2253 SIVAL(&data->value, 0, 0x00);
2257 if (!strcasecmp_m(value, "BeepEnabled")) {
2259 SIVAL(&data->value, 0, 0x00);
2263 if (!strcasecmp_m(value, "EventLog")) {
2265 /* formally was 0x1b */
2266 SIVAL(&data->value, 0, 0x00);
2270 if (!strcasecmp_m(value, "NetPopup")) {
2272 SIVAL(&data->value, 0, 0x00);
2276 if (!strcasecmp_m(value, "MajorVersion")) {
2279 /* Windows NT 4.0 seems to not allow uploading of drivers
2280 to a server that reports 0x3 as the MajorVersion.
2281 need to investigate more how Win2k gets around this .
2284 if (RA_WINNT == get_remote_arch()) {
2285 SIVAL(&data->value, 0, 0x02);
2287 SIVAL(&data->value, 0, 0x03);
2293 if (!strcasecmp_m(value, "MinorVersion")) {
2295 SIVAL(&data->value, 0, 0x00);
2300 * uint32_t size = 0x114
2301 * uint32_t major = 5
2302 * uint32_t minor = [0|1]
2303 * uint32_t build = [2195|2600]
2304 * extra unicode string = e.g. "Service Pack 3"
2306 if (!strcasecmp_m(value, "OSVersion")) {
2308 enum ndr_err_code ndr_err;
2309 struct spoolss_OSVersion os;
2312 * Set the default OSVersion to:
2314 * Windows Server 2003R2 SP2 (5.2.3790)
2316 * used to be Windows 2000 (5.0.2195)
2318 os.major = lp_parm_int(GLOBAL_SECTION_SNUM,
2319 "spoolss", "os_major",
2320 GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
2321 os.minor = lp_parm_int(GLOBAL_SECTION_SNUM,
2322 "spoolss", "os_minor",
2323 GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
2324 os.build = lp_parm_int(GLOBAL_SECTION_SNUM,
2325 "spoolss", "os_build",
2326 GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
2327 os.extra_string = ""; /* leave extra string empty */
2329 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2330 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2331 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2332 return WERR_GEN_FAILURE;
2335 if (DEBUGLEVEL >= 10) {
2336 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
2340 data->binary = blob;
2346 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2349 data->string = talloc_strdup(mem_ctx, SPOOLSS_DEFAULT_SERVER_PATH);
2350 W_ERROR_HAVE_NO_MEMORY(data->string);
2355 if (!strcasecmp_m(value, "Architecture")) {
2357 data->string = talloc_strdup(mem_ctx,
2358 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", GLOBAL_SPOOLSS_ARCHITECTURE));
2359 W_ERROR_HAVE_NO_MEMORY(data->string);
2364 if (!strcasecmp_m(value, "DsPresent")) {
2367 /* only show the publish check box if we are a
2368 member of a AD domain */
2370 if (lp_security() == SEC_ADS) {
2371 SIVAL(&data->value, 0, 0x01);
2373 SIVAL(&data->value, 0, 0x00);
2378 if (!strcasecmp_m(value, "DNSMachineName")) {
2379 const char *hostname = get_mydnsfullname();
2382 return WERR_FILE_NOT_FOUND;
2386 data->string = talloc_strdup(mem_ctx, hostname);
2387 W_ERROR_HAVE_NO_MEMORY(data->string);
2394 return WERR_INVALID_PARAMETER;
2397 /****************************************************************
2398 _spoolss_GetPrinterData
2399 ****************************************************************/
2401 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2402 struct spoolss_GetPrinterData *r)
2404 struct spoolss_GetPrinterDataEx r2;
2406 r2.in.handle = r->in.handle;
2407 r2.in.key_name = "PrinterDriverData";
2408 r2.in.value_name = r->in.value_name;
2409 r2.in.offered = r->in.offered;
2410 r2.out.type = r->out.type;
2411 r2.out.data = r->out.data;
2412 r2.out.needed = r->out.needed;
2414 return _spoolss_GetPrinterDataEx(p, &r2);
2417 /*********************************************************
2418 Connect to the client machine.
2419 **********************************************************/
2421 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe, struct cli_state **pp_cli,
2422 struct sockaddr_storage *client_ss, const char *remote_machine)
2425 struct sockaddr_storage rm_addr;
2426 char addr[INET6_ADDRSTRLEN];
2428 if ( is_zero_addr(client_ss) ) {
2429 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2431 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2432 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2435 print_sockaddr(addr, sizeof(addr), &rm_addr);
2437 rm_addr = *client_ss;
2438 print_sockaddr(addr, sizeof(addr), &rm_addr);
2439 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2443 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2444 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2449 /* setup the connection */
2450 ret = cli_full_connection( pp_cli, lp_netbios_name(), remote_machine,
2451 &rm_addr, 0, "IPC$", "IPC",
2455 0, lp_client_signing());
2457 if ( !NT_STATUS_IS_OK( ret ) ) {
2458 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2463 if ( smbXcli_conn_protocol((*pp_cli)->conn) < PROTOCOL_NT1 ) {
2464 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2465 cli_shutdown(*pp_cli);
2470 * Ok - we have an anonymous connection to the IPC$ share.
2471 * Now start the NT Domain stuff :-).
2474 ret = cli_rpc_pipe_open_noauth(*pp_cli, &ndr_table_spoolss, pp_pipe);
2475 if (!NT_STATUS_IS_OK(ret)) {
2476 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2477 remote_machine, nt_errstr(ret)));
2478 cli_shutdown(*pp_cli);
2485 /***************************************************************************
2486 Connect to the client.
2487 ****************************************************************************/
2489 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2490 uint32_t localprinter,
2491 enum winreg_Type type,
2492 struct policy_handle *handle,
2493 struct notify_back_channel **_chan,
2494 struct sockaddr_storage *client_ss,
2495 struct messaging_context *msg_ctx)
2499 struct notify_back_channel *chan;
2501 for (chan = back_channels; chan; chan = chan->next) {
2502 if (memcmp(&chan->client_address, client_ss,
2503 sizeof(struct sockaddr_storage)) == 0) {
2509 * If it's the first connection, contact the client
2510 * and connect to the IPC$ share anonymously
2513 fstring unix_printer;
2515 /* the +2 is to strip the leading 2 backslashs */
2516 fstrcpy(unix_printer, printer + 2);
2518 chan = talloc_zero(NULL, struct notify_back_channel);
2522 chan->client_address = *client_ss;
2524 if (!spoolss_connect_to_client(&chan->cli_pipe, &chan->cli, client_ss, unix_printer)) {
2529 DLIST_ADD(back_channels, chan);
2531 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2532 receive_notify2_message_list);
2535 if (chan->cli_pipe == NULL ||
2536 chan->cli_pipe->binding_handle == NULL) {
2537 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2538 "NULL %s for printer %s\n",
2539 chan->cli_pipe == NULL ?
2540 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2546 * Tell the specific printing tdb we want messages for this printer
2547 * by registering our PID.
2550 if (!print_notify_register_pid(snum)) {
2551 DEBUG(0, ("Failed to register our pid for printer %s\n",
2555 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2564 if (!NT_STATUS_IS_OK(status)) {
2565 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2566 result = ntstatus_to_werror(status);
2567 } else if (!W_ERROR_IS_OK(result)) {
2568 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2571 chan->active_connections++;
2574 return (W_ERROR_IS_OK(result));
2577 /****************************************************************
2578 ****************************************************************/
2580 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2581 const struct spoolss_NotifyOption *r)
2583 struct spoolss_NotifyOption *option;
2590 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2597 if (!option->count) {
2601 option->types = talloc_zero_array(option,
2602 struct spoolss_NotifyOptionType, option->count);
2603 if (!option->types) {
2604 talloc_free(option);
2608 for (i=0; i < option->count; i++) {
2609 option->types[i] = r->types[i];
2611 if (option->types[i].count) {
2612 option->types[i].fields = talloc_zero_array(option,
2613 union spoolss_Field, option->types[i].count);
2614 if (!option->types[i].fields) {
2615 talloc_free(option);
2618 for (k=0; k<option->types[i].count; k++) {
2619 option->types[i].fields[k] =
2620 r->types[i].fields[k];
2628 /****************************************************************
2629 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2631 * before replying OK: status=0 a rpc call is made to the workstation
2632 * asking ReplyOpenPrinter
2634 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2635 * called from api_spoolss_rffpcnex
2636 ****************************************************************/
2638 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2639 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2642 struct spoolss_NotifyOption *option = r->in.notify_options;
2643 struct sockaddr_storage client_ss;
2646 /* store the notify value in the printer struct */
2648 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2651 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2652 "Invalid handle (%s:%u:%u).\n",
2653 OUR_HANDLE(r->in.handle)));
2654 return WERR_INVALID_HANDLE;
2657 Printer->notify.flags = r->in.flags;
2658 Printer->notify.options = r->in.options;
2659 Printer->notify.printerlocal = r->in.printer_local;
2660 Printer->notify.msg_ctx = p->msg_ctx;
2662 TALLOC_FREE(Printer->notify.option);
2663 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2665 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2667 /* Connect to the client machine and send a ReplyOpenPrinter */
2669 if ( Printer->printer_type == SPLHND_SERVER)
2671 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2672 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2673 return WERR_INVALID_HANDLE;
2675 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2676 "remote_address is %s\n",
2677 tsocket_address_string(p->remote_address, p->mem_ctx)));
2679 if (!lp_print_notify_backchannel(snum)) {
2680 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2681 "backchannel disabled\n"));
2682 return WERR_RPC_S_SERVER_UNAVAILABLE;
2685 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2686 (struct sockaddr *) &client_ss,
2687 sizeof(struct sockaddr_storage));
2688 if (client_len < 0) {
2689 return WERR_NOT_ENOUGH_MEMORY;
2692 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2693 Printer->notify.printerlocal, REG_SZ,
2694 &Printer->notify.cli_hnd,
2695 &Printer->notify.cli_chan,
2696 &client_ss, p->msg_ctx)) {
2697 return WERR_RPC_S_SERVER_UNAVAILABLE;
2703 /*******************************************************************
2704 * fill a notify_info_data with the servername
2705 ********************************************************************/
2707 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2709 struct spoolss_Notify *data,
2710 print_queue_struct *queue,
2711 struct spoolss_PrinterInfo2 *pinfo2,
2712 TALLOC_CTX *mem_ctx)
2714 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2717 /*******************************************************************
2718 * fill a notify_info_data with the printername (not including the servername).
2719 ********************************************************************/
2721 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2723 struct spoolss_Notify *data,
2724 print_queue_struct *queue,
2725 struct spoolss_PrinterInfo2 *pinfo2,
2726 TALLOC_CTX *mem_ctx)
2728 /* the notify name should not contain the \\server\ part */
2729 const char *p = strrchr(pinfo2->printername, '\\');
2732 p = pinfo2->printername;
2737 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2740 /*******************************************************************
2741 * fill a notify_info_data with the servicename
2742 ********************************************************************/
2744 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2746 struct spoolss_Notify *data,
2747 print_queue_struct *queue,
2748 struct spoolss_PrinterInfo2 *pinfo2,
2749 TALLOC_CTX *mem_ctx)
2751 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2754 /*******************************************************************
2755 * fill a notify_info_data with the port name
2756 ********************************************************************/
2758 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2760 struct spoolss_Notify *data,
2761 print_queue_struct *queue,
2762 struct spoolss_PrinterInfo2 *pinfo2,
2763 TALLOC_CTX *mem_ctx)
2765 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2768 /*******************************************************************
2769 * fill a notify_info_data with the printername
2770 * but it doesn't exist, have to see what to do
2771 ********************************************************************/
2773 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2775 struct spoolss_Notify *data,
2776 print_queue_struct *queue,
2777 struct spoolss_PrinterInfo2 *pinfo2,
2778 TALLOC_CTX *mem_ctx)
2780 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2783 /*******************************************************************
2784 * fill a notify_info_data with the comment
2785 ********************************************************************/
2787 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2789 struct spoolss_Notify *data,
2790 print_queue_struct *queue,
2791 struct spoolss_PrinterInfo2 *pinfo2,
2792 TALLOC_CTX *mem_ctx)
2796 if (*pinfo2->comment == '\0') {
2797 p = lp_comment(talloc_tos(), snum);
2799 p = pinfo2->comment;
2802 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2805 /*******************************************************************
2806 * fill a notify_info_data with the comment
2807 * location = "Room 1, floor 2, building 3"
2808 ********************************************************************/
2810 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2812 struct spoolss_Notify *data,
2813 print_queue_struct *queue,
2814 struct spoolss_PrinterInfo2 *pinfo2,
2815 TALLOC_CTX *mem_ctx)
2817 const char *loc = pinfo2->location;
2820 status = printer_list_get_printer(mem_ctx,
2825 if (NT_STATUS_IS_OK(status)) {
2827 loc = pinfo2->location;
2831 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2834 /*******************************************************************
2835 * fill a notify_info_data with the device mode
2836 * jfm:xxxx don't to it for know but that's a real problem !!!
2837 ********************************************************************/
2839 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2841 struct spoolss_Notify *data,
2842 print_queue_struct *queue,
2843 struct spoolss_PrinterInfo2 *pinfo2,
2844 TALLOC_CTX *mem_ctx)
2846 /* for a dummy implementation we have to zero the fields */
2847 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2850 /*******************************************************************
2851 * fill a notify_info_data with the separator file name
2852 ********************************************************************/
2854 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2856 struct spoolss_Notify *data,
2857 print_queue_struct *queue,
2858 struct spoolss_PrinterInfo2 *pinfo2,
2859 TALLOC_CTX *mem_ctx)
2861 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2864 /*******************************************************************
2865 * fill a notify_info_data with the print processor
2866 * jfm:xxxx return always winprint to indicate we don't do anything to it
2867 ********************************************************************/
2869 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2871 struct spoolss_Notify *data,
2872 print_queue_struct *queue,
2873 struct spoolss_PrinterInfo2 *pinfo2,
2874 TALLOC_CTX *mem_ctx)
2876 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2879 /*******************************************************************
2880 * fill a notify_info_data with the print processor options
2881 * jfm:xxxx send an empty string
2882 ********************************************************************/
2884 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2886 struct spoolss_Notify *data,
2887 print_queue_struct *queue,
2888 struct spoolss_PrinterInfo2 *pinfo2,
2889 TALLOC_CTX *mem_ctx)
2891 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2894 /*******************************************************************
2895 * fill a notify_info_data with the data type
2896 * jfm:xxxx always send RAW as data type
2897 ********************************************************************/
2899 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2901 struct spoolss_Notify *data,
2902 print_queue_struct *queue,
2903 struct spoolss_PrinterInfo2 *pinfo2,
2904 TALLOC_CTX *mem_ctx)
2906 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2909 /*******************************************************************
2910 * fill a notify_info_data with the security descriptor
2911 * jfm:xxxx send an null pointer to say no security desc
2912 * have to implement security before !
2913 ********************************************************************/
2915 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2917 struct spoolss_Notify *data,
2918 print_queue_struct *queue,
2919 struct spoolss_PrinterInfo2 *pinfo2,
2920 TALLOC_CTX *mem_ctx)
2922 if (pinfo2->secdesc == NULL) {
2923 data->data.sd.sd = NULL;
2925 data->data.sd.sd = security_descriptor_copy(mem_ctx,
2928 data->data.sd.sd_size = ndr_size_security_descriptor(data->data.sd.sd,
2932 /*******************************************************************
2933 * fill a notify_info_data with the attributes
2934 * jfm:xxxx a samba printer is always shared
2935 ********************************************************************/
2937 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2939 struct spoolss_Notify *data,
2940 print_queue_struct *queue,
2941 struct spoolss_PrinterInfo2 *pinfo2,
2942 TALLOC_CTX *mem_ctx)
2944 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2947 /*******************************************************************
2948 * fill a notify_info_data with the priority
2949 ********************************************************************/
2951 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2953 struct spoolss_Notify *data,
2954 print_queue_struct *queue,
2955 struct spoolss_PrinterInfo2 *pinfo2,
2956 TALLOC_CTX *mem_ctx)
2958 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2961 /*******************************************************************
2962 * fill a notify_info_data with the default priority
2963 ********************************************************************/
2965 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2967 struct spoolss_Notify *data,
2968 print_queue_struct *queue,
2969 struct spoolss_PrinterInfo2 *pinfo2,
2970 TALLOC_CTX *mem_ctx)
2972 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2975 /*******************************************************************
2976 * fill a notify_info_data with the start time
2977 ********************************************************************/
2979 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2981 struct spoolss_Notify *data,
2982 print_queue_struct *queue,
2983 struct spoolss_PrinterInfo2 *pinfo2,
2984 TALLOC_CTX *mem_ctx)
2986 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2989 /*******************************************************************
2990 * fill a notify_info_data with the until time
2991 ********************************************************************/
2993 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
2995 struct spoolss_Notify *data,
2996 print_queue_struct *queue,
2997 struct spoolss_PrinterInfo2 *pinfo2,
2998 TALLOC_CTX *mem_ctx)
3000 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3003 /*******************************************************************
3004 * fill a notify_info_data with the status
3005 ********************************************************************/
3007 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3009 struct spoolss_Notify *data,
3010 print_queue_struct *queue,
3011 struct spoolss_PrinterInfo2 *pinfo2,
3012 TALLOC_CTX *mem_ctx)
3014 print_status_struct status;
3016 print_queue_length(msg_ctx, snum, &status);
3017 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3020 /*******************************************************************
3021 * fill a notify_info_data with the number of jobs queued
3022 ********************************************************************/
3024 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3026 struct spoolss_Notify *data,
3027 print_queue_struct *queue,
3028 struct spoolss_PrinterInfo2 *pinfo2,
3029 TALLOC_CTX *mem_ctx)
3031 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3032 data, print_queue_length(msg_ctx, snum, NULL));
3035 /*******************************************************************
3036 * fill a notify_info_data with the average ppm
3037 ********************************************************************/
3039 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3041 struct spoolss_Notify *data,
3042 print_queue_struct *queue,
3043 struct spoolss_PrinterInfo2 *pinfo2,
3044 TALLOC_CTX *mem_ctx)
3046 /* always respond 8 pages per minutes */
3047 /* a little hard ! */
3048 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3051 /*******************************************************************
3052 * fill a notify_info_data with username
3053 ********************************************************************/
3055 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3057 struct spoolss_Notify *data,
3058 print_queue_struct *queue,
3059 struct spoolss_PrinterInfo2 *pinfo2,
3060 TALLOC_CTX *mem_ctx)
3062 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3065 /*******************************************************************
3066 * fill a notify_info_data with job status
3067 ********************************************************************/
3069 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3071 struct spoolss_Notify *data,
3072 print_queue_struct *queue,
3073 struct spoolss_PrinterInfo2 *pinfo2,
3074 TALLOC_CTX *mem_ctx)
3076 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3079 /*******************************************************************
3080 * fill a notify_info_data with job name
3081 ********************************************************************/
3083 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3085 struct spoolss_Notify *data,
3086 print_queue_struct *queue,
3087 struct spoolss_PrinterInfo2 *pinfo2,
3088 TALLOC_CTX *mem_ctx)
3090 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3093 /*******************************************************************
3094 * fill a notify_info_data with job status
3095 ********************************************************************/
3097 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3099 struct spoolss_Notify *data,
3100 print_queue_struct *queue,
3101 struct spoolss_PrinterInfo2 *pinfo2,
3102 TALLOC_CTX *mem_ctx)
3105 * Now we're returning job status codes we just return a "" here. JRA.
3110 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3113 switch (queue->status) {
3118 p = ""; /* NT provides the paused string */
3127 #endif /* NO LONGER NEEDED. */
3129 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3132 /*******************************************************************
3133 * fill a notify_info_data with job time
3134 ********************************************************************/
3136 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3138 struct spoolss_Notify *data,
3139 print_queue_struct *queue,
3140 struct spoolss_PrinterInfo2 *pinfo2,
3141 TALLOC_CTX *mem_ctx)
3143 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3146 /*******************************************************************
3147 * fill a notify_info_data with job size
3148 ********************************************************************/
3150 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3152 struct spoolss_Notify *data,
3153 print_queue_struct *queue,
3154 struct spoolss_PrinterInfo2 *pinfo2,
3155 TALLOC_CTX *mem_ctx)
3157 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3160 /*******************************************************************
3161 * fill a notify_info_data with page info
3162 ********************************************************************/
3163 static void spoolss_notify_total_pages(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, queue->page_count);
3173 /*******************************************************************
3174 * fill a notify_info_data with pages printed info.
3175 ********************************************************************/
3176 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3178 struct spoolss_Notify *data,
3179 print_queue_struct *queue,
3180 struct spoolss_PrinterInfo2 *pinfo2,
3181 TALLOC_CTX *mem_ctx)
3183 /* Add code when back-end tracks this */
3184 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3187 /*******************************************************************
3188 Fill a notify_info_data with job position.
3189 ********************************************************************/
3191 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3193 struct spoolss_Notify *data,
3194 print_queue_struct *queue,
3195 struct spoolss_PrinterInfo2 *pinfo2,
3196 TALLOC_CTX *mem_ctx)
3198 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3201 /*******************************************************************
3202 Fill a notify_info_data with submitted time.
3203 ********************************************************************/
3205 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3207 struct spoolss_Notify *data,
3208 print_queue_struct *queue,
3209 struct spoolss_PrinterInfo2 *pinfo2,
3210 TALLOC_CTX *mem_ctx)
3212 data->data.string.string = NULL;
3213 data->data.string.size = 0;
3215 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3216 &data->data.string.string,
3217 &data->data.string.size);
3221 struct s_notify_info_data_table
3223 enum spoolss_NotifyType type;
3226 enum spoolss_NotifyTable variable_type;
3227 void (*fn) (struct messaging_context *msg_ctx,
3228 int snum, struct spoolss_Notify *data,
3229 print_queue_struct *queue,
3230 struct spoolss_PrinterInfo2 *pinfo2,
3231 TALLOC_CTX *mem_ctx);
3234 /* A table describing the various print notification constants and
3235 whether the notification data is a pointer to a variable sized
3236 buffer, a one value uint32_t or a two value uint32_t. */
3238 static const struct s_notify_info_data_table notify_info_data_table[] =
3240 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3241 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3242 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3243 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3244 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3245 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3246 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3250 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3266 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3267 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3268 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3269 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3270 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3271 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3272 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3273 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3274 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3275 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3276 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3277 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3278 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3279 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3280 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3281 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3282 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3291 /*******************************************************************
3292 Return the variable_type of info_data structure.
3293 ********************************************************************/
3295 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3300 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3301 if ( (notify_info_data_table[i].type == type) &&
3302 (notify_info_data_table[i].field == field) ) {
3303 return notify_info_data_table[i].variable_type;
3307 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3309 return (enum spoolss_NotifyTable) 0;
3312 /****************************************************************************
3313 ****************************************************************************/
3315 static bool search_notify(enum spoolss_NotifyType type,
3321 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3322 if (notify_info_data_table[i].type == type &&
3323 notify_info_data_table[i].field == field &&
3324 notify_info_data_table[i].fn != NULL) {
3333 /****************************************************************************
3334 ****************************************************************************/
3336 static void construct_info_data(struct spoolss_Notify *info_data,
3337 enum spoolss_NotifyType type,
3338 uint16_t field, int id)
3340 info_data->type = type;
3341 info_data->field.field = field;
3342 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3343 info_data->job_id = id;
3346 /*******************************************************************
3348 * fill a notify_info struct with info asked
3350 ********************************************************************/
3352 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3353 struct printer_handle *print_hnd,
3354 struct spoolss_NotifyInfo *info,
3355 struct spoolss_PrinterInfo2 *pinfo2,
3357 const struct spoolss_NotifyOptionType *option_type,
3359 TALLOC_CTX *mem_ctx)
3362 enum spoolss_NotifyType type;
3365 struct spoolss_Notify *current_data;
3367 type = option_type->type;
3369 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3370 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3371 option_type->count, lp_servicename(talloc_tos(), snum)));
3373 for(field_num=0; field_num < option_type->count; field_num++) {
3374 field = option_type->fields[field_num].field;
3376 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3378 if (!search_notify(type, field, &j) )
3381 info->notifies = talloc_realloc(info, info->notifies,
3382 struct spoolss_Notify,
3384 if (info->notifies == NULL) {
3385 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3389 current_data = &info->notifies[info->count];
3391 construct_info_data(current_data, type, field, id);
3393 DEBUG(10, ("construct_notify_printer_info: "
3394 "calling [%s] snum=%d printername=[%s])\n",
3395 notify_info_data_table[j].name, snum,
3396 pinfo2->printername));
3398 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3399 NULL, pinfo2, mem_ctx);
3407 /*******************************************************************
3409 * fill a notify_info struct with info asked
3411 ********************************************************************/
3413 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3414 print_queue_struct *queue,
3415 struct spoolss_NotifyInfo *info,
3416 struct spoolss_PrinterInfo2 *pinfo2,
3418 const struct spoolss_NotifyOptionType *option_type,
3420 TALLOC_CTX *mem_ctx)
3423 enum spoolss_NotifyType type;
3425 struct spoolss_Notify *current_data;
3427 DEBUG(4,("construct_notify_jobs_info\n"));
3429 type = option_type->type;
3431 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3432 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3433 option_type->count));
3435 for(field_num=0; field_num<option_type->count; field_num++) {
3436 field = option_type->fields[field_num].field;
3438 if (!search_notify(type, field, &j) )
3441 info->notifies = talloc_realloc(info, info->notifies,
3442 struct spoolss_Notify,
3444 if (info->notifies == NULL) {
3445 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3449 current_data=&(info->notifies[info->count]);
3451 construct_info_data(current_data, type, field, id);
3452 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3453 queue, pinfo2, mem_ctx);
3461 * JFM: The enumeration is not that simple, it's even non obvious.
3463 * let's take an example: I want to monitor the PRINTER SERVER for
3464 * the printer's name and the number of jobs currently queued.
3465 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3466 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3468 * I have 3 printers on the back of my server.
3470 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3473 * 1 printer 1 name 1
3474 * 2 printer 1 cjob 1
3475 * 3 printer 2 name 2
3476 * 4 printer 2 cjob 2
3477 * 5 printer 3 name 3
3478 * 6 printer 3 name 3
3480 * that's the print server case, the printer case is even worse.
3483 /*******************************************************************
3485 * enumerate all printers on the printserver
3486 * fill a notify_info struct with info asked
3488 ********************************************************************/
3490 static WERROR printserver_notify_info(struct pipes_struct *p,
3491 struct policy_handle *hnd,
3492 struct spoolss_NotifyInfo *info,
3493 TALLOC_CTX *mem_ctx)
3496 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3497 int n_services=lp_numservices();
3499 struct spoolss_NotifyOption *option;
3500 struct spoolss_NotifyOptionType option_type;
3501 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3504 DEBUG(4,("printserver_notify_info\n"));
3507 return WERR_INVALID_HANDLE;
3509 option = Printer->notify.option;
3512 info->notifies = NULL;
3515 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3516 sending a ffpcn() request first */
3519 return WERR_INVALID_HANDLE;
3521 for (i=0; i<option->count; i++) {
3522 option_type = option->types[i];
3524 if (option_type.type != PRINTER_NOTIFY_TYPE)
3527 for (snum = 0; snum < n_services; snum++) {
3528 if (!lp_browseable(snum) ||
3529 !lp_snum_ok(snum) ||
3530 !lp_printable(snum)) {
3531 continue; /* skip */
3534 /* Maybe we should use the SYSTEM session_info here... */
3535 result = winreg_get_printer_internal(mem_ctx,
3536 get_session_info_system(),
3538 lp_servicename(talloc_tos(), snum),
3540 if (!W_ERROR_IS_OK(result)) {
3541 DEBUG(4, ("printserver_notify_info: "
3542 "Failed to get printer [%s]\n",
3543 lp_servicename(talloc_tos(), snum)));
3548 construct_notify_printer_info(p->msg_ctx,
3554 TALLOC_FREE(pinfo2);
3560 * Debugging information, don't delete.
3563 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3564 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3565 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3567 for (i=0; i<info->count; i++) {
3568 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3569 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3570 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3577 /*******************************************************************
3579 * fill a notify_info struct with info asked
3581 ********************************************************************/
3583 static WERROR printer_notify_info(struct pipes_struct *p,
3584 struct policy_handle *hnd,
3585 struct spoolss_NotifyInfo *info,
3586 TALLOC_CTX *mem_ctx)
3589 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3592 struct spoolss_NotifyOption *option;
3593 struct spoolss_NotifyOptionType option_type;
3595 print_queue_struct *queue=NULL;
3596 print_status_struct status;
3597 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3599 struct tdb_print_db *pdb;
3601 DEBUG(4,("printer_notify_info\n"));
3604 return WERR_INVALID_HANDLE;
3606 option = Printer->notify.option;
3610 info->notifies = NULL;
3613 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3614 sending a ffpcn() request first */
3617 return WERR_INVALID_HANDLE;
3619 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3620 return WERR_INVALID_HANDLE;
3623 pdb = get_print_db_byname(Printer->sharename);
3625 return WERR_INVALID_HANDLE;
3628 /* Maybe we should use the SYSTEM session_info here... */
3629 result = winreg_get_printer_internal(mem_ctx,
3630 get_session_info_system(),
3632 lp_servicename(talloc_tos(), snum), &pinfo2);
3633 if (!W_ERROR_IS_OK(result)) {
3634 result = WERR_INVALID_HANDLE;
3639 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3640 * correct servername.
3642 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3643 if (pinfo2->servername == NULL) {
3644 result = WERR_NOT_ENOUGH_MEMORY;
3648 for (i = 0; i < option->count; i++) {
3649 option_type = option->types[i];
3651 switch (option_type.type) {
3652 case PRINTER_NOTIFY_TYPE:
3653 if (construct_notify_printer_info(p->msg_ctx,
3662 case JOB_NOTIFY_TYPE:
3664 count = print_queue_status(p->msg_ctx, snum, &queue,
3667 for (j = 0; j < count; j++) {
3669 jobid = sysjob_to_jobid_pdb(pdb,
3671 if (jobid == (uint32_t)-1) {
3672 DEBUG(2, ("ignoring untracked job %d\n",
3676 /* FIXME check return value */
3677 construct_notify_jobs_info(p->msg_ctx,
3691 * Debugging information, don't delete.
3694 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3695 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3696 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3698 for (i=0; i<info->count; i++) {
3699 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3700 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3701 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3705 talloc_free(pinfo2);
3708 release_print_db(pdb);
3712 /****************************************************************
3713 _spoolss_RouterRefreshPrinterChangeNotify
3714 ****************************************************************/
3716 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3717 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3719 struct spoolss_NotifyInfo *info;
3721 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3722 WERROR result = WERR_INVALID_HANDLE;
3724 /* we always have a spoolss_NotifyInfo struct */
3725 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3727 result = WERR_NOT_ENOUGH_MEMORY;
3731 *r->out.info = info;
3734 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3735 "Invalid handle (%s:%u:%u).\n",
3736 OUR_HANDLE(r->in.handle)));
3740 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3743 * We are now using the change value, and
3744 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3745 * I don't have a global notification system, I'm sending back all the
3746 * information even when _NOTHING_ has changed.
3749 /* We need to keep track of the change value to send back in
3750 RRPCN replies otherwise our updates are ignored. */
3752 Printer->notify.fnpcn = true;
3754 if (Printer->notify.cli_chan != NULL &&
3755 Printer->notify.cli_chan->active_connections > 0) {
3756 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3757 "Saving change value in request [%x]\n",
3759 Printer->notify.change = r->in.change_low;
3762 /* just ignore the spoolss_NotifyOption */
3764 switch (Printer->printer_type) {
3766 result = printserver_notify_info(p, r->in.handle,
3770 case SPLHND_PRINTER:
3771 result = printer_notify_info(p, r->in.handle,
3776 Printer->notify.fnpcn = false;
3782 /********************************************************************
3783 ********************************************************************/
3785 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3786 const char *servername,
3787 const char *printername,
3788 const char **printername_p)
3790 /* FIXME: add lp_force_printername() */
3792 if (servername == NULL) {
3793 *printername_p = talloc_strdup(mem_ctx, printername);
3794 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3798 if (servername[0] == '\\' && servername[1] == '\\') {
3802 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3803 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3808 /********************************************************************
3809 ********************************************************************/
3811 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3812 const char *printername)
3818 dm->devicename = talloc_strndup(dm, printername,
3819 MIN(strlen(printername), 31));
3822 /********************************************************************
3823 * construct_printer_info_0
3824 * fill a printer_info_0 struct
3825 ********************************************************************/
3827 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3828 const struct auth_session_info *session_info,
3829 struct messaging_context *msg_ctx,
3830 struct spoolss_PrinterInfo2 *info2,
3831 const char *servername,
3832 struct spoolss_PrinterInfo0 *r,
3836 struct printer_session_counter *session_counter;
3837 struct timeval setuptime;
3838 print_status_struct status;
3840 int os_major, os_minor, os_build;
3841 const char *architecture;
3842 uint32_t processor_architecture, processor_type;
3844 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3845 if (!W_ERROR_IS_OK(result)) {
3850 r->servername = talloc_strdup(mem_ctx, servername);
3851 W_ERROR_HAVE_NO_MEMORY(r->servername);
3853 r->servername = NULL;
3856 count = print_queue_length(msg_ctx, snum, &status);
3858 /* check if we already have a counter for this printer */
3859 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3860 if (session_counter->snum == snum)
3864 /* it's the first time, add it to the list */
3865 if (session_counter == NULL) {
3866 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3867 W_ERROR_HAVE_NO_MEMORY(session_counter);
3868 session_counter->snum = snum;
3869 session_counter->counter = 0;
3870 DLIST_ADD(counter_list, session_counter);
3874 session_counter->counter++;
3880 get_startup_time(&setuptime);
3881 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3884 * the global_counter should be stored in a TDB as it's common to all the clients
3885 * and should be zeroed on samba startup
3887 r->global_counter = session_counter->counter;
3890 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3891 os_major = lp_parm_int(GLOBAL_SECTION_SNUM,
3892 "spoolss", "os_major",
3893 GLOBAL_SPOOLSS_OS_MAJOR_DEFAULT);
3894 os_minor = lp_parm_int(GLOBAL_SECTION_SNUM,
3895 "spoolss", "os_minor",
3896 GLOBAL_SPOOLSS_OS_MINOR_DEFAULT);
3897 os_build = lp_parm_int(GLOBAL_SECTION_SNUM,
3898 "spoolss", "os_build",
3899 GLOBAL_SPOOLSS_OS_BUILD_DEFAULT);
3901 SCVAL(&r->version, 0, os_major);
3902 SCVAL(&r->version, 1, os_minor);
3903 SSVAL(&r->version, 2, os_build);
3905 architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
3908 GLOBAL_SPOOLSS_ARCHITECTURE);
3910 if (strequal(architecture, SPOOLSS_ARCHITECTURE_x64)) {
3911 processor_architecture = PROCESSOR_ARCHITECTURE_AMD64;
3912 processor_type = PROCESSOR_AMD_X8664;
3914 processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3915 processor_type = PROCESSOR_INTEL_PENTIUM;
3918 r->free_build = SPOOLSS_RELEASE_BUILD;
3920 r->max_spooling = 0;
3921 r->session_counter = session_counter->counter;
3922 r->num_error_out_of_paper = 0x0;
3923 r->num_error_not_ready = 0x0; /* number of print failure */
3925 r->number_of_processors = 0x1;
3926 r->processor_type = processor_type;
3927 r->high_part_total_bytes = 0x0;
3929 /* ChangeID in milliseconds*/
3930 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3931 info2->sharename, &r->change_id);
3933 r->last_error = WERR_OK;
3934 r->status = nt_printq_status(status.status);
3935 r->enumerate_network_printers = 0x0;
3936 r->c_setprinter = 0x0;
3937 r->processor_architecture = processor_architecture;
3938 r->processor_level = 0x6; /* 6 ???*/
3947 /********************************************************************
3948 * construct_printer_info1
3949 * fill a spoolss_PrinterInfo1 struct
3950 ********************************************************************/
3952 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3953 const struct spoolss_PrinterInfo2 *info2,
3955 const char *servername,
3956 struct spoolss_PrinterInfo1 *r,
3963 if (info2->comment == NULL || info2->comment[0] == '\0') {
3964 r->comment = lp_comment(mem_ctx, snum);
3966 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3968 W_ERROR_HAVE_NO_MEMORY(r->comment);
3970 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3971 if (!W_ERROR_IS_OK(result)) {
3975 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3979 W_ERROR_HAVE_NO_MEMORY(r->description);
3984 /********************************************************************
3985 * construct_printer_info2
3986 * fill a spoolss_PrinterInfo2 struct
3987 ********************************************************************/
3989 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3990 struct messaging_context *msg_ctx,
3991 const struct spoolss_PrinterInfo2 *info2,
3992 const char *servername,
3993 struct spoolss_PrinterInfo2 *r,
3997 print_status_struct status;
4000 count = print_queue_length(msg_ctx, snum, &status);
4003 r->servername = talloc_strdup(mem_ctx, servername);
4004 W_ERROR_HAVE_NO_MEMORY(r->servername);
4006 r->servername = NULL;
4009 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4010 if (!W_ERROR_IS_OK(result)) {
4014 r->sharename = lp_servicename(mem_ctx, snum);
4015 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4016 r->portname = talloc_strdup(mem_ctx, info2->portname);
4017 W_ERROR_HAVE_NO_MEMORY(r->portname);
4018 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4019 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4021 if (info2->comment[0] == '\0') {
4022 r->comment = lp_comment(mem_ctx, snum);
4024 r->comment = talloc_strdup(mem_ctx, info2->comment);
4026 W_ERROR_HAVE_NO_MEMORY(r->comment);
4028 r->location = talloc_strdup(mem_ctx, info2->location);
4029 if (info2->location[0] == '\0') {
4030 const char *loc = NULL;
4033 nt_status = printer_list_get_printer(mem_ctx,
4038 if (NT_STATUS_IS_OK(nt_status)) {
4040 r->location = talloc_strdup(mem_ctx, loc);
4044 W_ERROR_HAVE_NO_MEMORY(r->location);
4046 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4047 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4048 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4049 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4050 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4051 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4052 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4053 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4055 r->attributes = info2->attributes;
4057 r->priority = info2->priority;
4058 r->defaultpriority = info2->defaultpriority;
4059 r->starttime = info2->starttime;
4060 r->untiltime = info2->untiltime;
4061 r->status = nt_printq_status(status.status);
4063 r->averageppm = info2->averageppm;
4065 if (info2->devmode != NULL) {
4066 result = copy_devicemode(mem_ctx,
4069 if (!W_ERROR_IS_OK(result)) {
4072 } else if (lp_default_devmode(snum)) {
4073 result = spoolss_create_default_devmode(mem_ctx,
4076 if (!W_ERROR_IS_OK(result)) {
4081 DEBUG(8,("Returning NULL Devicemode!\n"));
4084 compose_devicemode_devicename(r->devmode, r->printername);
4088 if (info2->secdesc != NULL) {
4089 /* don't use talloc_steal() here unless you do a deep steal of all
4090 the SEC_DESC members */
4092 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4093 if (r->secdesc == NULL) {
4094 return WERR_NOT_ENOUGH_MEMORY;
4101 /********************************************************************
4102 * construct_printer_info3
4103 * fill a spoolss_PrinterInfo3 struct
4104 ********************************************************************/
4106 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4107 const struct spoolss_PrinterInfo2 *info2,
4108 const char *servername,
4109 struct spoolss_PrinterInfo3 *r,
4112 /* These are the components of the SD we are returning. */
4114 if (info2->secdesc != NULL) {
4115 /* don't use talloc_steal() here unless you do a deep steal of all
4116 the SEC_DESC members */
4118 r->secdesc = security_descriptor_copy(mem_ctx, info2->secdesc);
4119 if (r->secdesc == NULL) {
4120 return WERR_NOT_ENOUGH_MEMORY;
4127 /********************************************************************
4128 * construct_printer_info4
4129 * fill a spoolss_PrinterInfo4 struct
4130 ********************************************************************/
4132 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4133 const struct spoolss_PrinterInfo2 *info2,
4134 const char *servername,
4135 struct spoolss_PrinterInfo4 *r,
4140 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4141 if (!W_ERROR_IS_OK(result)) {
4146 r->servername = talloc_strdup(mem_ctx, servername);
4147 W_ERROR_HAVE_NO_MEMORY(r->servername);
4149 r->servername = NULL;
4152 r->attributes = info2->attributes;
4157 /********************************************************************
4158 * construct_printer_info5
4159 * fill a spoolss_PrinterInfo5 struct
4160 ********************************************************************/
4162 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4163 const struct spoolss_PrinterInfo2 *info2,
4164 const char *servername,
4165 struct spoolss_PrinterInfo5 *r,
4170 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4171 if (!W_ERROR_IS_OK(result)) {
4175 r->portname = talloc_strdup(mem_ctx, info2->portname);
4176 W_ERROR_HAVE_NO_MEMORY(r->portname);
4178 r->attributes = info2->attributes;
4181 * These two are not used by NT+ according to MSDN. However the values
4182 * we saw on Windows Server 2012 and 2016 are always set to the 0xafc8.
4184 r->device_not_selected_timeout = 0xafc8; /* 45 sec */
4185 r->transmission_retry_timeout = 0xafc8; /* 45 sec */
4190 /********************************************************************
4191 * construct_printer_info_6
4192 * fill a spoolss_PrinterInfo6 struct
4193 ********************************************************************/
4195 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4196 struct messaging_context *msg_ctx,
4197 const struct spoolss_PrinterInfo2 *info2,
4198 const char *servername,
4199 struct spoolss_PrinterInfo6 *r,
4202 print_status_struct status;
4204 print_queue_length(msg_ctx, snum, &status);
4206 r->status = nt_printq_status(status.status);
4211 /********************************************************************
4212 * construct_printer_info7
4213 * fill a spoolss_PrinterInfo7 struct
4214 ********************************************************************/
4216 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4217 struct messaging_context *msg_ctx,
4218 const char *servername,
4219 struct spoolss_PrinterInfo7 *r,
4222 const struct auth_session_info *session_info;
4223 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
4226 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
4227 if (tmp_ctx == NULL) {
4228 return WERR_NOT_ENOUGH_MEMORY;
4231 session_info = get_session_info_system();
4232 SMB_ASSERT(session_info != NULL);
4234 printer = lp_servicename(tmp_ctx, snum);
4235 if (printer == NULL) {
4236 DEBUG(0, ("invalid printer snum %d\n", snum));
4237 werr = WERR_INVALID_PARAMETER;
4241 if (is_printer_published(tmp_ctx, session_info, msg_ctx,
4242 servername, printer, &pinfo2)) {
4245 werr = nt_printer_guid_get(tmp_ctx, session_info, msg_ctx,
4247 if (!W_ERROR_IS_OK(werr)) {
4249 * If we do not have a GUID entry in the registry, then
4250 * try to retrieve it from AD and store it now.
4252 werr = nt_printer_guid_retrieve(tmp_ctx, printer,
4254 if (!W_ERROR_IS_OK(werr)) {
4255 DBG_NOTICE("Failed to retrieve GUID for "
4256 "printer [%s] from AD - %s\n",
4259 if (W_ERROR_EQUAL(werr, WERR_FILE_NOT_FOUND)) {
4261 * If we did not find it in AD, then it
4262 * is unpublished and we should reflect
4263 * this in the registry and return
4266 DBG_WARNING("Unpublish printer [%s]\n",
4268 nt_printer_publish(tmp_ctx,
4273 r->guid = talloc_strdup(mem_ctx, "");
4274 r->action = DSPRINT_UNPUBLISH;
4276 if (r->guid == NULL) {
4277 werr = WERR_NOT_ENOUGH_MEMORY;
4285 werr = nt_printer_guid_store(msg_ctx, printer, guid);
4286 if (!W_ERROR_IS_OK(werr)) {
4287 DEBUG(3, ("failed to store printer %s guid\n",
4292 /* [MS-RPRN] section 2.2: must use curly-braced GUIDs */
4293 guidstr = GUID_string2(mem_ctx, &guid);
4294 if (guidstr == NULL) {
4295 werr = WERR_NOT_ENOUGH_MEMORY;
4298 /* Convert GUID string to uppercase otherwise printers
4300 r->guid = talloc_strdup_upper(mem_ctx, guidstr);
4301 r->action = DSPRINT_PUBLISH;
4303 TALLOC_FREE(guidstr);
4305 r->guid = talloc_strdup(mem_ctx, "");
4306 r->action = DSPRINT_UNPUBLISH;
4308 if (r->guid == NULL) {
4309 werr = WERR_NOT_ENOUGH_MEMORY;
4315 talloc_free(tmp_ctx);
4319 /********************************************************************
4320 * construct_printer_info8
4321 * fill a spoolss_PrinterInfo8 struct
4322 ********************************************************************/
4324 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4325 const struct spoolss_PrinterInfo2 *info2,
4326 const char *servername,
4327 struct spoolss_DeviceModeInfo *r,
4331 const char *printername;
4333 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4334 if (!W_ERROR_IS_OK(result)) {
4338 if (info2->devmode != NULL) {
4339 result = copy_devicemode(mem_ctx,
4342 if (!W_ERROR_IS_OK(result)) {
4345 } else if (lp_default_devmode(snum)) {
4346 result = spoolss_create_default_devmode(mem_ctx,
4349 if (!W_ERROR_IS_OK(result)) {
4354 DEBUG(8,("Returning NULL Devicemode!\n"));
4357 compose_devicemode_devicename(r->devmode, printername);
4362 /********************************************************************
4363 Spoolss_enumprinters.
4364 ********************************************************************/
4366 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4367 const struct auth_session_info *session_info,
4368 struct messaging_context *msg_ctx,
4369 const char *servername,
4372 union spoolss_PrinterInfo **info_p,
4377 union spoolss_PrinterInfo *info = NULL;
4379 WERROR result = WERR_OK;
4380 struct dcerpc_binding_handle *b = NULL;
4381 TALLOC_CTX *tmp_ctx = NULL;
4383 tmp_ctx = talloc_new(mem_ctx);
4385 return WERR_NOT_ENOUGH_MEMORY;
4389 * printer shares are updated on client enumeration. The background
4390 * printer process updates printer_list.tdb at regular intervals.
4393 delete_and_reload_printers(server_event_context(), msg_ctx);
4396 n_services = lp_numservices();
4400 for (snum = 0; snum < n_services; snum++) {
4402 const char *printer;
4403 struct spoolss_PrinterInfo2 *info2;
4405 if (!snum_is_shared_printer(snum)) {
4409 printer = lp_const_servicename(snum);
4411 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4415 result = winreg_printer_binding_handle(tmp_ctx,
4419 if (!W_ERROR_IS_OK(result)) {
4424 result = winreg_create_printer(tmp_ctx, b,
4426 if (!W_ERROR_IS_OK(result)) {
4430 info = talloc_realloc(tmp_ctx, info,
4431 union spoolss_PrinterInfo,
4434 result = WERR_NOT_ENOUGH_MEMORY;
4438 result = winreg_get_printer(tmp_ctx, b,
4440 if (!W_ERROR_IS_OK(result)) {
4446 result = construct_printer_info0(info, session_info,
4449 &info[count].info0, snum);
4452 result = construct_printer_info1(info, info2, flags,
4454 &info[count].info1, snum);
4457 result = construct_printer_info2(info, msg_ctx, info2,
4459 &info[count].info2, snum);
4462 result = construct_printer_info4(info, info2,
4464 &info[count].info4, snum);
4467 result = construct_printer_info5(info, info2,
4469 &info[count].info5, snum);
4473 result = WERR_INVALID_LEVEL;
4477 if (!W_ERROR_IS_OK(result)) {
4485 if (W_ERROR_IS_OK(result)) {
4486 *info_p = talloc_move(mem_ctx, &info);
4490 talloc_free(tmp_ctx);
4495 /********************************************************************
4496 * handle enumeration of printers at level 0
4497 ********************************************************************/
4499 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4500 const struct auth_session_info *session_info,
4501 struct messaging_context *msg_ctx,
4503 const char *servername,
4504 union spoolss_PrinterInfo **info,
4507 DEBUG(4,("enum_all_printers_info_0\n"));
4509 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4510 servername, 0, flags, info, count);
4514 /********************************************************************
4515 ********************************************************************/
4517 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4518 const struct auth_session_info *session_info,
4519 struct messaging_context *msg_ctx,
4520 const char *servername,
4522 union spoolss_PrinterInfo **info,
4525 DEBUG(4,("enum_all_printers_info_1\n"));
4527 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4528 servername, 1, flags, info, count);
4531 /********************************************************************
4532 enum_all_printers_info_1_local.
4533 *********************************************************************/
4535 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4536 const struct auth_session_info *session_info,
4537 struct messaging_context *msg_ctx,
4538 const char *servername,
4539 union spoolss_PrinterInfo **info,
4542 DEBUG(4,("enum_all_printers_info_1_local\n"));
4544 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4545 servername, PRINTER_ENUM_ICON8, info, count);
4548 /********************************************************************
4549 enum_all_printers_info_1_name.
4550 *********************************************************************/
4552 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4553 const struct auth_session_info *session_info,
4554 struct messaging_context *msg_ctx,
4555 const char *servername,
4556 union spoolss_PrinterInfo **info,
4559 const char *s = servername;
4561 DEBUG(4,("enum_all_printers_info_1_name\n"));
4563 if (servername != NULL &&
4564 (servername[0] == '\\') && (servername[1] == '\\')) {
4568 if (!is_myname_or_ipaddr(s)) {
4569 return WERR_INVALID_NAME;
4572 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4573 servername, PRINTER_ENUM_ICON8, info, count);
4576 /********************************************************************
4577 enum_all_printers_info_1_network.
4578 *********************************************************************/
4580 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4581 const struct auth_session_info *session_info,
4582 struct messaging_context *msg_ctx,
4583 const char *servername,
4584 union spoolss_PrinterInfo **info,
4587 const char *s = servername;
4589 DEBUG(4,("enum_all_printers_info_1_network\n"));
4591 /* If we respond to a enum_printers level 1 on our name with flags
4592 set to PRINTER_ENUM_REMOTE with a list of printers then these
4593 printers incorrectly appear in the APW browse list.
4594 Specifically the printers for the server appear at the workgroup
4595 level where all the other servers in the domain are
4596 listed. Windows responds to this call with a
4597 WERR_CAN_NOT_COMPLETE so we should do the same. */
4599 if (servername != NULL &&
4600 (servername[0] == '\\') && (servername[1] == '\\')) {
4604 if (is_myname_or_ipaddr(s)) {
4605 return WERR_CAN_NOT_COMPLETE;
4608 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4609 servername, PRINTER_ENUM_NAME, info, count);
4612 /********************************************************************
4613 * api_spoolss_enumprinters
4615 * called from api_spoolss_enumprinters (see this to understand)
4616 ********************************************************************/
4618 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4619 const struct auth_session_info *session_info,
4620 struct messaging_context *msg_ctx,
4621 const char *servername,
4622 union spoolss_PrinterInfo **info,
4625 DEBUG(4,("enum_all_printers_info_2\n"));
4627 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4628 servername, 2, 0, info, count);
4631 /********************************************************************
4632 * handle enumeration of printers at level 1
4633 ********************************************************************/
4635 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4636 const struct auth_session_info *session_info,
4637 struct messaging_context *msg_ctx,
4639 const char *servername,
4640 union spoolss_PrinterInfo **info,
4643 /* Not all the flags are equals */
4645 if (flags & PRINTER_ENUM_LOCAL) {
4646 return enum_all_printers_info_1_local(mem_ctx, session_info,
4647 msg_ctx, servername, info, count);
4650 if (flags & PRINTER_ENUM_NAME) {
4651 return enum_all_printers_info_1_name(mem_ctx, session_info,
4652 msg_ctx, servername, info,
4656 if (flags & PRINTER_ENUM_NETWORK) {
4657 return enum_all_printers_info_1_network(mem_ctx, session_info,
4658 msg_ctx, servername, info,
4662 return WERR_OK; /* NT4sp5 does that */
4665 /********************************************************************
4666 * handle enumeration of printers at level 2
4667 ********************************************************************/
4669 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4670 const struct auth_session_info *session_info,
4671 struct messaging_context *msg_ctx,
4673 const char *servername,
4674 union spoolss_PrinterInfo **info,
4677 if (flags & PRINTER_ENUM_LOCAL) {
4679 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4684 if (flags & PRINTER_ENUM_NAME) {
4685 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4686 return WERR_INVALID_NAME;
4689 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4694 if (flags & PRINTER_ENUM_REMOTE) {
4695 return WERR_INVALID_LEVEL;
4701 /********************************************************************
4702 * handle enumeration of printers at level 4
4703 ********************************************************************/
4705 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4706 const struct auth_session_info *session_info,
4707 struct messaging_context *msg_ctx,
4709 const char *servername,
4710 union spoolss_PrinterInfo **info,
4713 DEBUG(4,("enum_all_printers_info_4\n"));
4715 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4716 servername, 4, flags, info, count);
4720 /********************************************************************
4721 * handle enumeration of printers at level 5
4722 ********************************************************************/
4724 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4725 const struct auth_session_info *session_info,
4726 struct messaging_context *msg_ctx,
4728 const char *servername,
4729 union spoolss_PrinterInfo **info,
4732 DEBUG(4,("enum_all_printers_info_5\n"));
4734 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4735 servername, 5, flags, info, count);
4738 /****************************************************************
4739 _spoolss_EnumPrinters
4740 ****************************************************************/
4742 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4743 struct spoolss_EnumPrinters *r)
4745 const struct auth_session_info *session_info = get_session_info_system();
4748 /* that's an [in out] buffer */
4750 if (!r->in.buffer && (r->in.offered != 0)) {
4751 return WERR_INVALID_PARAMETER;
4754 DEBUG(4,("_spoolss_EnumPrinters\n"));
4758 *r->out.info = NULL;
4762 * flags==PRINTER_ENUM_NAME
4763 * if name=="" then enumerates all printers
4764 * if name!="" then enumerate the printer
4765 * flags==PRINTER_ENUM_REMOTE
4766 * name is NULL, enumerate printers
4767 * Level 2: name!="" enumerates printers, name can't be NULL
4768 * Level 3: doesn't exist
4769 * Level 4: does a local registry lookup
4770 * Level 5: same as Level 2
4773 if (r->in.server && r->in.server[0] == '\0') {
4774 r->in.server = NULL;
4777 switch (r->in.level) {
4779 result = enumprinters_level0(p->mem_ctx, session_info,
4780 p->msg_ctx, r->in.flags,
4782 r->out.info, r->out.count);
4785 result = enumprinters_level1(p->mem_ctx, session_info,
4786 p->msg_ctx, r->in.flags,
4788 r->out.info, r->out.count);
4791 result = enumprinters_level2(p->mem_ctx, session_info,
4792 p->msg_ctx, r->in.flags,
4794 r->out.info, r->out.count);
4797 result = enumprinters_level4(p->mem_ctx, session_info,
4798 p->msg_ctx, r->in.flags,
4800 r->out.info, r->out.count);
4803 result = enumprinters_level5(p->mem_ctx, session_info,
4804 p->msg_ctx, r->in.flags,
4806 r->out.info, r->out.count);
4809 return WERR_INVALID_LEVEL;
4812 if (!W_ERROR_IS_OK(result)) {
4816 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4817 spoolss_EnumPrinters,
4818 *r->out.info, r->in.level,
4820 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4821 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4823 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4826 /****************************************************************
4828 ****************************************************************/
4830 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4831 struct spoolss_GetPrinter *r)
4833 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4834 struct spoolss_PrinterInfo2 *info2 = NULL;
4835 WERROR result = WERR_OK;
4838 /* that's an [in out] buffer */
4840 if (!r->in.buffer && (r->in.offered != 0)) {
4841 result = WERR_INVALID_PARAMETER;
4847 if (Printer == NULL) {
4848 result = WERR_INVALID_HANDLE;
4852 if (Printer->printer_type == SPLHND_SERVER) {
4854 struct dcerpc_binding_handle *b;
4856 if (r->in.level != 3) {
4857 result = WERR_INVALID_LEVEL;
4861 result = winreg_printer_binding_handle(p->mem_ctx,
4862 get_session_info_system(),
4865 if (!W_ERROR_IS_OK(result)) {
4869 result = winreg_get_printserver_secdesc(p->mem_ctx,
4871 &r->out.info->info3.secdesc);
4872 if (!W_ERROR_IS_OK(result)) {
4879 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4880 result = WERR_INVALID_HANDLE;
4884 result = winreg_get_printer_internal(p->mem_ctx,
4885 get_session_info_system(),
4887 lp_const_servicename(snum),
4889 if (!W_ERROR_IS_OK(result)) {
4893 switch (r->in.level) {
4895 result = construct_printer_info0(p->mem_ctx,
4896 get_session_info_system(),
4899 Printer->servername,
4900 &r->out.info->info0,
4904 result = construct_printer_info1(p->mem_ctx, info2,
4906 Printer->servername,
4907 &r->out.info->info1, snum);
4910 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4911 Printer->servername,
4912 &r->out.info->info2, snum);
4915 result = construct_printer_info3(p->mem_ctx, info2,
4916 Printer->servername,
4917 &r->out.info->info3, snum);
4920 result = construct_printer_info4(p->mem_ctx, info2,
4921 Printer->servername,
4922 &r->out.info->info4, snum);
4925 result = construct_printer_info5(p->mem_ctx, info2,
4926 Printer->servername,
4927 &r->out.info->info5, snum);
4930 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4931 Printer->servername,
4932 &r->out.info->info6, snum);
4935 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4936 Printer->servername,
4937 &r->out.info->info7, snum);
4940 result = construct_printer_info8(p->mem_ctx, info2,
4941 Printer->servername,
4942 &r->out.info->info8, snum);
4945 result = WERR_INVALID_LEVEL;
4950 if (!W_ERROR_IS_OK(result)) {
4951 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4952 r->in.level, win_errstr(result)));
4956 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4957 r->out.info, r->in.level);
4958 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4960 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4963 TALLOC_FREE(r->out.info);
4967 /********************************************************************
4968 ********************************************************************/
4970 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4972 if (in && strlen(in)) { \
4973 out = talloc_strdup(mem_ctx, in); \
4975 out = talloc_strdup(mem_ctx, ""); \
4977 W_ERROR_HAVE_NO_MEMORY(out); \
4980 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4982 if (in && strlen(in)) { \
4983 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4985 out = talloc_strdup(mem_ctx, ""); \
4987 W_ERROR_HAVE_NO_MEMORY(out); \
4990 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4991 const char **string_array,
4992 const char ***presult,
4993 const char *cservername,
4998 size_t num_strings = 0;
4999 const char **array = NULL;
5001 if (string_array == NULL) {
5002 return WERR_INVALID_PARAMETER;
5005 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
5006 const char *str = NULL;
5008 if (cservername == NULL || arch == NULL) {
5009 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
5011 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
5014 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
5016 return WERR_NOT_ENOUGH_MEMORY;
5021 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
5022 &array, &num_strings);
5025 if (presult != NULL) {
5034 /********************************************************************
5035 * fill a spoolss_DriverInfo1 struct
5036 ********************************************************************/
5038 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
5039 struct spoolss_DriverInfo1 *r,
5040 const struct spoolss_DriverInfo8 *driver,
5041 const char *servername)
5043 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5044 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5049 /********************************************************************
5050 * fill a spoolss_DriverInfo2 struct
5051 ********************************************************************/
5053 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
5054 struct spoolss_DriverInfo2 *r,
5055 const struct spoolss_DriverInfo8 *driver,
5056 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,
5089 /********************************************************************
5090 * fill a spoolss_DriverInfo3 struct
5091 ********************************************************************/
5093 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
5094 struct spoolss_DriverInfo3 *r,
5095 const struct spoolss_DriverInfo8 *driver,
5096 const char *servername)
5098 const char *cservername = canon_servername(servername);
5100 r->version = driver->version;
5102 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5103 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5104 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5105 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5107 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5108 driver->architecture,
5110 driver->driver_path,
5113 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5114 driver->architecture,
5119 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5120 driver->architecture,
5122 driver->config_file,
5125 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5126 driver->architecture,
5131 FILL_DRIVER_STRING(mem_ctx,
5132 driver->monitor_name,
5135 FILL_DRIVER_STRING(mem_ctx,
5136 driver->default_datatype,
5137 r->default_datatype);
5139 return string_array_from_driver_info(mem_ctx,
5140 driver->dependent_files,
5141 &r->dependent_files,
5143 driver->architecture,
5147 /********************************************************************
5148 * fill a spoolss_DriverInfo4 struct
5149 ********************************************************************/
5151 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5152 struct spoolss_DriverInfo4 *r,
5153 const struct spoolss_DriverInfo8 *driver,
5154 const char *servername)
5156 const char *cservername = canon_servername(servername);
5159 r->version = driver->version;
5161 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5162 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5163 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5164 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5166 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5167 driver->architecture,
5169 driver->driver_path,
5172 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5173 driver->architecture,
5178 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5179 driver->architecture,
5181 driver->config_file,
5184 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5185 driver->architecture,
5190 result = string_array_from_driver_info(mem_ctx,
5191 driver->dependent_files,
5192 &r->dependent_files,
5194 driver->architecture,
5196 if (!W_ERROR_IS_OK(result)) {
5200 FILL_DRIVER_STRING(mem_ctx,
5201 driver->monitor_name,
5204 FILL_DRIVER_STRING(mem_ctx,
5205 driver->default_datatype,
5206 r->default_datatype);
5209 result = string_array_from_driver_info(mem_ctx,
5210 driver->previous_names,
5217 /********************************************************************
5218 * fill a spoolss_DriverInfo5 struct
5219 ********************************************************************/
5221 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5222 struct spoolss_DriverInfo5 *r,
5223 const struct spoolss_DriverInfo8 *driver,
5224 const char *servername)
5226 const char *cservername = canon_servername(servername);
5228 r->version = driver->version;
5230 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5231 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5232 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5233 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5235 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5236 driver->architecture,
5238 driver->driver_path,
5241 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5242 driver->architecture,
5247 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5248 driver->architecture,
5250 driver->config_file,
5253 r->driver_attributes = 0;
5254 r->config_version = 0;
5255 r->driver_version = 0;
5259 /********************************************************************
5260 * fill a spoolss_DriverInfo6 struct
5261 ********************************************************************/
5263 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5264 struct spoolss_DriverInfo6 *r,
5265 const struct spoolss_DriverInfo8 *driver,
5266 const char *servername)
5268 const char *cservername = canon_servername(servername);
5271 r->version = driver->version;
5273 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5274 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5275 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5276 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5278 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5279 driver->architecture,
5281 driver->driver_path,
5284 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5285 driver->architecture,
5290 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5291 driver->architecture,
5293 driver->config_file,
5296 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5297 driver->architecture,
5302 FILL_DRIVER_STRING(mem_ctx,
5303 driver->monitor_name,
5306 FILL_DRIVER_STRING(mem_ctx,
5307 driver->default_datatype,
5308 r->default_datatype);
5310 result = string_array_from_driver_info(mem_ctx,
5311 driver->dependent_files,
5312 &r->dependent_files,
5314 driver->architecture,
5316 if (!W_ERROR_IS_OK(result)) {
5320 result = string_array_from_driver_info(mem_ctx,
5321 driver->previous_names,
5324 if (!W_ERROR_IS_OK(result)) {
5328 r->driver_date = driver->driver_date;
5329 r->driver_version = driver->driver_version;
5331 FILL_DRIVER_STRING(mem_ctx,
5332 driver->manufacturer_name,
5333 r->manufacturer_name);
5334 FILL_DRIVER_STRING(mem_ctx,
5335 driver->manufacturer_url,
5336 r->manufacturer_url);
5337 FILL_DRIVER_STRING(mem_ctx,
5338 driver->hardware_id,
5340 FILL_DRIVER_STRING(mem_ctx,
5347 /********************************************************************
5348 * fill a spoolss_DriverInfo8 struct
5349 ********************************************************************/
5351 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5352 struct spoolss_DriverInfo8 *r,
5353 const struct spoolss_DriverInfo8 *driver,
5354 const char *servername)
5356 const char *cservername = canon_servername(servername);
5359 r->version = driver->version;
5361 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5362 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5363 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5364 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5366 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5367 driver->architecture,
5369 driver->driver_path,
5372 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5373 driver->architecture,
5378 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5379 driver->architecture,
5381 driver->config_file,
5384 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5385 driver->architecture,
5390 FILL_DRIVER_STRING(mem_ctx,
5391 driver->monitor_name,
5394 FILL_DRIVER_STRING(mem_ctx,
5395 driver->default_datatype,
5396 r->default_datatype);
5398 result = string_array_from_driver_info(mem_ctx,
5399 driver->dependent_files,
5400 &r->dependent_files,
5402 driver->architecture,
5404 if (!W_ERROR_IS_OK(result)) {
5408 result = string_array_from_driver_info(mem_ctx,
5409 driver->previous_names,
5412 if (!W_ERROR_IS_OK(result)) {
5416 r->driver_date = driver->driver_date;
5417 r->driver_version = driver->driver_version;
5419 FILL_DRIVER_STRING(mem_ctx,
5420 driver->manufacturer_name,
5421 r->manufacturer_name);
5422 FILL_DRIVER_STRING(mem_ctx,
5423 driver->manufacturer_url,
5424 r->manufacturer_url);
5425 FILL_DRIVER_STRING(mem_ctx,
5426 driver->hardware_id,
5428 FILL_DRIVER_STRING(mem_ctx,
5432 FILL_DRIVER_STRING(mem_ctx,
5433 driver->print_processor,
5434 r->print_processor);
5435 FILL_DRIVER_STRING(mem_ctx,
5436 driver->vendor_setup,
5439 result = string_array_from_driver_info(mem_ctx,
5440 driver->color_profiles,
5443 if (!W_ERROR_IS_OK(result)) {
5447 FILL_DRIVER_STRING(mem_ctx,
5451 r->printer_driver_attributes = driver->printer_driver_attributes;
5453 result = string_array_from_driver_info(mem_ctx,
5454 driver->core_driver_dependencies,
5455 &r->core_driver_dependencies,
5457 if (!W_ERROR_IS_OK(result)) {
5461 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5462 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5467 #if 0 /* disabled until marshalling issues are resolved - gd */
5468 /********************************************************************
5469 ********************************************************************/
5471 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5472 struct spoolss_DriverFileInfo *r,
5473 const char *cservername,
5474 const char *file_name,
5475 enum spoolss_DriverFileType file_type,
5476 uint32_t file_version)
5478 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5479 cservername, file_name);
5480 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5481 r->file_type = file_type;
5482 r->file_version = file_version;
5487 /********************************************************************
5488 ********************************************************************/
5490 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5491 const struct spoolss_DriverInfo8 *driver,
5492 const char *cservername,
5493 struct spoolss_DriverFileInfo **info_p,
5496 struct spoolss_DriverFileInfo *info = NULL;
5504 if (strlen(driver->driver_path)) {
5505 info = talloc_realloc(mem_ctx, info,
5506 struct spoolss_DriverFileInfo,
5508 W_ERROR_HAVE_NO_MEMORY(info);
5509 result = fill_spoolss_DriverFileInfo(info,
5512 driver->driver_path,
5513 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5515 W_ERROR_NOT_OK_RETURN(result);
5519 if (strlen(driver->config_file)) {
5520 info = talloc_realloc(mem_ctx, info,
5521 struct spoolss_DriverFileInfo,
5523 W_ERROR_HAVE_NO_MEMORY(info);
5524 result = fill_spoolss_DriverFileInfo(info,
5527 driver->config_file,
5528 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5530 W_ERROR_NOT_OK_RETURN(result);
5534 if (strlen(driver->data_file)) {
5535 info = talloc_realloc(mem_ctx, info,
5536 struct spoolss_DriverFileInfo,
5538 W_ERROR_HAVE_NO_MEMORY(info);
5539 result = fill_spoolss_DriverFileInfo(info,
5543 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5545 W_ERROR_NOT_OK_RETURN(result);
5549 if (strlen(driver->help_file)) {
5550 info = talloc_realloc(mem_ctx, info,
5551 struct spoolss_DriverFileInfo,
5553 W_ERROR_HAVE_NO_MEMORY(info);
5554 result = fill_spoolss_DriverFileInfo(info,
5558 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5560 W_ERROR_NOT_OK_RETURN(result);
5564 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5565 info = talloc_realloc(mem_ctx, info,
5566 struct spoolss_DriverFileInfo,
5568 W_ERROR_HAVE_NO_MEMORY(info);
5569 result = fill_spoolss_DriverFileInfo(info,
5572 driver->dependent_files[i],
5573 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5575 W_ERROR_NOT_OK_RETURN(result);
5585 /********************************************************************
5586 * fill a spoolss_DriverInfo101 struct
5587 ********************************************************************/
5589 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5590 struct spoolss_DriverInfo101 *r,
5591 const struct spoolss_DriverInfo8 *driver,
5592 const char *servername)
5594 const char *cservername = canon_servername(servername);
5597 r->version = driver->version;
5599 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5600 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5601 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5602 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5604 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5608 if (!W_ERROR_IS_OK(result)) {
5612 FILL_DRIVER_STRING(mem_ctx,
5613 driver->monitor_name,
5616 FILL_DRIVER_STRING(mem_ctx,
5617 driver->default_datatype,
5618 r->default_datatype);
5620 result = string_array_from_driver_info(mem_ctx,
5621 driver->previous_names,
5624 if (!W_ERROR_IS_OK(result)) {
5628 r->driver_date = driver->driver_date;
5629 r->driver_version = driver->driver_version;
5631 FILL_DRIVER_STRING(mem_ctx,
5632 driver->manufacturer_name,
5633 r->manufacturer_name);
5634 FILL_DRIVER_STRING(mem_ctx,
5635 driver->manufacturer_url,
5636 r->manufacturer_url);
5637 FILL_DRIVER_STRING(mem_ctx,
5638 driver->hardware_id,
5640 FILL_DRIVER_STRING(mem_ctx,
5647 /********************************************************************
5648 ********************************************************************/
5650 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5651 const struct auth_session_info *session_info,
5652 struct messaging_context *msg_ctx,
5654 union spoolss_DriverInfo *r,
5656 const char *servername,
5657 const char *architecture,
5660 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5661 struct spoolss_DriverInfo8 *driver;
5663 struct dcerpc_binding_handle *b;
5664 TALLOC_CTX *tmp_ctx = NULL;
5667 return WERR_INVALID_LEVEL;
5670 tmp_ctx = talloc_new(mem_ctx);
5672 return WERR_NOT_ENOUGH_MEMORY;
5675 result = winreg_printer_binding_handle(tmp_ctx,
5679 if (!W_ERROR_IS_OK(result)) {
5683 result = winreg_get_printer(tmp_ctx, b,
5684 lp_const_servicename(snum),
5686 if (!W_ERROR_IS_OK(result)) {
5687 DBG_ERR("Failed to get printer info2 for [%s]: %s\n",
5688 lp_const_servicename(snum), win_errstr(result));
5689 result = WERR_INVALID_PRINTER_NAME;
5693 if (pinfo2->drivername == NULL || pinfo2->drivername[0] == '\0') {
5694 return WERR_UNKNOWN_PRINTER_DRIVER;
5697 DBG_INFO("Construct printer driver [%s] for [%s]\n",
5701 result = winreg_get_driver(tmp_ctx, b,
5703 pinfo2->drivername, version, &driver);
5705 DBG_INFO("winreg_get_driver() status: %s\n",
5706 win_errstr(result));
5708 if (!W_ERROR_IS_OK(result)) {
5710 * Is this a W2k client ?
5714 result = WERR_UNKNOWN_PRINTER_DRIVER;
5718 /* Yes - try again with a WinNT driver. */
5720 result = winreg_get_driver(tmp_ctx, b,
5724 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5725 win_errstr(result)));
5726 if (!W_ERROR_IS_OK(result)) {
5727 result = WERR_UNKNOWN_PRINTER_DRIVER;
5732 /* these are allocated on mem_ctx and not tmp_ctx because they are
5733 * the 'return value' and need to utlive this call */
5736 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5739 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5742 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5745 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5748 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5751 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5754 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5756 #if 0 /* disabled until marshalling issues are resolved - gd */
5758 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5762 result = WERR_INVALID_LEVEL;
5767 talloc_free(tmp_ctx);
5771 /****************************************************************
5772 _spoolss_GetPrinterDriver2
5773 ****************************************************************/
5775 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5776 struct spoolss_GetPrinterDriver2 *r)
5778 struct printer_handle *printer;
5780 uint32_t version = r->in.client_major_version;
5784 /* that's an [in out] buffer */
5786 if (!r->in.buffer && (r->in.offered != 0)) {
5787 result = WERR_INVALID_PARAMETER;
5791 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5793 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5794 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5795 result = WERR_INVALID_PRINTER_NAME;
5800 *r->out.server_major_version = 0;
5801 *r->out.server_minor_version = 0;
5803 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5804 result = WERR_INVALID_HANDLE;
5808 if (r->in.client_major_version == SPOOLSS_DRIVER_VERSION_2012) {
5809 DEBUG(3,("_spoolss_GetPrinterDriver2: v4 driver requested, "
5810 "downgrading to v3\n"));
5811 version = SPOOLSS_DRIVER_VERSION_200X;
5814 result = construct_printer_driver_info_level(p->mem_ctx,
5815 get_session_info_system(),
5817 r->in.level, r->out.info,
5818 snum, printer->servername,
5821 if (!W_ERROR_IS_OK(result)) {
5825 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5826 r->out.info, r->in.level);
5827 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5829 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5832 TALLOC_FREE(r->out.info);
5837 /****************************************************************
5838 _spoolss_StartPagePrinter
5839 ****************************************************************/
5841 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5842 struct spoolss_StartPagePrinter *r)
5844 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5847 DEBUG(3,("_spoolss_StartPagePrinter: "
5848 "Error in startpageprinter printer handle\n"));
5849 return WERR_INVALID_HANDLE;
5852 Printer->page_started = true;
5856 /****************************************************************
5857 _spoolss_EndPagePrinter
5858 ****************************************************************/
5860 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5861 struct spoolss_EndPagePrinter *r)
5865 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5868 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5869 OUR_HANDLE(r->in.handle)));
5870 return WERR_INVALID_HANDLE;
5873 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5874 return WERR_INVALID_HANDLE;
5876 Printer->page_started = false;
5877 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5882 /****************************************************************
5883 _spoolss_StartDocPrinter
5884 ****************************************************************/
5886 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5887 struct spoolss_StartDocPrinter *r)
5889 struct spoolss_DocumentInfo1 *info_1;
5891 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5897 DEBUG(2,("_spoolss_StartDocPrinter: "
5898 "Invalid handle (%s:%u:%u)\n",
5899 OUR_HANDLE(r->in.handle)));
5900 return WERR_INVALID_HANDLE;
5903 if (Printer->jobid) {
5904 DEBUG(2, ("_spoolss_StartDocPrinter: "
5905 "StartDocPrinter called twice! "
5906 "(existing jobid = %d)\n", Printer->jobid));
5907 return WERR_INVALID_HANDLE;
5910 if (r->in.info_ctr->level != 1) {
5911 return WERR_INVALID_LEVEL;
5914 info_1 = r->in.info_ctr->info.info1;
5917 * a nice thing with NT is it doesn't listen to what you tell it.
5918 * when asked to send _only_ RAW datas, it tries to send datas
5921 * So I add checks like in NT Server ...
5924 if (info_1->datatype) {
5926 * The v4 driver model used in Windows 8 declares print jobs
5927 * intended to bypass the XPS processing layer by setting
5928 * datatype to "XPS_PASS" instead of "RAW".
5930 if ((strcmp(info_1->datatype, "RAW") != 0)
5931 && (strcmp(info_1->datatype, "XPS_PASS") != 0)) {
5933 return WERR_INVALID_DATATYPE;
5937 /* get the share number of the printer */
5938 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5939 return WERR_INVALID_HANDLE;
5942 rc = get_remote_hostname(p->remote_address,
5946 return WERR_NOT_ENOUGH_MEMORY;
5948 if (strequal(rhost,"UNKNOWN")) {
5949 rhost = tsocket_address_inet_addr_string(p->remote_address,
5951 if (rhost == NULL) {
5952 return WERR_NOT_ENOUGH_MEMORY;
5956 werr = print_job_start(p->session_info,
5960 info_1->document_name,
5961 info_1->output_file,
5965 /* An error occurred in print_job_start() so return an appropriate
5968 if (!W_ERROR_IS_OK(werr)) {
5972 Printer->document_started = true;
5973 *r->out.job_id = Printer->jobid;
5978 /****************************************************************
5979 _spoolss_EndDocPrinter
5980 ****************************************************************/
5982 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5983 struct spoolss_EndDocPrinter *r)
5985 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5990 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5991 OUR_HANDLE(r->in.handle)));
5992 return WERR_INVALID_HANDLE;
5995 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5996 return WERR_INVALID_HANDLE;
5999 Printer->document_started = false;
6000 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
6001 if (!NT_STATUS_IS_OK(status)) {
6002 DEBUG(2, ("_spoolss_EndDocPrinter: "
6003 "print_job_end failed [%s]\n",
6004 nt_errstr(status)));
6008 return ntstatus_to_werror(status);
6011 /****************************************************************
6012 _spoolss_WritePrinter
6013 ****************************************************************/
6015 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
6016 struct spoolss_WritePrinter *r)
6018 ssize_t buffer_written;
6020 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6023 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
6024 OUR_HANDLE(r->in.handle)));
6025 *r->out.num_written = r->in._data_size;
6026 return WERR_INVALID_HANDLE;
6029 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6030 return WERR_INVALID_HANDLE;
6032 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
6033 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
6034 snum, Printer->jobid,
6035 (const char *)r->in.data.data,
6036 (size_t)r->in._data_size);
6037 if (buffer_written == (ssize_t)-1) {
6038 *r->out.num_written = 0;
6039 if (errno == ENOSPC)
6040 return WERR_NO_SPOOL_SPACE;
6042 return WERR_ACCESS_DENIED;
6045 *r->out.num_written = r->in._data_size;
6050 /********************************************************************
6051 * api_spoolss_getprinter
6052 * called from the spoolss dispatcher
6054 ********************************************************************/
6056 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
6057 struct pipes_struct *p)
6059 const struct auth_session_info *session_info = p->session_info;
6061 WERROR errcode = WERR_INVALID_FUNCTION;
6062 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6065 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
6066 OUR_HANDLE(handle)));
6067 return WERR_INVALID_HANDLE;
6070 if (!get_printer_snum(p, handle, &snum, NULL))
6071 return WERR_INVALID_HANDLE;
6074 case SPOOLSS_PRINTER_CONTROL_PAUSE:
6075 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
6077 case SPOOLSS_PRINTER_CONTROL_RESUME:
6078 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
6079 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
6081 case SPOOLSS_PRINTER_CONTROL_PURGE:
6082 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
6085 return WERR_INVALID_LEVEL;
6092 /****************************************************************
6093 _spoolss_AbortPrinter
6094 * From MSDN: "Deletes printer's spool file if printer is configured
6096 ****************************************************************/
6098 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
6099 struct spoolss_AbortPrinter *r)
6101 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6103 WERROR errcode = WERR_OK;
6106 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
6107 OUR_HANDLE(r->in.handle)));
6108 return WERR_INVALID_HANDLE;
6111 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
6112 return WERR_INVALID_HANDLE;
6114 if (!Printer->document_started) {
6115 return WERR_SPL_NO_STARTDOC;
6118 errcode = print_job_delete(p->session_info,
6126 /********************************************************************
6127 * called by spoolss_api_setprinter
6128 * when updating a printer description
6129 ********************************************************************/
6131 static WERROR update_printer_sec(struct policy_handle *handle,
6132 struct pipes_struct *p,
6133 struct sec_desc_buf *secdesc_ctr)
6135 struct spoolss_security_descriptor *new_secdesc = NULL;
6136 struct spoolss_security_descriptor *old_secdesc = NULL;
6137 const char *printer = NULL;
6140 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6141 struct dcerpc_binding_handle *b;
6142 TALLOC_CTX *tmp_ctx = NULL;
6146 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6147 OUR_HANDLE(handle)));
6149 result = WERR_INVALID_HANDLE;
6153 if (secdesc_ctr == NULL) {
6154 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6155 result = WERR_INVALID_PARAMETER;
6159 switch (Printer->printer_type) {
6162 case SPLHND_PRINTER:
6163 if (!get_printer_snum(p, handle, &snum, NULL)) {
6164 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6165 OUR_HANDLE(handle)));
6166 result = WERR_INVALID_HANDLE;
6169 printer = lp_const_servicename(snum);
6175 /* Check the user has permissions to change the security
6176 descriptor. By experimentation with two NT machines, the user
6177 requires Full Access to the printer to change security
6180 switch (Printer->printer_type) {
6182 ok = Printer->access_granted == SERVER_ACCESS_ADMINISTER;
6184 case SPLHND_PRINTER:
6185 ok = Printer->access_granted == PRINTER_ACCESS_ADMINISTER;
6192 DEBUG(4,("update_printer_sec: updated denied by printer permissions "
6193 "(access_granted: 0x%08x)\n", Printer->access_granted));
6194 result = WERR_ACCESS_DENIED;
6198 tmp_ctx = talloc_new(p->mem_ctx);
6200 return WERR_NOT_ENOUGH_MEMORY;
6203 result = winreg_printer_binding_handle(tmp_ctx,
6204 get_session_info_system(),
6207 if (!W_ERROR_IS_OK(result)) {
6211 /* NT seems to like setting the security descriptor even though
6212 nothing may have actually changed. */
6214 if (printer != NULL) {
6215 result = winreg_get_printer_secdesc(tmp_ctx, b,
6219 result = winreg_get_printserver_secdesc(tmp_ctx, b,
6222 if (!W_ERROR_IS_OK(result)) {
6223 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6224 result = WERR_INVALID_HANDLE;
6228 if (DEBUGLEVEL >= 10) {
6229 struct security_acl *the_acl;
6232 the_acl = old_secdesc->dacl;
6233 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6234 printer, the_acl->num_aces));
6236 for (i = 0; i < the_acl->num_aces; i++) {
6237 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6238 &the_acl->aces[i].trustee),
6239 the_acl->aces[i].access_mask));
6242 the_acl = secdesc_ctr->sd->dacl;
6245 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6246 printer, the_acl->num_aces));
6248 for (i = 0; i < the_acl->num_aces; i++) {
6249 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6250 &the_acl->aces[i].trustee),
6251 the_acl->aces[i].access_mask));
6254 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6258 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6259 if (new_secdesc == NULL) {
6260 result = WERR_NOT_ENOUGH_MEMORY;
6264 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6269 if (printer != NULL) {
6270 result = winreg_set_printer_secdesc(tmp_ctx, b,
6274 result = winreg_set_printserver_secdesc(tmp_ctx, b,
6279 talloc_free(tmp_ctx);
6283 /********************************************************************
6284 Canonicalize printer info from a client
6285 ********************************************************************/
6287 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6288 struct spoolss_SetPrinterInfo2 *info2,
6291 fstring printername;
6294 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6295 "portname=%s drivername=%s comment=%s location=%s\n",
6296 info2->servername, info2->printername, info2->sharename,
6297 info2->portname, info2->drivername, info2->comment,
6300 /* we force some elements to "correct" values */
6301 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6302 if (info2->servername == NULL) {
6305 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6306 if (info2->sharename == NULL) {
6310 /* check to see if we allow printername != sharename */
6311 if (lp_force_printername(snum)) {
6312 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6313 lp_netbios_name(), info2->sharename);
6315 /* make sure printername is in \\server\printername format */
6316 fstrcpy(printername, info2->printername);
6318 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6319 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6323 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6324 lp_netbios_name(), p);
6326 if (info2->printername == NULL) {
6330 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6331 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6336 /****************************************************************************
6337 ****************************************************************************/
6339 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6341 char *cmd = lp_addport_command(talloc_tos());
6342 char *command = NULL;
6344 bool is_print_op = false;
6347 return WERR_ACCESS_DENIED;
6350 command = talloc_asprintf(ctx,
6351 "%s \"%s\" \"%s\"", cmd, portname, uri );
6353 return WERR_NOT_ENOUGH_MEMORY;
6357 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6359 DEBUG(10,("Running [%s]\n", command));
6361 /********* BEGIN SePrintOperatorPrivilege **********/
6366 ret = smbrun(command, NULL, NULL);
6371 /********* END SePrintOperatorPrivilege **********/
6373 DEBUGADD(10,("returned [%d]\n", ret));
6375 TALLOC_FREE(command);
6378 return WERR_ACCESS_DENIED;
6384 /****************************************************************************
6385 ****************************************************************************/
6387 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6391 * As we do not know if we are embedded in the file server process
6392 * or not, we have to pretend that all shares are in use.
6397 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6398 struct spoolss_SetPrinterInfo2 *info2,
6399 const char *remote_machine,
6400 struct messaging_context *msg_ctx)
6402 char *cmd = lp_addprinter_command(talloc_tos());
6404 char *command = NULL;
6408 bool is_print_op = false;
6410 if (!remote_machine) {
6414 command = talloc_asprintf(ctx,
6415 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6416 cmd, info2->printername, info2->sharename,
6417 info2->portname, info2->drivername,
6418 info2->location, info2->comment, remote_machine);
6424 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6426 DEBUG(10,("Running [%s]\n", command));
6428 /********* BEGIN SePrintOperatorPrivilege **********/
6433 ret = smbrun(command, &fd, NULL);
6435 /* Tell everyone we updated smb.conf. */
6436 messaging_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0);
6442 /********* END SePrintOperatorPrivilege **********/
6444 DEBUGADD(10,("returned [%d]\n", ret));
6446 TALLOC_FREE(command);
6454 /* reload our services immediately */
6456 reload_services(NULL, spoolss_conn_snum_used, false);
6460 /* Get lines and convert them back to dos-codepage */
6461 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6462 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6465 /* Set the portname to what the script says the portname should be. */
6466 /* but don't require anything to be return from the script exit a good error code */
6469 /* Set the portname to what the script says the portname should be. */
6470 info2->portname = talloc_strdup(ctx, qlines[0]);
6471 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6474 TALLOC_FREE(qlines);
6478 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6479 const struct auth_session_info *session_info,
6480 struct messaging_context *msg_ctx,
6482 struct spoolss_SetPrinterInfo2 *printer,
6483 struct spoolss_PrinterInfo2 *old_printer)
6485 bool force_update = (old_printer == NULL);
6486 const char *dnsdomname;
6487 const char *longname;
6488 const char *uncname;
6489 const char *spooling;
6491 WERROR result = WERR_OK;
6492 struct dcerpc_binding_handle *b;
6493 TALLOC_CTX *tmp_ctx;
6496 tmp_ctx = talloc_new(mem_ctx);
6498 return WERR_NOT_ENOUGH_MEMORY;
6501 result = winreg_printer_binding_handle(tmp_ctx,
6505 if (!W_ERROR_IS_OK(result)) {
6509 if (printer->drivername != NULL &&
6511 !strequal(printer->drivername, old_printer->drivername))) {
6512 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6514 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6515 result = WERR_INVALID_DATA;
6518 result = winreg_set_printer_dataex(tmp_ctx, b,
6520 SPOOL_DSSPOOLER_KEY,
6521 SPOOL_REG_DRIVERNAME,
6525 if (!W_ERROR_IS_OK(result)) {
6526 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6530 if (!force_update) {
6531 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6532 printer->drivername));
6534 notify_printer_driver(server_event_context(), msg_ctx,
6535 snum, printer->drivername ?
6536 printer->drivername : "");
6540 if (printer->comment != NULL &&
6542 !strequal(printer->comment, old_printer->comment))) {
6543 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6545 DEBUG(0, ("comment data corrupted\n"));
6546 result = WERR_INVALID_DATA;
6549 result = winreg_set_printer_dataex(tmp_ctx, b,
6551 SPOOL_DSSPOOLER_KEY,
6552 SPOOL_REG_DESCRIPTION,
6556 if (!W_ERROR_IS_OK(result)) {
6557 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6561 if (!force_update) {
6562 notify_printer_comment(server_event_context(), msg_ctx,
6563 snum, printer->comment ?
6564 printer->comment : "");
6568 if (printer->sharename != NULL &&
6570 !strequal(printer->sharename, old_printer->sharename))) {
6571 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6573 DEBUG(0, ("sharename data corrupted\n"));
6574 result = WERR_INVALID_DATA;
6577 result = winreg_set_printer_dataex(tmp_ctx, b,
6579 SPOOL_DSSPOOLER_KEY,
6580 SPOOL_REG_PRINTSHARENAME,
6584 if (!W_ERROR_IS_OK(result)) {
6585 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6589 if (!force_update) {
6590 notify_printer_sharename(server_event_context(),
6592 snum, printer->sharename ?
6593 printer->sharename : "");
6596 /* name change, purge any cache entries for the old */
6597 prune_printername_cache();
6600 if (printer->printername != NULL &&
6602 !strequal(printer->printername, old_printer->printername))) {
6605 p = strrchr(printer->printername, '\\' );
6609 p = printer->printername;
6612 ok = push_reg_sz(tmp_ctx, &buffer, p);
6614 DEBUG(0, ("printername data corrupted\n"));
6615 result = WERR_INVALID_DATA;
6618 result = winreg_set_printer_dataex(tmp_ctx, b,
6620 SPOOL_DSSPOOLER_KEY,
6621 SPOOL_REG_PRINTERNAME,
6625 if (!W_ERROR_IS_OK(result)) {
6626 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6630 if (!force_update) {
6631 notify_printer_printername(server_event_context(),
6632 msg_ctx, snum, p ? p : "");
6635 /* name change, purge any cache entries for the old */
6636 prune_printername_cache();
6639 if (printer->portname != NULL &&
6641 !strequal(printer->portname, old_printer->portname))) {
6642 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6644 DEBUG(0, ("portname data corrupted\n"));
6645 result = WERR_INVALID_DATA;
6648 result = winreg_set_printer_dataex(tmp_ctx, b,
6650 SPOOL_DSSPOOLER_KEY,
6655 if (!W_ERROR_IS_OK(result)) {
6656 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6660 if (!force_update) {
6661 notify_printer_port(server_event_context(),
6662 msg_ctx, snum, printer->portname ?
6663 printer->portname : "");
6667 if (printer->location != NULL &&
6669 !strequal(printer->location, old_printer->location))) {
6670 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6672 DEBUG(0, ("location data corrupted\n"));
6673 result = WERR_INVALID_DATA;
6676 result = winreg_set_printer_dataex(tmp_ctx, b,
6678 SPOOL_DSSPOOLER_KEY,
6683 if (!W_ERROR_IS_OK(result)) {
6684 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6688 if (!force_update) {
6689 notify_printer_location(server_event_context(),
6692 printer->location : "");
6696 if (printer->sepfile != NULL &&
6698 !strequal(printer->sepfile, old_printer->sepfile))) {
6699 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6701 DEBUG(0, ("sepfile data corrupted\n"));
6702 result = WERR_INVALID_DATA;
6705 result = winreg_set_printer_dataex(tmp_ctx, b,
6707 SPOOL_DSSPOOLER_KEY,
6708 SPOOL_REG_PRINTSEPARATORFILE,
6712 if (!W_ERROR_IS_OK(result)) {
6713 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6717 if (!force_update) {
6718 notify_printer_sepfile(server_event_context(),
6721 printer->sepfile : "");
6725 if (printer->starttime != 0 &&
6727 printer->starttime != old_printer->starttime)) {
6728 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6729 SIVAL(buffer.data, 0, printer->starttime);
6730 result = winreg_set_printer_dataex(tmp_ctx, b,
6732 SPOOL_DSSPOOLER_KEY,
6733 SPOOL_REG_PRINTSTARTTIME,
6737 if (!W_ERROR_IS_OK(result)) {
6738 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6743 if (printer->untiltime != 0 &&
6745 printer->untiltime != old_printer->untiltime)) {
6746 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6747 SIVAL(buffer.data, 0, printer->untiltime);
6748 result = winreg_set_printer_dataex(tmp_ctx, b,
6750 SPOOL_DSSPOOLER_KEY,
6751 SPOOL_REG_PRINTENDTIME,
6755 if (!W_ERROR_IS_OK(result)) {
6756 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6761 if (force_update || printer->priority != old_printer->priority) {
6762 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6763 SIVAL(buffer.data, 0, printer->priority);
6764 result = winreg_set_printer_dataex(tmp_ctx, b,
6766 SPOOL_DSSPOOLER_KEY,
6771 if (!W_ERROR_IS_OK(result)) {
6772 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6777 if (force_update || printer->attributes != old_printer->attributes) {
6778 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6779 SIVAL(buffer.data, 0, (printer->attributes &
6780 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6781 result = winreg_set_printer_dataex(tmp_ctx, b,
6783 SPOOL_DSSPOOLER_KEY,
6784 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6788 if (!W_ERROR_IS_OK(result)) {
6789 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6793 switch (printer->attributes & 0x3) {
6795 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6798 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6801 spooling = SPOOL_REGVAL_PRINTDIRECT;
6804 spooling = "unknown";
6806 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6808 DEBUG(0, ("printSpooling data corrupted\n"));
6809 result = WERR_INVALID_DATA;
6812 winreg_set_printer_dataex(tmp_ctx, b,
6814 SPOOL_DSSPOOLER_KEY,
6815 SPOOL_REG_PRINTSPOOLING,
6821 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6823 DEBUG(0, ("shortServerName data corrupted\n"));
6824 result = WERR_INVALID_DATA;
6827 result = winreg_set_printer_dataex(tmp_ctx, b,
6829 SPOOL_DSSPOOLER_KEY,
6830 SPOOL_REG_SHORTSERVERNAME,
6834 if (!W_ERROR_IS_OK(result)) {
6835 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6839 dnsdomname = get_mydnsfullname();
6840 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6841 longname = talloc_strdup(tmp_ctx, dnsdomname);
6843 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6845 if (longname == NULL) {
6846 result = WERR_NOT_ENOUGH_MEMORY;
6850 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6852 DEBUG(0, ("longname data corrupted\n"));
6853 result = WERR_INVALID_DATA;
6856 result = winreg_set_printer_dataex(tmp_ctx, b,
6858 SPOOL_DSSPOOLER_KEY,
6859 SPOOL_REG_SERVERNAME,
6863 if (!W_ERROR_IS_OK(result)) {
6864 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6868 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6869 lp_netbios_name(), printer->sharename);
6870 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6872 DEBUG(0, ("uncName data corrupted\n"));
6873 result = WERR_INVALID_DATA;
6876 result = winreg_set_printer_dataex(tmp_ctx, b,
6878 SPOOL_DSSPOOLER_KEY,
6883 if (!W_ERROR_IS_OK(result)) {
6884 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6889 talloc_free(tmp_ctx);
6893 /********************************************************************
6894 * Called by spoolss_api_setprinter
6895 * when updating a printer description.
6896 ********************************************************************/
6898 static WERROR update_printer(struct pipes_struct *p,
6899 struct policy_handle *handle,
6900 struct spoolss_SetPrinterInfoCtr *info_ctr,
6901 struct spoolss_DeviceMode *devmode)
6903 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6904 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6905 struct spoolss_PrinterInfo2 *old_printer;
6906 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6908 WERROR result = WERR_OK;
6909 TALLOC_CTX *tmp_ctx;
6910 struct dcerpc_binding_handle *b;
6912 DEBUG(8,("update_printer\n"));
6914 tmp_ctx = talloc_new(p->mem_ctx);
6915 if (tmp_ctx == NULL) {
6916 return WERR_NOT_ENOUGH_MEMORY;
6920 result = WERR_INVALID_HANDLE;
6924 if (!get_printer_snum(p, handle, &snum, NULL)) {
6925 result = WERR_INVALID_HANDLE;
6929 result = winreg_printer_binding_handle(tmp_ctx,
6930 get_session_info_system(),
6933 if (!W_ERROR_IS_OK(result)) {
6937 result = winreg_get_printer(tmp_ctx, b,
6938 lp_const_servicename(snum),
6940 if (!W_ERROR_IS_OK(result)) {
6941 result = WERR_INVALID_HANDLE;
6945 /* Do sanity check on the requested changes for Samba */
6946 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6947 result = WERR_INVALID_PARAMETER;
6951 /* FIXME!!! If the driver has changed we really should verify that
6952 it is installed before doing much else --jerry */
6954 /* Check calling user has permission to update printer description */
6955 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6956 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6957 result = WERR_ACCESS_DENIED;
6961 /* Call addprinter hook */
6962 /* Check changes to see if this is really needed */
6964 if (*lp_addprinter_command(talloc_tos()) &&
6965 (!strequal(printer->drivername, old_printer->drivername) ||
6966 !strequal(printer->comment, old_printer->comment) ||
6967 !strequal(printer->portname, old_printer->portname) ||
6968 !strequal(printer->location, old_printer->location)) )
6972 raddr = tsocket_address_inet_addr_string(p->remote_address,
6974 if (raddr == NULL) {
6975 return WERR_NOT_ENOUGH_MEMORY;
6978 /* add_printer_hook() will call reload_services() */
6979 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6982 result = WERR_ACCESS_DENIED;
6987 result = update_dsspooler(tmp_ctx,
6988 get_session_info_system(),
6993 if (!W_ERROR_IS_OK(result)) {
6997 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6999 if (devmode == NULL) {
7000 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
7002 result = winreg_update_printer(tmp_ctx, b,
7010 talloc_free(tmp_ctx);
7015 /****************************************************************************
7016 ****************************************************************************/
7017 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
7018 struct policy_handle *handle,
7019 struct spoolss_SetPrinterInfo7 *info7)
7022 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7025 struct printer_handle *Printer;
7027 if ( lp_security() != SEC_ADS ) {
7028 return WERR_INVALID_LEVEL;
7031 Printer = find_printer_index_by_hnd(p, handle);
7033 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
7036 return WERR_INVALID_HANDLE;
7038 if (!get_printer_snum(p, handle, &snum, NULL))
7039 return WERR_INVALID_HANDLE;
7041 result = winreg_get_printer_internal(p->mem_ctx,
7042 get_session_info_system(),
7044 lp_servicename(talloc_tos(), snum),
7046 if (!W_ERROR_IS_OK(result)) {
7047 return WERR_INVALID_HANDLE;
7050 nt_printer_publish(pinfo2,
7051 get_session_info_system(),
7056 TALLOC_FREE(pinfo2);
7059 return WERR_INVALID_LEVEL;
7063 /********************************************************************
7064 ********************************************************************/
7066 static WERROR update_printer_devmode(struct pipes_struct *p,
7067 struct policy_handle *handle,
7068 struct spoolss_DeviceMode *devmode)
7071 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
7072 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
7074 DEBUG(8,("update_printer_devmode\n"));
7077 return WERR_INVALID_HANDLE;
7080 if (!get_printer_snum(p, handle, &snum, NULL)) {
7081 return WERR_INVALID_HANDLE;
7084 /* Check calling user has permission to update printer description */
7085 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
7086 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
7087 return WERR_ACCESS_DENIED;
7090 return winreg_update_printer_internal(p->mem_ctx,
7091 get_session_info_system(),
7093 lp_const_servicename(snum),
7101 /****************************************************************
7103 ****************************************************************/
7105 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
7106 struct spoolss_SetPrinter *r)
7110 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7113 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
7114 OUR_HANDLE(r->in.handle)));
7115 return WERR_INVALID_HANDLE;
7118 /* check the level */
7119 switch (r->in.info_ctr->level) {
7121 return control_printer(r->in.handle, r->in.command, p);
7123 result = update_printer(p, r->in.handle,
7125 r->in.devmode_ctr->devmode);
7126 if (!W_ERROR_IS_OK(result))
7128 if (r->in.secdesc_ctr->sd)
7129 result = update_printer_sec(r->in.handle, p,
7133 return update_printer_sec(r->in.handle, p,
7136 struct spoolss_PrinterInfo2 *old_printer;
7137 struct spoolss_SetPrinterInfo2 *set_old_printer;
7138 struct spoolss_SetPrinterInfoCtr *info_ctr;
7139 struct dcerpc_binding_handle *b;
7141 TALLOC_CTX *tmp_ctx;
7143 tmp_ctx = talloc_new(p->mem_ctx);
7144 if (tmp_ctx == NULL) {
7145 return WERR_NOT_ENOUGH_MEMORY;
7148 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7149 TALLOC_FREE(tmp_ctx);
7150 return WERR_INVALID_HANDLE;
7153 result = winreg_printer_binding_handle(tmp_ctx,
7154 get_session_info_system(),
7157 if (!W_ERROR_IS_OK(result)) {
7158 TALLOC_FREE(tmp_ctx);
7162 result = winreg_get_printer(tmp_ctx, b,
7163 lp_const_servicename(snum),
7165 if (!W_ERROR_IS_OK(result)) {
7166 TALLOC_FREE(tmp_ctx);
7167 return WERR_INVALID_HANDLE;
7170 old_printer->servername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->servername);
7171 if (old_printer->servername == NULL) {
7172 TALLOC_FREE(tmp_ctx);
7173 return WERR_NOT_ENOUGH_MEMORY;
7176 old_printer->printername = talloc_strdup(tmp_ctx, r->in.info_ctr->info.info4->printername);
7177 if (old_printer->printername == NULL) {
7178 TALLOC_FREE(tmp_ctx);
7179 return WERR_NOT_ENOUGH_MEMORY;
7182 old_printer->attributes = r->in.info_ctr->info.info4->attributes;
7184 set_old_printer = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
7185 if (set_old_printer == NULL) {
7186 TALLOC_FREE(tmp_ctx);
7187 return WERR_NOT_ENOUGH_MEMORY;
7190 spoolss_printerinfo2_to_setprinterinfo2(old_printer, set_old_printer);
7192 info_ctr = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfoCtr);
7193 if (info_ctr == NULL) {
7194 TALLOC_FREE(tmp_ctx);
7195 return WERR_NOT_ENOUGH_MEMORY;
7198 info_ctr->level = 2;
7199 info_ctr->info.info2 = set_old_printer;
7201 result = update_printer(p, r->in.handle,
7203 r->in.devmode_ctr->devmode);
7205 if (!W_ERROR_IS_OK(result)) {
7206 TALLOC_FREE(tmp_ctx);
7210 if (r->in.secdesc_ctr->sd) {
7211 result = update_printer_sec(r->in.handle, p,
7215 TALLOC_FREE(tmp_ctx);
7219 return publish_or_unpublish_printer(p, r->in.handle,
7220 r->in.info_ctr->info.info7);
7222 return update_printer_devmode(p, r->in.handle,
7223 r->in.devmode_ctr->devmode);
7225 return WERR_INVALID_LEVEL;
7229 /****************************************************************
7230 _spoolss_FindClosePrinterNotify
7231 ****************************************************************/
7233 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
7234 struct spoolss_FindClosePrinterNotify *r)
7236 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
7239 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
7240 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
7241 return WERR_INVALID_HANDLE;
7244 if (Printer->notify.cli_chan != NULL &&
7245 Printer->notify.cli_chan->active_connections > 0) {
7248 if (Printer->printer_type == SPLHND_PRINTER) {
7249 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7250 return WERR_INVALID_HANDLE;
7254 srv_spoolss_replycloseprinter(snum, Printer);
7257 Printer->notify.flags=0;
7258 Printer->notify.options=0;
7259 Printer->notify.localmachine[0]='\0';
7260 Printer->notify.printerlocal=0;
7261 TALLOC_FREE(Printer->notify.option);
7266 /****************************************************************
7268 ****************************************************************/
7270 WERROR _spoolss_AddJob(struct pipes_struct *p,
7271 struct spoolss_AddJob *r)
7273 if (!r->in.buffer && (r->in.offered != 0)) {
7274 return WERR_INVALID_PARAMETER;
7277 /* this is what a NT server returns for AddJob. AddJob must fail on
7278 * non-local printers */
7280 if (r->in.level != 1) {
7281 return WERR_INVALID_LEVEL;
7284 return WERR_INVALID_PARAMETER;
7287 /****************************************************************************
7289 ****************************************************************************/
7291 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
7292 struct spoolss_JobInfo1 *r,
7293 const print_queue_struct *queue,
7295 int position, int snum,
7296 struct spoolss_PrinterInfo2 *pinfo2)
7300 t = gmtime(&queue->time);
7304 r->printer_name = lp_servicename(mem_ctx, snum);
7305 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7306 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7307 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7308 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7309 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7310 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7311 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7312 r->data_type = talloc_strdup(mem_ctx, "RAW");
7313 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7314 r->text_status = talloc_strdup(mem_ctx, "");
7315 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7317 r->status = nt_printj_status(queue->status);
7318 r->priority = queue->priority;
7319 r->position = position;
7320 r->total_pages = queue->page_count;
7321 r->pages_printed = 0; /* ??? */
7323 init_systemtime(&r->submitted, t);
7328 /****************************************************************************
7330 ****************************************************************************/
7332 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7333 struct spoolss_JobInfo2 *r,
7334 const print_queue_struct *queue,
7336 int position, int snum,
7337 struct spoolss_PrinterInfo2 *pinfo2,
7338 struct spoolss_DeviceMode *devmode)
7342 t = gmtime(&queue->time);
7346 r->printer_name = lp_servicename(mem_ctx, snum);
7347 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7348 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7349 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7350 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7351 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7352 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7353 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7354 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7355 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7356 r->data_type = talloc_strdup(mem_ctx, "RAW");
7357 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7358 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7359 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7360 r->parameters = talloc_strdup(mem_ctx, "");
7361 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7362 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7363 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7365 r->devmode = devmode;
7367 r->text_status = talloc_strdup(mem_ctx, "");
7368 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7372 r->status = nt_printj_status(queue->status);
7373 r->priority = queue->priority;
7374 r->position = position;
7377 r->total_pages = queue->page_count;
7378 r->size = queue->size;
7379 init_systemtime(&r->submitted, t);
7381 r->pages_printed = 0; /* ??? */
7386 /****************************************************************************
7387 Enumjobs at level 1.
7388 ****************************************************************************/
7390 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7391 const print_queue_struct *queue,
7392 uint32_t num_queues, int snum,
7393 struct spoolss_PrinterInfo2 *pinfo2,
7394 union spoolss_JobInfo **info_p,
7397 union spoolss_JobInfo *info;
7399 WERROR result = WERR_OK;
7400 uint32_t num_filled;
7401 struct tdb_print_db *pdb;
7403 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7405 result = WERR_NOT_ENOUGH_MEMORY;
7409 pdb = get_print_db_byname(pinfo2->sharename);
7411 result = WERR_INVALID_PARAMETER;
7416 for (i = 0; i < num_queues; i++) {
7417 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7418 if (jobid == (uint32_t)-1) {
7419 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7423 result = fill_job_info1(info,
7424 &info[num_filled].info1,
7430 if (!W_ERROR_IS_OK(result)) {
7437 release_print_db(pdb);
7439 *count = num_filled;
7444 release_print_db(pdb);
7452 /****************************************************************************
7453 Enumjobs at level 2.
7454 ****************************************************************************/
7456 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7457 const print_queue_struct *queue,
7458 uint32_t num_queues, int snum,
7459 struct spoolss_PrinterInfo2 *pinfo2,
7460 union spoolss_JobInfo **info_p,
7463 union spoolss_JobInfo *info;
7465 WERROR result = WERR_OK;
7466 uint32_t num_filled;
7467 struct tdb_print_db *pdb;
7469 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7471 result = WERR_NOT_ENOUGH_MEMORY;
7475 pdb = get_print_db_byname(pinfo2->sharename);
7477 result = WERR_INVALID_PARAMETER;
7482 for (i = 0; i< num_queues; i++) {
7483 struct spoolss_DeviceMode *devmode;
7484 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7485 if (jobid == (uint32_t)-1) {
7486 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7490 result = spoolss_create_default_devmode(info,
7491 pinfo2->printername,
7493 if (!W_ERROR_IS_OK(result)) {
7494 DEBUG(3, ("Can't proceed w/o a devmode!"));
7498 result = fill_job_info2(info,
7499 &info[num_filled].info2,
7506 if (!W_ERROR_IS_OK(result)) {
7512 release_print_db(pdb);
7514 *count = num_filled;
7519 release_print_db(pdb);
7527 /****************************************************************************
7528 Enumjobs at level 3.
7529 ****************************************************************************/
7531 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7532 const print_queue_struct *queue,
7533 uint32_t num_queues, int snum,
7534 struct spoolss_PrinterInfo2 *pinfo2,
7535 union spoolss_JobInfo **info_p,
7538 union spoolss_JobInfo *info;
7540 WERROR result = WERR_OK;
7541 uint32_t num_filled;
7542 struct tdb_print_db *pdb;
7544 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7546 result = WERR_NOT_ENOUGH_MEMORY;
7550 pdb = get_print_db_byname(pinfo2->sharename);
7552 result = WERR_INVALID_PARAMETER;
7557 for (i = 0; i < num_queues; i++) {
7558 uint32_t jobid = sysjob_to_jobid_pdb(pdb, queue[i].sysjob);
7559 if (jobid == (uint32_t)-1) {
7560 DEBUG(4, ("skipping sysjob %d\n", queue[i].sysjob));
7564 info[num_filled].info3.job_id = jobid;
7565 /* next_job_id is overwritten on next iteration */
7566 info[num_filled].info3.next_job_id = 0;
7567 info[num_filled].info3.reserved = 0;
7569 if (num_filled > 0) {
7570 info[num_filled - 1].info3.next_job_id = jobid;
7575 release_print_db(pdb);
7577 *count = num_filled;
7588 /****************************************************************
7590 ****************************************************************/
7592 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7593 struct spoolss_EnumJobs *r)
7596 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7598 print_status_struct prt_status;
7599 print_queue_struct *queue = NULL;
7602 /* that's an [in out] buffer */
7604 if (!r->in.buffer && (r->in.offered != 0)) {
7605 return WERR_INVALID_PARAMETER;
7608 if ((r->in.level != 1) && (r->in.level != 2) && (r->in.level != 3)) {
7609 DEBUG(4, ("EnumJobs level %d not supported\n", r->in.level));
7610 return WERR_INVALID_LEVEL;
7613 DEBUG(4,("_spoolss_EnumJobs\n"));
7617 *r->out.info = NULL;
7619 /* lookup the printer snum and tdb entry */
7621 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7622 return WERR_INVALID_HANDLE;
7625 result = winreg_get_printer_internal(p->mem_ctx,
7626 get_session_info_system(),
7628 lp_const_servicename(snum),
7630 if (!W_ERROR_IS_OK(result)) {
7634 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7635 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7636 count, prt_status.status, prt_status.message));
7640 TALLOC_FREE(pinfo2);
7644 switch (r->in.level) {
7646 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7647 pinfo2, r->out.info, r->out.count);
7650 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7651 pinfo2, r->out.info, r->out.count);
7654 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7655 pinfo2, r->out.info, r->out.count);
7658 SMB_ASSERT(false); /* level checked on entry */
7663 TALLOC_FREE(pinfo2);
7665 if (!W_ERROR_IS_OK(result)) {
7669 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7671 *r->out.info, r->in.level,
7673 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7674 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7676 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7679 /****************************************************************
7680 _spoolss_ScheduleJob
7681 ****************************************************************/
7683 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7684 struct spoolss_ScheduleJob *r)
7689 /****************************************************************
7690 ****************************************************************/
7692 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7693 struct messaging_context *msg_ctx,
7694 const char *printer_name,
7696 struct spoolss_SetJobInfo1 *r)
7700 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7701 return WERR_INVALID_HANDLE;
7704 if (strequal(old_doc_name, r->document_name)) {
7708 if (!print_job_set_name(server_event_context(), msg_ctx,
7709 printer_name, job_id, r->document_name)) {
7710 return WERR_INVALID_HANDLE;
7716 /****************************************************************
7718 ****************************************************************/
7720 WERROR _spoolss_SetJob(struct pipes_struct *p,
7721 struct spoolss_SetJob *r)
7723 const struct auth_session_info *session_info = p->session_info;
7725 WERROR errcode = WERR_INVALID_FUNCTION;
7727 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7728 return WERR_INVALID_HANDLE;
7731 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7732 return WERR_INVALID_PRINTER_NAME;
7735 switch (r->in.command) {
7736 case SPOOLSS_JOB_CONTROL_CANCEL:
7737 case SPOOLSS_JOB_CONTROL_DELETE:
7738 errcode = print_job_delete(session_info, p->msg_ctx,
7739 snum, r->in.job_id);
7740 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7744 case SPOOLSS_JOB_CONTROL_PAUSE:
7745 errcode = print_job_pause(session_info, p->msg_ctx,
7746 snum, r->in.job_id);
7748 case SPOOLSS_JOB_CONTROL_RESTART:
7749 case SPOOLSS_JOB_CONTROL_RESUME:
7750 errcode = print_job_resume(session_info, p->msg_ctx,
7751 snum, r->in.job_id);
7753 case SPOOLSS_JOB_CONTROL_NOOP:
7757 return WERR_INVALID_LEVEL;
7760 if (!W_ERROR_IS_OK(errcode)) {
7764 if (r->in.ctr == NULL) {
7768 switch (r->in.ctr->level) {
7770 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7771 lp_const_servicename(snum),
7773 r->in.ctr->info.info1);
7779 return WERR_INVALID_LEVEL;
7785 /****************************************************************************
7786 Enumerates all printer drivers by level and architecture.
7787 ****************************************************************************/
7789 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7790 const struct auth_session_info *session_info,
7791 struct messaging_context *msg_ctx,
7792 const char *servername,
7793 const char *architecture,
7795 union spoolss_DriverInfo **info_p,
7800 struct spoolss_DriverInfo8 *driver;
7801 union spoolss_DriverInfo *info = NULL;
7803 WERROR result = WERR_OK;
7804 uint32_t num_drivers;
7805 const char **drivers;
7806 struct dcerpc_binding_handle *b;
7807 TALLOC_CTX *tmp_ctx = NULL;
7812 tmp_ctx = talloc_new(mem_ctx);
7814 return WERR_NOT_ENOUGH_MEMORY;
7817 result = winreg_printer_binding_handle(tmp_ctx,
7821 if (!W_ERROR_IS_OK(result)) {
7825 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7826 result = winreg_get_driver_list(tmp_ctx, b,
7827 architecture, version,
7828 &num_drivers, &drivers);
7829 if (!W_ERROR_IS_OK(result)) {
7832 DEBUG(4, ("we have:[%d] drivers in environment"
7833 " [%s] and version [%d]\n",
7834 num_drivers, architecture, version));
7836 if (num_drivers != 0) {
7837 info = talloc_realloc(tmp_ctx, info,
7838 union spoolss_DriverInfo,
7839 count + num_drivers);
7841 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7842 "failed to enlarge driver info buffer!\n"));
7843 result = WERR_NOT_ENOUGH_MEMORY;
7848 for (i = 0; i < num_drivers; i++) {
7849 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7851 result = winreg_get_driver(tmp_ctx, b,
7852 architecture, drivers[i],
7854 if (!W_ERROR_IS_OK(result)) {
7860 result = fill_printer_driver_info1(info, &info[count+i].info1,
7861 driver, servername);
7864 result = fill_printer_driver_info2(info, &info[count+i].info2,
7865 driver, servername);
7868 result = fill_printer_driver_info3(info, &info[count+i].info3,
7869 driver, servername);
7872 result = fill_printer_driver_info4(info, &info[count+i].info4,
7873 driver, servername);
7876 result = fill_printer_driver_info5(info, &info[count+i].info5,
7877 driver, servername);
7880 result = fill_printer_driver_info6(info, &info[count+i].info6,
7881 driver, servername);
7884 result = fill_printer_driver_info8(info, &info[count+i].info8,
7885 driver, servername);
7888 result = WERR_INVALID_LEVEL;
7892 TALLOC_FREE(driver);
7894 if (!W_ERROR_IS_OK(result)) {
7899 count += num_drivers;
7900 TALLOC_FREE(drivers);
7904 if (W_ERROR_IS_OK(result)) {
7905 *info_p = talloc_move(mem_ctx, &info);
7909 talloc_free(tmp_ctx);
7913 /****************************************************************************
7914 Enumerates all printer drivers by level.
7915 ****************************************************************************/
7917 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7918 const struct auth_session_info *session_info,
7919 struct messaging_context *msg_ctx,
7920 const char *servername,
7921 const char *architecture,
7923 union spoolss_DriverInfo **info_p,
7927 WERROR result = WERR_OK;
7929 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7931 for (a=0; archi_table[a].long_archi != NULL; a++) {
7933 union spoolss_DriverInfo *info = NULL;
7936 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7940 archi_table[a].long_archi,
7944 if (!W_ERROR_IS_OK(result)) {
7948 for (i=0; i < count; i++) {
7949 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7950 info[i], info_p, count_p);
7957 return enumprinterdrivers_level_by_architecture(mem_ctx,
7967 /****************************************************************
7968 _spoolss_EnumPrinterDrivers
7969 ****************************************************************/
7971 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7972 struct spoolss_EnumPrinterDrivers *r)
7974 const char *cservername;
7977 /* that's an [in out] buffer */
7979 if (!r->in.buffer && (r->in.offered != 0)) {
7980 return WERR_INVALID_PARAMETER;
7983 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7987 *r->out.info = NULL;
7989 cservername = canon_servername(r->in.server);
7991 if (!is_myname_or_ipaddr(cservername)) {
7992 return WERR_UNKNOWN_PRINTER_DRIVER;
7995 result = enumprinterdrivers_level(p->mem_ctx,
7996 get_session_info_system(),
8003 if (!W_ERROR_IS_OK(result)) {
8007 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8008 spoolss_EnumPrinterDrivers,
8009 *r->out.info, r->in.level,
8011 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8012 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8014 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8017 /****************************************************************
8019 ****************************************************************/
8021 WERROR _spoolss_EnumForms(struct pipes_struct *p,
8022 struct spoolss_EnumForms *r)
8028 *r->out.info = NULL;
8030 /* that's an [in out] buffer */
8032 if (!r->in.buffer && (r->in.offered != 0) ) {
8033 return WERR_INVALID_PARAMETER;
8036 DEBUG(4,("_spoolss_EnumForms\n"));
8037 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8038 DEBUGADD(5,("Info level [%d]\n", r->in.level));
8040 switch (r->in.level) {
8042 result = winreg_printer_enumforms1_internal(p->mem_ctx,
8043 get_session_info_system(),
8049 result = WERR_INVALID_LEVEL;
8053 if (!W_ERROR_IS_OK(result)) {
8057 if (*r->out.count == 0) {
8058 return WERR_NO_MORE_ITEMS;
8061 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8063 *r->out.info, r->in.level,
8065 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8066 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8068 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8071 /****************************************************************
8073 ****************************************************************/
8075 WERROR _spoolss_GetForm(struct pipes_struct *p,
8076 struct spoolss_GetForm *r)
8080 /* that's an [in out] buffer */
8082 if (!r->in.buffer && (r->in.offered != 0)) {
8083 TALLOC_FREE(r->out.info);
8084 return WERR_INVALID_PARAMETER;
8087 DEBUG(4,("_spoolss_GetForm\n"));
8088 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
8089 DEBUGADD(5,("Info level [%d]\n", r->in.level));
8091 switch (r->in.level) {
8093 result = winreg_printer_getform1_internal(p->mem_ctx,
8094 get_session_info_system(),
8097 &r->out.info->info1);
8100 result = WERR_INVALID_LEVEL;
8104 if (!W_ERROR_IS_OK(result)) {
8105 TALLOC_FREE(r->out.info);
8109 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
8110 r->out.info, r->in.level);
8111 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8113 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8116 /****************************************************************************
8117 ****************************************************************************/
8119 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
8120 struct spoolss_PortInfo1 *r,
8123 r->port_name = talloc_strdup(mem_ctx, name);
8124 W_ERROR_HAVE_NO_MEMORY(r->port_name);
8129 /****************************************************************************
8130 TODO: This probably needs distinguish between TCP/IP and Local ports
8132 ****************************************************************************/
8134 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
8135 struct spoolss_PortInfo2 *r,
8138 r->port_name = talloc_strdup(mem_ctx, name);
8139 W_ERROR_HAVE_NO_MEMORY(r->port_name);
8141 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
8142 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8144 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
8145 W_ERROR_HAVE_NO_MEMORY(r->description);
8147 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
8154 /****************************************************************************
8155 wrapper around the enumer ports command
8156 ****************************************************************************/
8158 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
8160 char *cmd = lp_enumports_command(talloc_tos());
8161 char **qlines = NULL;
8162 char *command = NULL;
8170 /* if no hook then just fill in the default port */
8173 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
8174 return WERR_NOT_ENOUGH_MEMORY;
8176 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
8177 TALLOC_FREE(qlines);
8178 return WERR_NOT_ENOUGH_MEMORY;
8184 /* we have a valid enumport command */
8186 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
8188 return WERR_NOT_ENOUGH_MEMORY;
8191 DEBUG(10,("Running [%s]\n", command));
8192 ret = smbrun(command, &fd, NULL);
8193 DEBUG(10,("Returned [%d]\n", ret));
8194 TALLOC_FREE(command);
8199 return WERR_ACCESS_DENIED;
8203 qlines = fd_lines_load(fd, &numlines, 0, NULL);
8204 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
8214 /****************************************************************************
8216 ****************************************************************************/
8218 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
8219 union spoolss_PortInfo **info_p,
8222 union spoolss_PortInfo *info = NULL;
8224 WERROR result = WERR_OK;
8225 char **qlines = NULL;
8228 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8229 if (!W_ERROR_IS_OK(result)) {
8234 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8236 DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8237 result = WERR_NOT_ENOUGH_MEMORY;
8241 for (i=0; i<numlines; i++) {
8242 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8243 result = fill_port_1(info, &info[i].info1, qlines[i]);
8244 if (!W_ERROR_IS_OK(result)) {
8249 TALLOC_FREE(qlines);
8252 if (!W_ERROR_IS_OK(result)) {
8254 TALLOC_FREE(qlines);
8266 /****************************************************************************
8268 ****************************************************************************/
8270 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
8271 union spoolss_PortInfo **info_p,
8274 union spoolss_PortInfo *info = NULL;
8276 WERROR result = WERR_OK;
8277 char **qlines = NULL;
8280 result = enumports_hook(talloc_tos(), &numlines, &qlines );
8281 if (!W_ERROR_IS_OK(result)) {
8286 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
8288 DEBUG(10,("Returning WERR_NOT_ENOUGH_MEMORY\n"));
8289 result = WERR_NOT_ENOUGH_MEMORY;
8293 for (i=0; i<numlines; i++) {
8294 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
8295 result = fill_port_2(info, &info[i].info2, qlines[i]);
8296 if (!W_ERROR_IS_OK(result)) {
8301 TALLOC_FREE(qlines);
8304 if (!W_ERROR_IS_OK(result)) {
8306 TALLOC_FREE(qlines);
8318 /****************************************************************
8320 ****************************************************************/
8322 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
8323 struct spoolss_EnumPorts *r)
8327 /* that's an [in out] buffer */
8329 if (!r->in.buffer && (r->in.offered != 0)) {
8330 return WERR_INVALID_PARAMETER;
8333 DEBUG(4,("_spoolss_EnumPorts\n"));
8337 *r->out.info = NULL;
8339 switch (r->in.level) {
8341 result = enumports_level_1(p->mem_ctx, r->out.info,
8345 result = enumports_level_2(p->mem_ctx, r->out.info,
8349 return WERR_INVALID_LEVEL;
8352 if (!W_ERROR_IS_OK(result)) {
8356 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8358 *r->out.info, r->in.level,
8360 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8361 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8363 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8366 /****************************************************************************
8367 ****************************************************************************/
8369 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8371 struct spoolss_SetPrinterInfoCtr *info_ctr,
8372 struct spoolss_DeviceMode *devmode,
8373 struct security_descriptor *secdesc,
8374 struct spoolss_UserLevelCtr *user_ctr,
8375 struct policy_handle *handle)
8377 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8378 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8380 WERROR err = WERR_OK;
8382 /* samba does not have a concept of local, non-shared printers yet, so
8383 * make sure we always setup sharename - gd */
8384 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8385 (info2->printername != NULL && info2->printername[0] != '\0')) {
8386 DEBUG(5, ("spoolss_addprinterex_level_2: "
8387 "no sharename has been set, setting printername %s as sharename\n",
8388 info2->printername));
8389 info2->sharename = info2->printername;
8392 /* check to see if the printer already exists */
8393 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8394 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8396 return WERR_PRINTER_ALREADY_EXISTS;
8399 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8400 if ((snum = print_queue_snum(info2->printername)) != -1) {
8401 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8402 info2->printername));
8403 return WERR_PRINTER_ALREADY_EXISTS;
8407 /* validate printer info struct */
8408 if (!info2->printername || strlen(info2->printername) == 0) {
8409 return WERR_INVALID_PRINTER_NAME;
8411 if (!info2->portname || strlen(info2->portname) == 0) {
8412 return WERR_UNKNOWN_PORT;
8414 if (!info2->drivername || strlen(info2->drivername) == 0) {
8415 return WERR_UNKNOWN_PRINTER_DRIVER;
8417 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8418 return WERR_UNKNOWN_PRINTPROCESSOR;
8421 /* FIXME!!! smbd should check to see if the driver is installed before
8422 trying to add a printer like this --jerry */
8424 if (*lp_addprinter_command(talloc_tos()) ) {
8427 raddr = tsocket_address_inet_addr_string(p->remote_address,
8429 if (raddr == NULL) {
8430 return WERR_NOT_ENOUGH_MEMORY;
8433 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8436 return WERR_ACCESS_DENIED;
8439 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8440 "smb.conf parameter \"addprinter command\" is defined. This "
8441 "parameter must exist for this call to succeed\n",
8442 info2->sharename ));
8445 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8446 return WERR_ACCESS_DENIED;
8449 /* you must be a printer admin to add a new printer */
8450 if (!W_ERROR_IS_OK(print_access_check(p->session_info,
8453 PRINTER_ACCESS_ADMINISTER))) {
8454 return WERR_ACCESS_DENIED;
8458 * Do sanity check on the requested changes for Samba.
8461 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8462 return WERR_INVALID_PARAMETER;
8465 if (devmode == NULL) {
8466 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8469 err = update_dsspooler(p->mem_ctx,
8470 get_session_info_system(),
8475 if (!W_ERROR_IS_OK(err)) {
8479 err = winreg_update_printer_internal(p->mem_ctx,
8480 get_session_info_system(),
8487 if (!W_ERROR_IS_OK(err)) {
8491 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8492 if (!W_ERROR_IS_OK(err)) {
8493 /* Handle open failed - remove addition. */
8494 ZERO_STRUCTP(handle);
8501 /****************************************************************
8502 _spoolss_AddPrinterEx
8503 ****************************************************************/
8505 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8506 struct spoolss_AddPrinterEx *r)
8508 switch (r->in.info_ctr->level) {
8510 /* we don't handle yet */
8511 /* but I know what to do ... */
8512 return WERR_INVALID_LEVEL;
8514 return spoolss_addprinterex_level_2(p, r->in.server,
8516 r->in.devmode_ctr->devmode,
8517 r->in.secdesc_ctr->sd,
8518 r->in.userlevel_ctr,
8521 return WERR_INVALID_LEVEL;
8525 /****************************************************************
8527 ****************************************************************/
8529 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8530 struct spoolss_AddPrinter *r)
8532 struct spoolss_AddPrinterEx a;
8533 struct spoolss_UserLevelCtr userlevel_ctr;
8535 ZERO_STRUCT(userlevel_ctr);
8537 userlevel_ctr.level = 1;
8539 a.in.server = r->in.server;
8540 a.in.info_ctr = r->in.info_ctr;
8541 a.in.devmode_ctr = r->in.devmode_ctr;
8542 a.in.secdesc_ctr = r->in.secdesc_ctr;
8543 a.in.userlevel_ctr = &userlevel_ctr;
8544 a.out.handle = r->out.handle;
8546 return _spoolss_AddPrinterEx(p, &a);
8549 /****************************************************************
8550 _spoolss_AddPrinterDriverEx
8551 ****************************************************************/
8553 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8554 struct spoolss_AddPrinterDriverEx *r)
8556 WERROR err = WERR_OK;
8557 const char *driver_name = NULL;
8558 const char *driver_directory = NULL;
8562 * we only support the semantics of AddPrinterDriver()
8563 * i.e. only copy files that are newer than existing ones
8566 if (r->in.flags == 0) {
8567 return WERR_INVALID_PARAMETER;
8570 if (!(r->in.flags & APD_COPY_ALL_FILES) &&
8571 !(r->in.flags & APD_COPY_NEW_FILES)) {
8572 return WERR_ACCESS_DENIED;
8576 if (r->in.info_ctr->level != 3 &&
8577 r->in.info_ctr->level != 6 &&
8578 r->in.info_ctr->level != 8) {
8579 DEBUG(0,("%s: level %d not yet implemented\n", __func__,
8580 r->in.info_ctr->level));
8581 return WERR_INVALID_LEVEL;
8584 DEBUG(5,("Cleaning driver's information\n"));
8585 err = clean_up_driver_struct(p->mem_ctx,
8590 if (!W_ERROR_IS_OK(err)) {
8591 DBG_ERR("clean_up_driver_struct failed - %s\n",
8596 DEBUG(5,("Moving driver to final destination\n"));
8597 err = move_driver_to_download_area(p->session_info,
8600 if (!W_ERROR_IS_OK(err)) {
8601 DBG_ERR("move_driver_to_download_area failed - %s\n",
8606 err = winreg_add_driver_internal(p->mem_ctx,
8607 get_session_info_system(),
8612 if (!W_ERROR_IS_OK(err)) {
8613 DBG_ERR("winreg_add_driver_internal failed - %s\n",
8619 * I think this is where he DrvUpgradePrinter() hook would be
8620 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8621 * server. Right now, we just need to send ourselves a message
8622 * to update each printer bound to this driver. --jerry
8625 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8626 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8627 __func__, driver_name));
8634 /****************************************************************
8635 _spoolss_AddPrinterDriver
8636 ****************************************************************/
8638 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8639 struct spoolss_AddPrinterDriver *r)
8641 struct spoolss_AddPrinterDriverEx a;
8643 switch (r->in.info_ctr->level) {
8650 return WERR_INVALID_LEVEL;
8653 a.in.servername = r->in.servername;
8654 a.in.info_ctr = r->in.info_ctr;
8655 a.in.flags = APD_COPY_NEW_FILES;
8657 return _spoolss_AddPrinterDriverEx(p, &a);
8660 /****************************************************************************
8661 ****************************************************************************/
8663 struct _spoolss_paths {
8669 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8671 static const struct _spoolss_paths spoolss_paths[]= {
8672 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8673 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8676 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8677 const char *servername,
8678 const char *environment,
8682 const char *pservername = NULL;
8683 const char *long_archi;
8684 const char *short_archi;
8688 /* environment may be empty */
8689 if (environment && strlen(environment)) {
8690 long_archi = environment;
8692 long_archi = lp_parm_const_string(GLOBAL_SECTION_SNUM,
8693 "spoolss", "architecture",
8694 GLOBAL_SPOOLSS_ARCHITECTURE);
8697 /* servername may be empty */
8698 if (servername && strlen(servername)) {
8699 pservername = canon_servername(servername);
8701 if (!is_myname_or_ipaddr(pservername)) {
8702 return WERR_INVALID_PARAMETER;
8706 if (!(short_archi = get_short_archi(long_archi))) {
8707 return WERR_INVALID_ENVIRONMENT;
8710 switch (component) {
8711 case SPOOLSS_PRTPROCS_PATH:
8712 case SPOOLSS_DRIVER_PATH:
8714 *path = talloc_asprintf(mem_ctx,
8717 spoolss_paths[component].share,
8720 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8721 SPOOLSS_DEFAULT_SERVER_PATH,
8722 spoolss_paths[component].dir,
8727 return WERR_INVALID_PARAMETER;
8731 return WERR_NOT_ENOUGH_MEMORY;
8737 /****************************************************************************
8738 ****************************************************************************/
8740 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8741 const char *servername,
8742 const char *environment,
8743 struct spoolss_DriverDirectoryInfo1 *r)
8748 werr = compose_spoolss_server_path(mem_ctx,
8751 SPOOLSS_DRIVER_PATH,
8753 if (!W_ERROR_IS_OK(werr)) {
8757 DEBUG(4,("printer driver directory: [%s]\n", path));
8759 r->directory_name = path;
8764 /****************************************************************
8765 _spoolss_GetPrinterDriverDirectory
8766 ****************************************************************/
8768 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8769 struct spoolss_GetPrinterDriverDirectory *r)
8773 /* that's an [in out] buffer */
8775 if (!r->in.buffer && (r->in.offered != 0)) {
8776 TALLOC_FREE(r->out.info);
8777 return WERR_INVALID_PARAMETER;
8780 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8785 /* r->in.level is ignored */
8787 werror = getprinterdriverdir_level_1(p->mem_ctx,
8790 &r->out.info->info1);
8791 if (!W_ERROR_IS_OK(werror)) {
8792 TALLOC_FREE(r->out.info);
8796 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8797 r->out.info, r->in.level);
8798 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8800 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8803 /****************************************************************
8804 _spoolss_EnumPrinterData
8805 ****************************************************************/
8807 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8808 struct spoolss_EnumPrinterData *r)
8811 struct spoolss_EnumPrinterDataEx r2;
8813 struct spoolss_PrinterEnumValues *info, *val = NULL;
8816 r2.in.handle = r->in.handle;
8817 r2.in.key_name = "PrinterDriverData";
8819 r2.out.count = &count;
8820 r2.out.info = &info;
8821 r2.out.needed = &needed;
8823 result = _spoolss_EnumPrinterDataEx(p, &r2);
8824 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8825 r2.in.offered = needed;
8826 result = _spoolss_EnumPrinterDataEx(p, &r2);
8828 if (!W_ERROR_IS_OK(result)) {
8833 * The NT machine wants to know the biggest size of value and data
8835 * cf: MSDN EnumPrinterData remark section
8838 if (!r->in.value_offered && !r->in.data_offered) {
8839 uint32_t biggest_valuesize = 0;
8840 uint32_t biggest_datasize = 0;
8843 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8845 for (i=0; i<count; i++) {
8847 name_length = strlen(info[i].value_name);
8848 if (strlen(info[i].value_name) > biggest_valuesize) {
8849 biggest_valuesize = name_length;
8852 if (info[i].data_length > biggest_datasize) {
8853 biggest_datasize = info[i].data_length;
8856 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8860 /* the value is an UNICODE string but real_value_size is the length
8861 in bytes including the trailing 0 */
8863 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8864 *r->out.data_needed = biggest_datasize;
8866 DEBUG(6,("final values: [%d], [%d]\n",
8867 *r->out.value_needed, *r->out.data_needed));
8872 if (r->in.enum_index < count) {
8873 val = &info[r->in.enum_index];
8877 /* out_value should default to "" or else NT4 has
8878 problems unmarshalling the response */
8880 if (r->in.value_offered) {
8881 *r->out.value_needed = 1;
8882 r->out.value_name = talloc_strdup(r, "");
8883 if (!r->out.value_name) {
8884 return WERR_NOT_ENOUGH_MEMORY;
8887 r->out.value_name = NULL;
8888 *r->out.value_needed = 0;
8891 /* the data is counted in bytes */
8893 *r->out.data_needed = r->in.data_offered;
8895 result = WERR_NO_MORE_ITEMS;
8899 * - counted in bytes in the request
8900 * - counted in UNICODE chars in the max reply
8901 * - counted in bytes in the real size
8903 * take a pause *before* coding not *during* coding
8907 if (r->in.value_offered) {
8908 r->out.value_name = talloc_strdup(r, val->value_name);
8909 if (!r->out.value_name) {
8910 return WERR_NOT_ENOUGH_MEMORY;
8912 *r->out.value_needed = val->value_name_len;
8914 r->out.value_name = NULL;
8915 *r->out.value_needed = 0;
8920 *r->out.type = val->type;
8922 /* data - counted in bytes */
8925 * See the section "Dynamically Typed Query Parameters"
8929 if (r->out.data && val->data && val->data->data &&
8930 val->data_length && r->in.data_offered) {
8931 memcpy(r->out.data, val->data->data,
8932 MIN(val->data_length,r->in.data_offered));
8935 *r->out.data_needed = val->data_length;
8943 /****************************************************************
8944 _spoolss_SetPrinterData
8945 ****************************************************************/
8947 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8948 struct spoolss_SetPrinterData *r)
8950 struct spoolss_SetPrinterDataEx r2;
8952 r2.in.handle = r->in.handle;
8953 r2.in.key_name = "PrinterDriverData";
8954 r2.in.value_name = r->in.value_name;
8955 r2.in.type = r->in.type;
8956 r2.in.data = r->in.data;
8957 r2.in.offered = r->in.offered;
8959 return _spoolss_SetPrinterDataEx(p, &r2);
8962 /****************************************************************
8963 _spoolss_ResetPrinter
8964 ****************************************************************/
8966 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8967 struct spoolss_ResetPrinter *r)
8969 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8972 DEBUG(5,("_spoolss_ResetPrinter\n"));
8975 * All we do is to check to see if the handle and queue is valid.
8976 * This call really doesn't mean anything to us because we only
8977 * support RAW printing. --jerry
8981 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8982 OUR_HANDLE(r->in.handle)));
8983 return WERR_INVALID_HANDLE;
8986 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8987 return WERR_INVALID_HANDLE;
8990 /* blindly return success */
8994 /****************************************************************
8995 _spoolss_DeletePrinterData
8996 ****************************************************************/
8998 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8999 struct spoolss_DeletePrinterData *r)
9001 struct spoolss_DeletePrinterDataEx r2;
9003 r2.in.handle = r->in.handle;
9004 r2.in.key_name = "PrinterDriverData";
9005 r2.in.value_name = r->in.value_name;
9007 return _spoolss_DeletePrinterDataEx(p, &r2);
9010 /****************************************************************
9012 ****************************************************************/
9014 WERROR _spoolss_AddForm(struct pipes_struct *p,
9015 struct spoolss_AddForm *r)
9017 struct spoolss_AddFormInfo1 *form;
9019 WERROR status = WERR_OK;
9020 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9021 struct dcerpc_binding_handle *b;
9022 TALLOC_CTX *tmp_ctx = NULL;
9024 DEBUG(5,("_spoolss_AddForm\n"));
9027 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
9028 OUR_HANDLE(r->in.handle)));
9029 return WERR_INVALID_HANDLE;
9032 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9033 and not a printer admin, then fail */
9035 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9036 !security_token_has_privilege(p->session_info->security_token,
9037 SEC_PRIV_PRINT_OPERATOR)) {
9038 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
9039 return WERR_ACCESS_DENIED;
9042 if (r->in.info_ctr->level != 1) {
9043 return WERR_INVALID_LEVEL;
9046 form = r->in.info_ctr->info.info1;
9048 return WERR_INVALID_PARAMETER;
9051 switch (form->flags) {
9052 case SPOOLSS_FORM_USER:
9053 case SPOOLSS_FORM_BUILTIN:
9054 case SPOOLSS_FORM_PRINTER:
9057 return WERR_INVALID_PARAMETER;
9060 tmp_ctx = talloc_new(p->mem_ctx);
9062 return WERR_NOT_ENOUGH_MEMORY;
9065 status = winreg_printer_binding_handle(tmp_ctx,
9066 get_session_info_system(),
9069 if (!W_ERROR_IS_OK(status)) {
9073 status = winreg_printer_addform1(tmp_ctx, b, form);
9074 if (!W_ERROR_IS_OK(status)) {
9079 * ChangeID must always be set if this is a printer
9081 if (Printer->printer_type == SPLHND_PRINTER) {
9082 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9083 status = WERR_INVALID_HANDLE;
9087 status = winreg_printer_update_changeid(tmp_ctx, b,
9088 lp_const_servicename(snum));
9092 talloc_free(tmp_ctx);
9096 /****************************************************************
9098 ****************************************************************/
9100 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
9101 struct spoolss_DeleteForm *r)
9103 const char *form_name = r->in.form_name;
9104 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9106 WERROR status = WERR_OK;
9107 struct dcerpc_binding_handle *b;
9108 TALLOC_CTX *tmp_ctx = NULL;
9110 DEBUG(5,("_spoolss_DeleteForm\n"));
9113 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
9114 OUR_HANDLE(r->in.handle)));
9115 return WERR_INVALID_HANDLE;
9118 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9119 !security_token_has_privilege(p->session_info->security_token,
9120 SEC_PRIV_PRINT_OPERATOR)) {
9121 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
9122 return WERR_ACCESS_DENIED;
9125 tmp_ctx = talloc_new(p->mem_ctx);
9127 return WERR_NOT_ENOUGH_MEMORY;
9130 status = winreg_printer_binding_handle(tmp_ctx,
9131 get_session_info_system(),
9134 if (!W_ERROR_IS_OK(status)) {
9138 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
9139 if (!W_ERROR_IS_OK(status)) {
9144 * ChangeID must always be set if this is a printer
9146 if (Printer->printer_type == SPLHND_PRINTER) {
9147 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9148 status = WERR_INVALID_HANDLE;
9152 status = winreg_printer_update_changeid(tmp_ctx, b,
9153 lp_const_servicename(snum));
9157 talloc_free(tmp_ctx);
9161 /****************************************************************
9163 ****************************************************************/
9165 WERROR _spoolss_SetForm(struct pipes_struct *p,
9166 struct spoolss_SetForm *r)
9168 struct spoolss_AddFormInfo1 *form;
9169 const char *form_name = r->in.form_name;
9171 WERROR status = WERR_OK;
9172 struct dcerpc_binding_handle *b;
9173 TALLOC_CTX *tmp_ctx = NULL;
9175 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9177 DEBUG(5,("_spoolss_SetForm\n"));
9180 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
9181 OUR_HANDLE(r->in.handle)));
9182 return WERR_INVALID_HANDLE;
9185 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
9186 and not a printer admin, then fail */
9188 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
9189 !security_token_has_privilege(p->session_info->security_token,
9190 SEC_PRIV_PRINT_OPERATOR)) {
9191 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
9192 return WERR_ACCESS_DENIED;
9195 if (r->in.info_ctr->level != 1) {
9196 return WERR_INVALID_LEVEL;
9199 form = r->in.info_ctr->info.info1;
9201 return WERR_INVALID_PARAMETER;
9204 tmp_ctx = talloc_new(p->mem_ctx);
9206 return WERR_NOT_ENOUGH_MEMORY;
9209 status = winreg_printer_binding_handle(tmp_ctx,
9210 get_session_info_system(),
9213 if (!W_ERROR_IS_OK(status)) {
9217 status = winreg_printer_setform1(tmp_ctx, b,
9220 if (!W_ERROR_IS_OK(status)) {
9225 * ChangeID must always be set if this is a printer
9227 if (Printer->printer_type == SPLHND_PRINTER) {
9228 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9229 status = WERR_INVALID_HANDLE;
9233 status = winreg_printer_update_changeid(tmp_ctx, b,
9234 lp_const_servicename(snum));
9238 talloc_free(tmp_ctx);
9242 /****************************************************************************
9243 fill_print_processor1
9244 ****************************************************************************/
9246 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
9247 struct spoolss_PrintProcessorInfo1 *r,
9248 const char *print_processor_name)
9250 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
9251 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
9256 /****************************************************************************
9257 enumprintprocessors level 1.
9258 ****************************************************************************/
9260 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
9261 union spoolss_PrintProcessorInfo **info_p,
9264 union spoolss_PrintProcessorInfo *info;
9267 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
9268 W_ERROR_HAVE_NO_MEMORY(info);
9272 result = fill_print_processor1(info, &info[0].info1, "winprint");
9273 if (!W_ERROR_IS_OK(result)) {
9278 if (!W_ERROR_IS_OK(result)) {
9289 /****************************************************************
9290 _spoolss_EnumPrintProcessors
9291 ****************************************************************/
9293 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
9294 struct spoolss_EnumPrintProcessors *r)
9298 /* that's an [in out] buffer */
9300 if (!r->in.buffer && (r->in.offered != 0)) {
9301 return WERR_INVALID_PARAMETER;
9304 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
9307 * Enumerate the print processors ...
9309 * Just reply with "winprint", to keep NT happy
9310 * and I can use my nice printer checker.
9315 *r->out.info = NULL;
9317 if (!get_short_archi(r->in.environment)) {
9318 return WERR_INVALID_ENVIRONMENT;
9321 switch (r->in.level) {
9323 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
9327 return WERR_INVALID_LEVEL;
9330 if (!W_ERROR_IS_OK(result)) {
9334 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9335 spoolss_EnumPrintProcessors,
9336 *r->out.info, r->in.level,
9338 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9339 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9341 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9344 /****************************************************************************
9345 fill_printprocdatatype1
9346 ****************************************************************************/
9348 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
9349 struct spoolss_PrintProcDataTypesInfo1 *r,
9350 const char *name_array)
9352 r->name_array = talloc_strdup(mem_ctx, name_array);
9353 W_ERROR_HAVE_NO_MEMORY(r->name_array);
9358 /****************************************************************************
9359 enumprintprocdatatypes level 1.
9360 ****************************************************************************/
9362 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
9363 union spoolss_PrintProcDataTypesInfo **info_p,
9367 union spoolss_PrintProcDataTypesInfo *info;
9369 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
9370 W_ERROR_HAVE_NO_MEMORY(info);
9374 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9375 if (!W_ERROR_IS_OK(result)) {
9380 if (!W_ERROR_IS_OK(result)) {
9391 /****************************************************************
9392 _spoolss_EnumPrintProcessorDataTypes
9393 ****************************************************************/
9395 WERROR _spoolss_EnumPrintProcessorDataTypes(struct pipes_struct *p,
9396 struct spoolss_EnumPrintProcessorDataTypes *r)
9400 /* that's an [in out] buffer */
9402 if (!r->in.buffer && (r->in.offered != 0)) {
9403 return WERR_INVALID_PARAMETER;
9406 DEBUG(5,("_spoolss_EnumPrintProcessorDataTypes\n"));
9410 *r->out.info = NULL;
9412 if (r->in.print_processor_name == NULL ||
9413 !strequal(r->in.print_processor_name, "winprint")) {
9414 return WERR_UNKNOWN_PRINTPROCESSOR;
9417 switch (r->in.level) {
9419 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9423 return WERR_INVALID_LEVEL;
9426 if (!W_ERROR_IS_OK(result)) {
9430 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9431 spoolss_EnumPrintProcessorDataTypes,
9432 *r->out.info, r->in.level,
9434 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9435 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9437 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9440 /****************************************************************************
9442 ****************************************************************************/
9444 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9445 struct spoolss_MonitorInfo1 *r,
9446 const char *monitor_name)
9448 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9449 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9454 /****************************************************************************
9456 ****************************************************************************/
9458 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9459 struct spoolss_MonitorInfo2 *r,
9460 const char *monitor_name,
9461 const char *environment,
9462 const char *dll_name)
9464 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9465 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9466 r->environment = talloc_strdup(mem_ctx, environment);
9467 W_ERROR_HAVE_NO_MEMORY(r->environment);
9468 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9469 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9474 /****************************************************************************
9475 enumprintmonitors level 1.
9476 ****************************************************************************/
9478 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9479 union spoolss_MonitorInfo **info_p,
9482 union spoolss_MonitorInfo *info;
9483 WERROR result = WERR_OK;
9485 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9486 W_ERROR_HAVE_NO_MEMORY(info);
9490 result = fill_monitor_1(info, &info[0].info1,
9492 if (!W_ERROR_IS_OK(result)) {
9496 result = fill_monitor_1(info, &info[1].info1,
9498 if (!W_ERROR_IS_OK(result)) {
9503 if (!W_ERROR_IS_OK(result)) {
9514 /****************************************************************************
9515 enumprintmonitors level 2.
9516 ****************************************************************************/
9518 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9519 union spoolss_MonitorInfo **info_p,
9522 union spoolss_MonitorInfo *info;
9523 WERROR result = WERR_OK;
9524 const char *architecture;
9526 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9527 W_ERROR_HAVE_NO_MEMORY(info);
9531 architecture = lp_parm_const_string(GLOBAL_SECTION_SNUM,
9534 GLOBAL_SPOOLSS_ARCHITECTURE);
9536 result = fill_monitor_2(info, &info[0].info2,
9540 if (!W_ERROR_IS_OK(result)) {
9544 result = fill_monitor_2(info, &info[1].info2,
9548 if (!W_ERROR_IS_OK(result)) {
9553 if (!W_ERROR_IS_OK(result)) {
9564 /****************************************************************
9565 _spoolss_EnumMonitors
9566 ****************************************************************/
9568 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9569 struct spoolss_EnumMonitors *r)
9573 /* that's an [in out] buffer */
9575 if (!r->in.buffer && (r->in.offered != 0)) {
9576 return WERR_INVALID_PARAMETER;
9579 DEBUG(5,("_spoolss_EnumMonitors\n"));
9582 * Enumerate the print monitors ...
9584 * Just reply with "Local Port", to keep NT happy
9585 * and I can use my nice printer checker.
9590 *r->out.info = NULL;
9592 switch (r->in.level) {
9594 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9598 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9602 return WERR_INVALID_LEVEL;
9605 if (!W_ERROR_IS_OK(result)) {
9609 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9610 spoolss_EnumMonitors,
9611 *r->out.info, r->in.level,
9613 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9614 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9616 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9619 /****************************************************************************
9620 ****************************************************************************/
9622 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9623 const print_queue_struct *queue,
9624 int count, int snum,
9625 struct spoolss_PrinterInfo2 *pinfo2,
9628 struct spoolss_JobInfo1 *r)
9633 for (i=0; i<count; i++) {
9634 if (queue[i].sysjob == sysjob) {
9640 if (found == false) {
9641 /* NT treats not found as bad param... yet another bad choice */
9642 return WERR_INVALID_PARAMETER;
9645 return fill_job_info1(mem_ctx,
9654 /****************************************************************************
9655 ****************************************************************************/
9657 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9658 const print_queue_struct *queue,
9659 int count, int snum,
9660 struct spoolss_PrinterInfo2 *pinfo2,
9663 struct spoolss_JobInfo2 *r)
9667 struct spoolss_DeviceMode *devmode;
9670 for (i=0; i<count; i++) {
9671 if (queue[i].sysjob == sysjob) {
9677 if (found == false) {
9678 /* NT treats not found as bad param... yet another bad
9680 return WERR_INVALID_PARAMETER;
9684 * if the print job does not have a DEVMODE associated with it,
9685 * just use the one for the printer. A NULL devicemode is not
9686 * a failure condition
9689 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9691 result = spoolss_create_default_devmode(mem_ctx,
9692 pinfo2->printername,
9694 if (!W_ERROR_IS_OK(result)) {
9695 DEBUG(3, ("Can't proceed w/o a devmode!"));
9700 return fill_job_info2(mem_ctx,
9710 /****************************************************************
9712 ****************************************************************/
9714 WERROR _spoolss_GetJob(struct pipes_struct *p,
9715 struct spoolss_GetJob *r)
9717 WERROR result = WERR_OK;
9718 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9719 const char *svc_name;
9723 struct tdb_print_db *pdb;
9724 print_queue_struct *queue = NULL;
9725 print_status_struct prt_status;
9727 /* that's an [in out] buffer */
9729 if (!r->in.buffer && (r->in.offered != 0)) {
9730 result = WERR_INVALID_PARAMETER;
9731 goto err_jinfo_free;
9734 DEBUG(5,("_spoolss_GetJob\n"));
9738 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9739 result = WERR_INVALID_HANDLE;
9740 goto err_jinfo_free;
9743 svc_name = lp_const_servicename(snum);
9744 if (svc_name == NULL) {
9745 result = WERR_INVALID_PARAMETER;
9746 goto err_jinfo_free;
9749 result = winreg_get_printer_internal(p->mem_ctx,
9750 get_session_info_system(),
9754 if (!W_ERROR_IS_OK(result)) {
9755 goto err_jinfo_free;
9758 pdb = get_print_db_byname(svc_name);
9760 DEBUG(3, ("failed to get print db for svc %s\n", svc_name));
9761 result = WERR_INVALID_PARAMETER;
9762 goto err_pinfo_free;
9765 sysjob = jobid_to_sysjob_pdb(pdb, r->in.job_id);
9766 release_print_db(pdb);
9768 DEBUG(3, ("no sysjob for spoolss jobid %u\n", r->in.job_id));
9769 result = WERR_INVALID_PARAMETER;
9770 goto err_pinfo_free;
9773 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9775 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9776 count, prt_status.status, prt_status.message));
9778 switch (r->in.level) {
9780 result = getjob_level_1(p->mem_ctx,
9781 queue, count, snum, pinfo2,
9782 r->in.job_id, sysjob,
9783 &r->out.info->info1);
9786 result = getjob_level_2(p->mem_ctx,
9787 queue, count, snum, pinfo2,
9788 r->in.job_id, sysjob,
9789 &r->out.info->info2);
9792 result = WERR_INVALID_LEVEL;
9797 TALLOC_FREE(pinfo2);
9799 if (!W_ERROR_IS_OK(result)) {
9800 goto err_jinfo_free;
9803 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9805 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9807 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9810 TALLOC_FREE(pinfo2);
9812 TALLOC_FREE(r->out.info);
9816 /****************************************************************
9817 _spoolss_GetPrinterDataEx
9818 ****************************************************************/
9820 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9821 struct spoolss_GetPrinterDataEx *r)
9824 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9825 const char *printer;
9827 WERROR result = WERR_OK;
9829 enum winreg_Type val_type = REG_NONE;
9830 uint8_t *val_data = NULL;
9831 uint32_t val_size = 0;
9832 struct dcerpc_binding_handle *b;
9833 TALLOC_CTX *tmp_ctx;
9835 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9837 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9838 r->in.key_name, r->in.value_name));
9840 /* in case of problem, return some default values */
9843 *r->out.type = REG_NONE;
9845 tmp_ctx = talloc_new(p->mem_ctx);
9847 return WERR_NOT_ENOUGH_MEMORY;
9851 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9852 OUR_HANDLE(r->in.handle)));
9853 result = WERR_INVALID_HANDLE;
9857 /* Is the handle to a printer or to the server? */
9859 if (Printer->printer_type == SPLHND_SERVER) {
9861 union spoolss_PrinterData data;
9863 result = getprinterdata_printer_server(tmp_ctx,
9867 if (!W_ERROR_IS_OK(result)) {
9871 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9872 *r->out.type, &data);
9873 if (!W_ERROR_IS_OK(result)) {
9877 *r->out.needed = blob.length;
9879 if (r->in.offered >= *r->out.needed) {
9880 memcpy(r->out.data, blob.data, blob.length);
9887 /* check to see if the keyname is valid */
9888 if (!strlen(r->in.key_name)) {
9889 result = WERR_INVALID_PARAMETER;
9893 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9894 result = WERR_INVALID_HANDLE;
9897 printer = lp_const_servicename(snum);
9899 result = winreg_printer_binding_handle(tmp_ctx,
9900 get_session_info_system(),
9903 if (!W_ERROR_IS_OK(result)) {
9907 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9908 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9909 strequal(r->in.value_name, "ChangeId")) {
9910 *r->out.type = REG_DWORD;
9912 if (r->in.offered >= *r->out.needed) {
9913 uint32_t changeid = 0;
9915 result = winreg_printer_get_changeid(tmp_ctx, b,
9918 if (!W_ERROR_IS_OK(result)) {
9922 SIVAL(r->out.data, 0, changeid);
9928 result = winreg_get_printer_dataex(tmp_ctx, b,
9935 if (!W_ERROR_IS_OK(result)) {
9939 *r->out.needed = val_size;
9940 *r->out.type = val_type;
9942 if (r->in.offered >= *r->out.needed) {
9943 memcpy(r->out.data, val_data, val_size);
9947 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9949 if (W_ERROR_IS_OK(result)) {
9950 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9953 talloc_free(tmp_ctx);
9957 /****************************************************************
9958 _spoolss_SetPrinterDataEx
9959 ****************************************************************/
9961 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9962 struct spoolss_SetPrinterDataEx *r)
9964 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9966 WERROR result = WERR_OK;
9967 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9969 struct dcerpc_binding_handle *b;
9970 TALLOC_CTX *tmp_ctx;
9972 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9974 /* From MSDN documentation of SetPrinterDataEx: pass request to
9975 SetPrinterData if key is "PrinterDriverData" */
9978 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9979 OUR_HANDLE(r->in.handle)));
9980 return WERR_INVALID_HANDLE;
9983 if (Printer->printer_type == SPLHND_SERVER) {
9984 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9985 "Not implemented for server handles yet\n"));
9986 return WERR_INVALID_PARAMETER;
9989 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9990 return WERR_INVALID_HANDLE;
9994 * Access check : NT returns "access denied" if you make a
9995 * SetPrinterData call without the necessary privildge.
9996 * we were originally returning OK if nothing changed
9997 * which made Win2k issue **a lot** of SetPrinterData
9998 * when connecting to a printer --jerry
10001 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10002 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
10003 "change denied by handle access permissions\n"));
10004 return WERR_ACCESS_DENIED;
10007 tmp_ctx = talloc_new(p->mem_ctx);
10009 return WERR_NOT_ENOUGH_MEMORY;
10012 result = winreg_printer_binding_handle(tmp_ctx,
10013 get_session_info_system(),
10016 if (!W_ERROR_IS_OK(result)) {
10020 result = winreg_get_printer(tmp_ctx, b,
10021 lp_servicename(talloc_tos(), snum),
10023 if (!W_ERROR_IS_OK(result)) {
10027 /* check for OID in valuename */
10029 oid_string = strchr(r->in.value_name, ',');
10031 *oid_string = '\0';
10035 /* save the registry data */
10037 result = winreg_set_printer_dataex(tmp_ctx, b,
10045 if (W_ERROR_IS_OK(result)) {
10046 /* save the OID if one was specified */
10048 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
10049 r->in.key_name, SPOOL_OID_KEY);
10051 result = WERR_NOT_ENOUGH_MEMORY;
10056 * I'm not checking the status here on purpose. Don't know
10057 * if this is right, but I'm returning the status from the
10058 * previous set_printer_dataex() call. I have no idea if
10059 * this is right. --jerry
10061 winreg_set_printer_dataex(tmp_ctx, b,
10066 (uint8_t *) oid_string,
10067 strlen(oid_string) + 1);
10070 result = winreg_printer_update_changeid(tmp_ctx, b,
10071 lp_const_servicename(snum));
10076 talloc_free(tmp_ctx);
10080 /****************************************************************
10081 _spoolss_DeletePrinterDataEx
10082 ****************************************************************/
10084 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
10085 struct spoolss_DeletePrinterDataEx *r)
10087 const char *printer;
10089 WERROR status = WERR_OK;
10090 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10092 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
10095 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
10096 "Invalid handle (%s:%u:%u).\n",
10097 OUR_HANDLE(r->in.handle)));
10098 return WERR_INVALID_HANDLE;
10101 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10102 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
10103 "printer properties change denied by handle\n"));
10104 return WERR_ACCESS_DENIED;
10107 if (!r->in.value_name || !r->in.key_name) {
10108 return WERR_NOT_ENOUGH_MEMORY;
10111 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10112 return WERR_INVALID_HANDLE;
10114 printer = lp_const_servicename(snum);
10116 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
10117 get_session_info_system(),
10122 if (W_ERROR_IS_OK(status)) {
10123 status = winreg_printer_update_changeid_internal(p->mem_ctx,
10124 get_session_info_system(),
10132 /****************************************************************
10133 _spoolss_EnumPrinterKey
10134 ****************************************************************/
10136 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
10137 struct spoolss_EnumPrinterKey *r)
10140 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10142 WERROR result = WERR_FILE_NOT_FOUND;
10143 const char **array = NULL;
10146 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
10149 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
10150 OUR_HANDLE(r->in.handle)));
10151 return WERR_INVALID_HANDLE;
10154 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10155 return WERR_INVALID_HANDLE;
10158 result = winreg_enum_printer_key_internal(p->mem_ctx,
10159 get_session_info_system(),
10161 lp_const_servicename(snum),
10165 if (!W_ERROR_IS_OK(result)) {
10169 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
10170 result = WERR_NOT_ENOUGH_MEMORY;
10174 *r->out._ndr_size = r->in.offered / 2;
10175 *r->out.needed = blob.length;
10177 if (r->in.offered < *r->out.needed) {
10178 result = WERR_MORE_DATA;
10181 r->out.key_buffer->string_array = array;
10185 if (!W_ERROR_IS_OK(result)) {
10186 TALLOC_FREE(array);
10187 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
10188 *r->out.needed = 0;
10195 /****************************************************************
10196 _spoolss_DeletePrinterKey
10197 ****************************************************************/
10199 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
10200 struct spoolss_DeletePrinterKey *r)
10202 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10205 const char *printer;
10206 struct dcerpc_binding_handle *b;
10207 TALLOC_CTX *tmp_ctx;
10209 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
10212 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
10213 OUR_HANDLE(r->in.handle)));
10214 return WERR_INVALID_HANDLE;
10217 /* if keyname == NULL, return error */
10218 if ( !r->in.key_name )
10219 return WERR_INVALID_PARAMETER;
10221 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10222 return WERR_INVALID_HANDLE;
10225 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
10226 DEBUG(3, ("_spoolss_DeletePrinterKey: "
10227 "printer properties change denied by handle\n"));
10228 return WERR_ACCESS_DENIED;
10231 printer = lp_const_servicename(snum);
10233 tmp_ctx = talloc_new(p->mem_ctx);
10235 return WERR_NOT_ENOUGH_MEMORY;
10238 status = winreg_printer_binding_handle(tmp_ctx,
10239 get_session_info_system(),
10242 if (!W_ERROR_IS_OK(status)) {
10246 /* delete the key and all subkeys */
10247 status = winreg_delete_printer_key(tmp_ctx, b,
10250 if (W_ERROR_IS_OK(status)) {
10251 status = winreg_printer_update_changeid(tmp_ctx, b,
10256 talloc_free(tmp_ctx);
10260 /****************************************************************
10261 _spoolss_EnumPrinterDataEx
10262 ****************************************************************/
10264 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
10265 struct spoolss_EnumPrinterDataEx *r)
10267 uint32_t count = 0;
10268 struct spoolss_PrinterEnumValues *info = NULL;
10269 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10273 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
10276 *r->out.needed = 0;
10277 *r->out.info = NULL;
10280 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
10281 OUR_HANDLE(r->in.handle)));
10282 return WERR_INVALID_HANDLE;
10286 * first check for a keyname of NULL or "". Win2k seems to send
10287 * this a lot and we should send back WERR_INVALID_PARAMETER
10288 * no need to spend time looking up the printer in this case.
10292 if (!strlen(r->in.key_name)) {
10293 result = WERR_INVALID_PARAMETER;
10297 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
10298 return WERR_INVALID_HANDLE;
10301 /* now look for a match on the key name */
10302 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
10303 get_session_info_system(),
10305 lp_const_servicename(snum),
10309 if (!W_ERROR_IS_OK(result)) {
10313 #if 0 /* FIXME - gd */
10314 /* housekeeping information in the reply */
10316 /* Fix from Martin Zielinski <mz@seh.de> - ensure
10317 * the hand marshalled container size is a multiple
10318 * of 4 bytes for RPC alignment.
10322 needed += 4-(needed % 4);
10325 *r->out.count = count;
10326 *r->out.info = info;
10329 if (!W_ERROR_IS_OK(result)) {
10333 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
10334 spoolss_EnumPrinterDataEx,
10337 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
10338 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
10340 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
10343 /****************************************************************************
10344 ****************************************************************************/
10346 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
10347 const char *servername,
10348 const char *environment,
10349 struct spoolss_PrintProcessorDirectoryInfo1 *r)
10354 werr = compose_spoolss_server_path(mem_ctx,
10357 SPOOLSS_PRTPROCS_PATH,
10359 if (!W_ERROR_IS_OK(werr)) {
10363 DEBUG(4,("print processor directory: [%s]\n", path));
10365 r->directory_name = path;
10370 /****************************************************************
10371 _spoolss_GetPrintProcessorDirectory
10372 ****************************************************************/
10374 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
10375 struct spoolss_GetPrintProcessorDirectory *r)
10378 char *prnproc_share = NULL;
10379 bool prnproc_share_exists = false;
10382 /* that's an [in out] buffer */
10384 if (!r->in.buffer && (r->in.offered != 0)) {
10385 result = WERR_INVALID_PARAMETER;
10386 goto err_info_free;
10389 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
10392 *r->out.needed = 0;
10394 /* r->in.level is ignored */
10396 /* We always should reply with a local print processor directory so that
10397 * users are not forced to have a [prnproc$] share on the Samba spoolss
10398 * server, if users decide to do so, lets announce it though - Guenther */
10400 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
10401 if (!prnproc_share) {
10402 result = WERR_NOT_ENOUGH_MEMORY;
10403 goto err_info_free;
10406 prnproc_share_exists = true;
10409 result = getprintprocessordirectory_level_1(p->mem_ctx,
10410 prnproc_share_exists ? r->in.server : NULL,
10412 &r->out.info->info1);
10413 if (!W_ERROR_IS_OK(result)) {
10414 goto err_info_free;
10417 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10418 r->out.info, r->in.level);
10419 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10421 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10424 TALLOC_FREE(r->out.info);
10428 /*******************************************************************
10429 ********************************************************************/
10431 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10432 const char *dllname)
10434 enum ndr_err_code ndr_err;
10435 struct spoolss_MonitorUi ui;
10437 ui.dll_name = dllname;
10439 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10440 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10441 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10442 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10444 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10447 /*******************************************************************
10448 Streams the monitor UI DLL name in UNICODE
10449 *******************************************************************/
10451 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10452 struct security_token *token, DATA_BLOB *in,
10453 DATA_BLOB *out, uint32_t *needed)
10455 const char *dllname = "tcpmonui.dll";
10457 *needed = (strlen(dllname)+1) * 2;
10459 if (out->length < *needed) {
10460 return WERR_INSUFFICIENT_BUFFER;
10463 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10464 return WERR_NOT_ENOUGH_MEMORY;
10470 /*******************************************************************
10471 ********************************************************************/
10473 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10474 struct spoolss_PortData1 *port1,
10475 const DATA_BLOB *buf)
10477 enum ndr_err_code ndr_err;
10478 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10479 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10480 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10481 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10483 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10486 /*******************************************************************
10487 ********************************************************************/
10489 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10490 struct spoolss_PortData2 *port2,
10491 const DATA_BLOB *buf)
10493 enum ndr_err_code ndr_err;
10494 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10495 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10496 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10497 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10499 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10502 /*******************************************************************
10503 Create a new TCP/IP port
10504 *******************************************************************/
10506 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10507 struct security_token *token, DATA_BLOB *in,
10508 DATA_BLOB *out, uint32_t *needed)
10510 struct spoolss_PortData1 port1;
10511 struct spoolss_PortData2 port2;
10512 char *device_uri = NULL;
10515 const char *portname;
10516 const char *hostaddress;
10518 uint32_t port_number;
10521 /* peek for spoolss_PortData version */
10523 if (!in || (in->length < (128 + 4))) {
10524 return WERR_GEN_FAILURE;
10527 version = IVAL(in->data, 128);
10531 ZERO_STRUCT(port1);
10533 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10534 return WERR_NOT_ENOUGH_MEMORY;
10537 portname = port1.portname;
10538 hostaddress = port1.hostaddress;
10539 queue = port1.queue;
10540 protocol = port1.protocol;
10541 port_number = port1.port_number;
10545 ZERO_STRUCT(port2);
10547 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10548 return WERR_NOT_ENOUGH_MEMORY;
10551 portname = port2.portname;
10552 hostaddress = port2.hostaddress;
10553 queue = port2.queue;
10554 protocol = port2.protocol;
10555 port_number = port2.port_number;
10559 DEBUG(1,("xcvtcp_addport: "
10560 "unknown version of port_data: %d\n", version));
10561 return WERR_UNKNOWN_PORT;
10564 /* create the device URI and call the add_port_hook() */
10566 switch (protocol) {
10567 case PROTOCOL_RAWTCP_TYPE:
10568 device_uri = talloc_asprintf(mem_ctx,
10569 "socket://%s:%d/", hostaddress,
10573 case PROTOCOL_LPR_TYPE:
10574 device_uri = talloc_asprintf(mem_ctx,
10575 "lpr://%s/%s", hostaddress, queue );
10579 return WERR_UNKNOWN_PORT;
10583 return WERR_NOT_ENOUGH_MEMORY;
10586 return add_port_hook(mem_ctx, token, portname, device_uri);
10589 /*******************************************************************
10590 *******************************************************************/
10592 struct xcv_api_table xcvtcp_cmds[] = {
10593 { "MonitorUI", xcvtcp_monitorui },
10594 { "AddPort", xcvtcp_addport},
10598 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10599 struct security_token *token, const char *command,
10606 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10608 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10609 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10610 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10613 return WERR_INVALID_FUNCTION;
10616 /*******************************************************************
10617 *******************************************************************/
10618 #if 0 /* don't support management using the "Local Port" monitor */
10620 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10621 struct security_token *token, DATA_BLOB *in,
10622 DATA_BLOB *out, uint32_t *needed)
10624 const char *dllname = "localui.dll";
10626 *needed = (strlen(dllname)+1) * 2;
10628 if (out->length < *needed) {
10629 return WERR_INSUFFICIENT_BUFFER;
10632 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10633 return WERR_NOT_ENOUGH_MEMORY;
10639 /*******************************************************************
10640 *******************************************************************/
10642 struct xcv_api_table xcvlocal_cmds[] = {
10643 { "MonitorUI", xcvlocal_monitorui },
10647 struct xcv_api_table xcvlocal_cmds[] = {
10654 /*******************************************************************
10655 *******************************************************************/
10657 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10658 struct security_token *token, const char *command,
10659 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10664 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10666 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10667 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10668 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10670 return WERR_INVALID_FUNCTION;
10673 /****************************************************************
10675 ****************************************************************/
10677 WERROR _spoolss_XcvData(struct pipes_struct *p,
10678 struct spoolss_XcvData *r)
10680 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10681 DATA_BLOB out_data = data_blob_null;
10685 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10686 OUR_HANDLE(r->in.handle)));
10687 return WERR_INVALID_HANDLE;
10690 /* Has to be a handle to the TCP/IP port monitor */
10692 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10693 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10694 return WERR_INVALID_HANDLE;
10697 /* requires administrative access to the server */
10699 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10700 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10701 return WERR_ACCESS_DENIED;
10704 /* Allocate the outgoing buffer */
10706 if (r->in.out_data_size) {
10707 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10708 if (out_data.data == NULL) {
10709 return WERR_NOT_ENOUGH_MEMORY;
10713 switch ( Printer->printer_type ) {
10714 case SPLHND_PORTMON_TCP:
10715 werror = process_xcvtcp_command(p->mem_ctx,
10716 p->session_info->security_token,
10717 r->in.function_name,
10718 &r->in.in_data, &out_data,
10721 case SPLHND_PORTMON_LOCAL:
10722 werror = process_xcvlocal_command(p->mem_ctx,
10723 p->session_info->security_token,
10724 r->in.function_name,
10725 &r->in.in_data, &out_data,
10729 werror = WERR_INVALID_PRINT_MONITOR;
10732 if (!W_ERROR_IS_OK(werror)) {
10736 *r->out.status_code = 0;
10738 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10739 memcpy(r->out.out_data, out_data.data,
10740 MIN(r->in.out_data_size, out_data.length));
10746 /****************************************************************
10747 _spoolss_AddPrintProcessor
10748 ****************************************************************/
10750 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10751 struct spoolss_AddPrintProcessor *r)
10753 /* for now, just indicate success and ignore the add. We'll
10754 automatically set the winprint processor for printer
10755 entries later. Used to debug the LexMark Optra S 1855 PCL
10761 /****************************************************************
10763 ****************************************************************/
10765 WERROR _spoolss_AddPort(struct pipes_struct *p,
10766 struct spoolss_AddPort *r)
10768 /* do what w2k3 does */
10770 return WERR_NOT_SUPPORTED;
10773 /****************************************************************
10774 _spoolss_GetPrinterDriver
10775 ****************************************************************/
10777 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10778 struct spoolss_GetPrinterDriver *r)
10780 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10781 return WERR_NOT_SUPPORTED;
10784 /****************************************************************
10785 _spoolss_ReadPrinter
10786 ****************************************************************/
10788 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10789 struct spoolss_ReadPrinter *r)
10791 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10792 return WERR_NOT_SUPPORTED;
10795 /****************************************************************
10796 _spoolss_WaitForPrinterChange
10797 ****************************************************************/
10799 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10800 struct spoolss_WaitForPrinterChange *r)
10802 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10803 return WERR_NOT_SUPPORTED;
10806 /****************************************************************
10807 _spoolss_ConfigurePort
10808 ****************************************************************/
10810 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10811 struct spoolss_ConfigurePort *r)
10813 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10814 return WERR_NOT_SUPPORTED;
10817 /****************************************************************
10818 _spoolss_DeletePort
10819 ****************************************************************/
10821 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10822 struct spoolss_DeletePort *r)
10824 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10825 return WERR_NOT_SUPPORTED;
10828 /****************************************************************
10829 _spoolss_CreatePrinterIC
10830 ****************************************************************/
10832 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10833 struct spoolss_CreatePrinterIC *r)
10835 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10836 return WERR_NOT_SUPPORTED;
10839 /****************************************************************
10840 _spoolss_PlayGDIScriptOnPrinterIC
10841 ****************************************************************/
10843 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10844 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10846 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10847 return WERR_NOT_SUPPORTED;
10850 /****************************************************************
10851 _spoolss_DeletePrinterIC
10852 ****************************************************************/
10854 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10855 struct spoolss_DeletePrinterIC *r)
10857 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10858 return WERR_NOT_SUPPORTED;
10861 /****************************************************************
10862 _spoolss_AddPrinterConnection
10863 ****************************************************************/
10865 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10866 struct spoolss_AddPrinterConnection *r)
10868 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10869 return WERR_NOT_SUPPORTED;
10872 /****************************************************************
10873 _spoolss_DeletePrinterConnection
10874 ****************************************************************/
10876 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10877 struct spoolss_DeletePrinterConnection *r)
10879 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10880 return WERR_NOT_SUPPORTED;
10883 /****************************************************************
10884 _spoolss_PrinterMessageBox
10885 ****************************************************************/
10887 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10888 struct spoolss_PrinterMessageBox *r)
10890 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10891 return WERR_NOT_SUPPORTED;
10894 /****************************************************************
10895 _spoolss_AddMonitor
10896 ****************************************************************/
10898 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10899 struct spoolss_AddMonitor *r)
10901 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10902 return WERR_NOT_SUPPORTED;
10905 /****************************************************************
10906 _spoolss_DeleteMonitor
10907 ****************************************************************/
10909 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10910 struct spoolss_DeleteMonitor *r)
10912 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10913 return WERR_NOT_SUPPORTED;
10916 /****************************************************************
10917 _spoolss_DeletePrintProcessor
10918 ****************************************************************/
10920 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10921 struct spoolss_DeletePrintProcessor *r)
10923 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10924 return WERR_NOT_SUPPORTED;
10927 /****************************************************************
10928 _spoolss_AddPrintProvidor
10929 ****************************************************************/
10931 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10932 struct spoolss_AddPrintProvidor *r)
10934 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10935 return WERR_NOT_SUPPORTED;
10938 /****************************************************************
10939 _spoolss_DeletePrintProvidor
10940 ****************************************************************/
10942 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10943 struct spoolss_DeletePrintProvidor *r)
10945 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10946 return WERR_NOT_SUPPORTED;
10949 /****************************************************************
10950 _spoolss_FindFirstPrinterChangeNotification
10951 ****************************************************************/
10953 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10954 struct spoolss_FindFirstPrinterChangeNotification *r)
10956 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10957 return WERR_NOT_SUPPORTED;
10960 /****************************************************************
10961 _spoolss_FindNextPrinterChangeNotification
10962 ****************************************************************/
10964 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10965 struct spoolss_FindNextPrinterChangeNotification *r)
10967 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10968 return WERR_NOT_SUPPORTED;
10971 /****************************************************************
10972 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10973 ****************************************************************/
10975 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10976 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10978 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10979 return WERR_NOT_SUPPORTED;
10982 /****************************************************************
10983 _spoolss_ReplyOpenPrinter
10984 ****************************************************************/
10986 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10987 struct spoolss_ReplyOpenPrinter *r)
10989 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10990 return WERR_NOT_SUPPORTED;
10993 /****************************************************************
10994 _spoolss_RouterReplyPrinter
10995 ****************************************************************/
10997 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10998 struct spoolss_RouterReplyPrinter *r)
11000 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11001 return WERR_NOT_SUPPORTED;
11004 /****************************************************************
11005 _spoolss_ReplyClosePrinter
11006 ****************************************************************/
11008 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
11009 struct spoolss_ReplyClosePrinter *r)
11011 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11012 return WERR_NOT_SUPPORTED;
11015 /****************************************************************
11017 ****************************************************************/
11019 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
11020 struct spoolss_AddPortEx *r)
11022 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11023 return WERR_NOT_SUPPORTED;
11026 /****************************************************************
11027 _spoolss_RouterFindFirstPrinterChangeNotification
11028 ****************************************************************/
11030 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
11031 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
11033 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11034 return WERR_NOT_SUPPORTED;
11037 /****************************************************************
11038 _spoolss_SpoolerInit
11039 ****************************************************************/
11041 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
11042 struct spoolss_SpoolerInit *r)
11044 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11045 return WERR_NOT_SUPPORTED;
11048 /****************************************************************
11049 _spoolss_ResetPrinterEx
11050 ****************************************************************/
11052 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
11053 struct spoolss_ResetPrinterEx *r)
11055 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11056 return WERR_NOT_SUPPORTED;
11059 /****************************************************************
11060 _spoolss_RouterReplyPrinterEx
11061 ****************************************************************/
11063 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
11064 struct spoolss_RouterReplyPrinterEx *r)
11066 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11067 return WERR_NOT_SUPPORTED;
11070 /****************************************************************
11072 ****************************************************************/
11074 WERROR _spoolss_44(struct pipes_struct *p,
11075 struct spoolss_44 *r)
11077 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11078 return WERR_NOT_SUPPORTED;
11081 /****************************************************************
11083 ****************************************************************/
11085 WERROR _spoolss_SetPort(struct pipes_struct *p,
11086 struct spoolss_SetPort *r)
11088 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11089 return WERR_NOT_SUPPORTED;
11092 /****************************************************************
11094 ****************************************************************/
11096 WERROR _spoolss_4a(struct pipes_struct *p,
11097 struct spoolss_4a *r)
11099 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11100 return WERR_NOT_SUPPORTED;
11103 /****************************************************************
11105 ****************************************************************/
11107 WERROR _spoolss_4b(struct pipes_struct *p,
11108 struct spoolss_4b *r)
11110 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11111 return WERR_NOT_SUPPORTED;
11114 /****************************************************************
11116 ****************************************************************/
11118 WERROR _spoolss_4c(struct pipes_struct *p,
11119 struct spoolss_4c *r)
11121 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11122 return WERR_NOT_SUPPORTED;
11125 /****************************************************************
11127 ****************************************************************/
11129 WERROR _spoolss_53(struct pipes_struct *p,
11130 struct spoolss_53 *r)
11132 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11133 return WERR_NOT_SUPPORTED;
11136 /****************************************************************
11137 _spoolss_AddPerMachineConnection
11138 ****************************************************************/
11140 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
11141 struct spoolss_AddPerMachineConnection *r)
11143 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11144 return WERR_NOT_SUPPORTED;
11147 /****************************************************************
11148 _spoolss_DeletePerMachineConnection
11149 ****************************************************************/
11151 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
11152 struct spoolss_DeletePerMachineConnection *r)
11154 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11155 return WERR_NOT_SUPPORTED;
11158 /****************************************************************
11159 _spoolss_EnumPerMachineConnections
11160 ****************************************************************/
11162 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
11163 struct spoolss_EnumPerMachineConnections *r)
11165 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11166 return WERR_NOT_SUPPORTED;
11169 /****************************************************************
11171 ****************************************************************/
11173 WERROR _spoolss_5a(struct pipes_struct *p,
11174 struct spoolss_5a *r)
11176 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11177 return WERR_NOT_SUPPORTED;
11180 /****************************************************************
11182 ****************************************************************/
11184 WERROR _spoolss_5b(struct pipes_struct *p,
11185 struct spoolss_5b *r)
11187 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11188 return WERR_NOT_SUPPORTED;
11191 /****************************************************************
11193 ****************************************************************/
11195 WERROR _spoolss_5c(struct pipes_struct *p,
11196 struct spoolss_5c *r)
11198 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11199 return WERR_NOT_SUPPORTED;
11202 /****************************************************************
11204 ****************************************************************/
11206 WERROR _spoolss_5d(struct pipes_struct *p,
11207 struct spoolss_5d *r)
11209 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11210 return WERR_NOT_SUPPORTED;
11213 /****************************************************************
11215 ****************************************************************/
11217 WERROR _spoolss_5e(struct pipes_struct *p,
11218 struct spoolss_5e *r)
11220 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11221 return WERR_NOT_SUPPORTED;
11224 /****************************************************************
11226 ****************************************************************/
11228 WERROR _spoolss_5f(struct pipes_struct *p,
11229 struct spoolss_5f *r)
11231 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11232 return WERR_NOT_SUPPORTED;
11235 /****************************************************************
11237 ****************************************************************/
11239 WERROR _spoolss_60(struct pipes_struct *p,
11240 struct spoolss_60 *r)
11242 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11243 return WERR_NOT_SUPPORTED;
11246 /****************************************************************
11247 _spoolss_SendRecvBidiData
11248 ****************************************************************/
11250 WERROR _spoolss_SendRecvBidiData(struct pipes_struct *p,
11251 struct spoolss_SendRecvBidiData *r)
11253 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11254 return WERR_NOT_SUPPORTED;
11257 /****************************************************************
11259 ****************************************************************/
11261 WERROR _spoolss_62(struct pipes_struct *p,
11262 struct spoolss_62 *r)
11264 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11265 return WERR_NOT_SUPPORTED;
11268 /****************************************************************
11270 ****************************************************************/
11272 WERROR _spoolss_63(struct pipes_struct *p,
11273 struct spoolss_63 *r)
11275 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11276 return WERR_NOT_SUPPORTED;
11279 /****************************************************************
11281 ****************************************************************/
11283 WERROR _spoolss_64(struct pipes_struct *p,
11284 struct spoolss_64 *r)
11286 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11287 return WERR_NOT_SUPPORTED;
11290 /****************************************************************
11292 ****************************************************************/
11294 WERROR _spoolss_65(struct pipes_struct *p,
11295 struct spoolss_65 *r)
11297 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11298 return WERR_NOT_SUPPORTED;
11301 /****************************************************************
11302 _spoolss_GetCorePrinterDrivers
11303 ****************************************************************/
11305 HRESULT _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
11306 struct spoolss_GetCorePrinterDrivers *r)
11308 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11309 return HRES_ERROR_NOT_SUPPORTED;
11312 /****************************************************************
11314 ****************************************************************/
11316 WERROR _spoolss_67(struct pipes_struct *p,
11317 struct spoolss_67 *r)
11319 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11320 return WERR_NOT_SUPPORTED;
11323 /****************************************************************
11324 _spoolss_GetPrinterDriverPackagePath
11325 ****************************************************************/
11327 HRESULT _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
11328 struct spoolss_GetPrinterDriverPackagePath *r)
11330 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11331 return HRES_ERROR_NOT_SUPPORTED;
11334 /****************************************************************
11336 ****************************************************************/
11338 WERROR _spoolss_69(struct pipes_struct *p,
11339 struct spoolss_69 *r)
11341 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11342 return WERR_NOT_SUPPORTED;
11345 /****************************************************************
11347 ****************************************************************/
11349 WERROR _spoolss_6a(struct pipes_struct *p,
11350 struct spoolss_6a *r)
11352 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11353 return WERR_NOT_SUPPORTED;
11356 /****************************************************************
11358 ****************************************************************/
11360 WERROR _spoolss_6b(struct pipes_struct *p,
11361 struct spoolss_6b *r)
11363 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11364 return WERR_NOT_SUPPORTED;
11367 /****************************************************************
11369 ****************************************************************/
11371 WERROR _spoolss_6c(struct pipes_struct *p,
11372 struct spoolss_6c *r)
11374 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11375 return WERR_NOT_SUPPORTED;
11378 /****************************************************************
11380 ****************************************************************/
11382 WERROR _spoolss_6d(struct pipes_struct *p,
11383 struct spoolss_6d *r)
11385 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11386 return WERR_NOT_SUPPORTED;
11389 /****************************************************************
11390 _spoolss_GetJobNamedPropertyValue
11391 ****************************************************************/
11393 WERROR _spoolss_GetJobNamedPropertyValue(struct pipes_struct *p,
11394 struct spoolss_GetJobNamedPropertyValue *r)
11396 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11397 return WERR_NOT_SUPPORTED;
11400 /****************************************************************
11401 _spoolss_SetJobNamedProperty
11402 ****************************************************************/
11404 WERROR _spoolss_SetJobNamedProperty(struct pipes_struct *p,
11405 struct spoolss_SetJobNamedProperty *r)
11407 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11408 return WERR_NOT_SUPPORTED;
11411 /****************************************************************
11412 _spoolss_DeleteJobNamedProperty
11413 ****************************************************************/
11415 WERROR _spoolss_DeleteJobNamedProperty(struct pipes_struct *p,
11416 struct spoolss_DeleteJobNamedProperty *r)
11418 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11419 return WERR_NOT_SUPPORTED;
11422 /****************************************************************
11423 _spoolss_EnumJobNamedProperties
11424 ****************************************************************/
11426 WERROR _spoolss_EnumJobNamedProperties(struct pipes_struct *p,
11427 struct spoolss_EnumJobNamedProperties *r)
11429 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11430 return WERR_NOT_SUPPORTED;
11433 /****************************************************************
11435 ****************************************************************/
11437 WERROR _spoolss_72(struct pipes_struct *p,
11438 struct spoolss_72 *r)
11440 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11441 return WERR_NOT_SUPPORTED;
11444 /****************************************************************
11446 ****************************************************************/
11448 WERROR _spoolss_73(struct pipes_struct *p,
11449 struct spoolss_73 *r)
11451 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11452 return WERR_NOT_SUPPORTED;
11455 /****************************************************************
11456 _spoolss_RpcLogJobInfoForBranchOffice
11457 ****************************************************************/
11459 WERROR _spoolss_LogJobInfoForBranchOffice(struct pipes_struct *p,
11460 struct spoolss_LogJobInfoForBranchOffice *r)
11462 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11463 return WERR_NOT_SUPPORTED;