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"
59 /* macros stolen from s4 spoolss server */
60 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
61 ((info)?ndr_size_##fn(info, level, 0):0)
63 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
64 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
66 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
67 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
69 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
72 #define DBGC_CLASS DBGC_RPC_SRV
74 #ifndef MAX_OPEN_PRINTER_EXS
75 #define MAX_OPEN_PRINTER_EXS 50
78 struct notify_back_channel;
80 /* structure to store the printer handles */
81 /* and a reference to what it's pointing to */
82 /* and the notify info asked about */
83 /* that's the central struct */
84 struct printer_handle {
85 struct printer_handle *prev, *next;
86 bool document_started;
88 uint32 jobid; /* jobid in printing backend */
90 const char *servername;
93 uint32 access_granted;
99 struct spoolss_NotifyOption *option;
100 struct policy_handle cli_hnd;
101 struct notify_back_channel *cli_chan;
103 /* are we in a FindNextPrinterChangeNotify() call? */
105 struct messaging_context *msg_ctx;
112 /* devmode sent in the OpenPrinter() call */
113 struct spoolss_DeviceMode *devmode;
115 /* TODO cache the printer info2 structure */
116 struct spoolss_PrinterInfo2 *info2;
120 static struct printer_handle *printers_list;
122 struct printer_session_counter {
123 struct printer_session_counter *next;
124 struct printer_session_counter *prev;
130 static struct printer_session_counter *counter_list;
132 struct notify_back_channel {
133 struct notify_back_channel *prev, *next;
135 /* associated client */
136 struct sockaddr_storage client_address;
138 /* print notify back-channel pipe handle*/
139 struct rpc_pipe_client *cli_pipe;
140 uint32_t active_connections;
143 static struct notify_back_channel *back_channels;
145 /* Map generic permissions to printer object specific permissions */
147 const struct standard_mapping printer_std_mapping = {
154 /* Map generic permissions to print server object specific permissions */
156 const struct standard_mapping printserver_std_mapping = {
163 /* API table for Xcv Monitor functions */
165 struct xcv_api_table {
167 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
170 static void prune_printername_cache(void);
172 /********************************************************************
173 * Canonicalize servername.
174 ********************************************************************/
176 static const char *canon_servername(const char *servername)
178 const char *pservername = servername;
179 while (*pservername == '\\') {
185 /* translate between internal status numbers and NT status numbers */
186 static int nt_printj_status(int v)
192 return JOB_STATUS_PAUSED;
194 return JOB_STATUS_SPOOLING;
196 return JOB_STATUS_PRINTING;
198 return JOB_STATUS_ERROR;
200 return JOB_STATUS_DELETING;
202 return JOB_STATUS_OFFLINE;
204 return JOB_STATUS_PAPEROUT;
206 return JOB_STATUS_PRINTED;
208 return JOB_STATUS_DELETED;
210 return JOB_STATUS_BLOCKED_DEVQ;
211 case LPQ_USER_INTERVENTION:
212 return JOB_STATUS_USER_INTERVENTION;
217 static int nt_printq_status(int v)
221 return PRINTER_STATUS_PAUSED;
230 /***************************************************************************
231 Disconnect from the client
232 ****************************************************************************/
234 static void srv_spoolss_replycloseprinter(int snum,
235 struct printer_handle *prn_hnd)
241 * Tell the specific printing tdb we no longer want messages for this printer
242 * by deregistering our PID.
245 if (!print_notify_deregister_pid(snum)) {
246 DEBUG(0, ("Failed to register our pid for printer %s\n",
247 lp_const_servicename(snum)));
250 /* weird if the test succeeds !!! */
251 if (prn_hnd->notify.cli_chan == NULL ||
252 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
253 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
254 prn_hnd->notify.cli_chan->active_connections == 0) {
255 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
256 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
257 TALLOC_FREE(prn_hnd->notify.cli_chan);
261 status = dcerpc_spoolss_ReplyClosePrinter(
262 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
264 &prn_hnd->notify.cli_hnd,
266 if (!NT_STATUS_IS_OK(status)) {
267 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269 result = ntstatus_to_werror(status);
270 } else if (!W_ERROR_IS_OK(result)) {
271 DEBUG(0, ("reply_close_printer failed [%s].\n",
272 win_errstr(result)));
275 /* if it's the last connection, deconnect the IPC$ share */
276 if (prn_hnd->notify.cli_chan->active_connections == 1) {
278 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
279 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
280 TALLOC_FREE(prn_hnd->notify.cli_chan);
282 if (prn_hnd->notify.msg_ctx != NULL) {
283 messaging_deregister(prn_hnd->notify.msg_ctx,
284 MSG_PRINTER_NOTIFY2, NULL);
288 if (prn_hnd->notify.cli_chan) {
289 prn_hnd->notify.cli_chan->active_connections--;
290 prn_hnd->notify.cli_chan = NULL;
294 /****************************************************************************
295 Functions to free a printer entry datastruct.
296 ****************************************************************************/
298 static int printer_entry_destructor(struct printer_handle *Printer)
300 if (Printer->notify.cli_chan != NULL &&
301 Printer->notify.cli_chan->active_connections > 0) {
304 switch(Printer->printer_type) {
306 srv_spoolss_replycloseprinter(snum, Printer);
310 snum = print_queue_snum(Printer->sharename);
312 srv_spoolss_replycloseprinter(snum, Printer);
320 Printer->notify.flags=0;
321 Printer->notify.options=0;
322 Printer->notify.localmachine[0]='\0';
323 Printer->notify.printerlocal=0;
324 TALLOC_FREE(Printer->notify.option);
325 TALLOC_FREE(Printer->devmode);
327 /* Remove from the internal list. */
328 DLIST_REMOVE(printers_list, Printer);
332 /****************************************************************************
333 find printer index by handle
334 ****************************************************************************/
336 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
337 struct policy_handle *hnd)
339 struct printer_handle *find_printer = NULL;
341 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
342 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
349 /****************************************************************************
350 Close printer index by handle.
351 ****************************************************************************/
353 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
355 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
358 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
363 close_policy_hnd(p, hnd);
368 /****************************************************************************
369 Delete a printer given a handle.
370 ****************************************************************************/
372 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
373 const char *sharename,
374 struct messaging_context *msg_ctx)
376 char *cmd = lp_deleteprinter_cmd();
377 char *command = NULL;
379 bool is_print_op = false;
381 /* can't fail if we don't try */
386 command = talloc_asprintf(ctx,
393 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
395 DEBUG(10,("Running [%s]\n", command));
397 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
402 if ( (ret = smbrun(command, NULL)) == 0 ) {
403 /* Tell everyone we updated smb.conf. */
404 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
410 /********** END SePrintOperatorPrivlege BLOCK **********/
412 DEBUGADD(10,("returned [%d]\n", ret));
414 TALLOC_FREE(command);
417 return WERR_BADFID; /* What to return here? */
422 /****************************************************************************
423 Delete a printer given a handle.
424 ****************************************************************************/
426 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
428 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
432 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
438 * It turns out that Windows allows delete printer on a handle
439 * opened by an admin user, then used on a pipe handle created
440 * by an anonymous user..... but they're working on security.... riiight !
444 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
445 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
446 return WERR_ACCESS_DENIED;
449 /* this does not need a become root since the access check has been
450 done on the handle already */
452 result = winreg_delete_printer_key_internal(p->mem_ctx,
453 get_session_info_system(),
457 if (!W_ERROR_IS_OK(result)) {
458 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
462 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
463 Printer->sharename, p->msg_ctx);
464 if (!W_ERROR_IS_OK(result)) {
467 prune_printername_cache();
471 /****************************************************************************
472 Return the snum of a printer corresponding to an handle.
473 ****************************************************************************/
475 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
476 int *number, struct share_params **params)
478 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
481 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
486 switch (Printer->printer_type) {
488 DEBUG(4,("short name:%s\n", Printer->sharename));
489 *number = print_queue_snum(Printer->sharename);
490 return (*number != -1);
498 /****************************************************************************
499 Set printer handle type.
500 Check if it's \\server or \\server\printer
501 ****************************************************************************/
503 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
505 DEBUG(3,("Setting printer type=%s\n", handlename));
507 /* it's a print server */
508 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
509 DEBUGADD(4,("Printer is a print server\n"));
510 Printer->printer_type = SPLHND_SERVER;
512 /* it's a printer (set_printer_hnd_name() will handle port monitors */
514 DEBUGADD(4,("Printer is a printer\n"));
515 Printer->printer_type = SPLHND_PRINTER;
521 static void prune_printername_cache_fn(const char *key, const char *value,
522 time_t timeout, void *private_data)
527 static void prune_printername_cache(void)
529 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
532 /****************************************************************************
533 Set printer handle name.. Accept names like \\server, \\server\printer,
534 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
535 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
536 XcvDataPort() interface.
537 ****************************************************************************/
539 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
540 const struct auth_session_info *session_info,
541 struct messaging_context *msg_ctx,
542 struct printer_handle *Printer,
543 const char *handlename)
546 int n_services=lp_numservices();
548 const char *printername;
549 const char *servername = NULL;
552 struct spoolss_PrinterInfo2 *info2 = NULL;
557 * Hopefully nobody names his printers like this. Maybe \ or ,
558 * are illegal in printer names even?
560 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
564 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
565 (unsigned long)strlen(handlename)));
567 aprinter = discard_const_p(char, handlename);
568 if ( *handlename == '\\' ) {
569 servername = canon_servername(handlename);
570 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
574 if (!is_myname_or_ipaddr(servername)) {
575 return WERR_INVALID_PRINTER_NAME;
577 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
578 if (Printer->servername == NULL) {
583 if (Printer->printer_type == SPLHND_SERVER) {
587 if (Printer->printer_type != SPLHND_PRINTER) {
588 return WERR_INVALID_HANDLE;
591 DEBUGADD(5, ("searching for [%s]\n", aprinter));
593 p = strchr(aprinter, ',');
600 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
602 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
608 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
611 /* check for the Port Monitor Interface */
612 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
613 Printer->printer_type = SPLHND_PORTMON_TCP;
614 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
617 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
618 Printer->printer_type = SPLHND_PORTMON_LOCAL;
619 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
624 * With hundreds of printers, the "for" loop iterating all
625 * shares can be quite expensive, as it is done on every
626 * OpenPrinter. The loop maps "aprinter" to "sname", the
627 * result of which we cache in gencache.
630 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
632 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
634 found = (strcmp(tmp, printer_not_found) != 0);
636 DEBUG(4, ("Printer %s not found\n", aprinter));
638 return WERR_INVALID_PRINTER_NAME;
644 /* Search all sharenames first as this is easier than pulling
645 the printer_info_2 off of disk. Don't use find_service() since
646 that calls out to map_username() */
648 /* do another loop to look for printernames */
649 for (snum = 0; !found && snum < n_services; snum++) {
650 const char *printer = lp_const_servicename(snum);
652 /* no point going on if this is not a printer */
653 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
657 /* ignore [printers] share */
658 if (strequal(printer, "printers")) {
662 fstrcpy(sname, printer);
663 if (strequal(aprinter, printer)) {
668 /* no point looking up the printer object if
669 we aren't allowing printername != sharename */
670 if (lp_force_printername(snum)) {
674 result = winreg_get_printer_internal(mem_ctx,
679 if ( !W_ERROR_IS_OK(result) ) {
680 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
681 sname, win_errstr(result)));
685 printername = strrchr(info2->printername, '\\');
686 if (printername == NULL) {
687 printername = info2->printername;
692 if (strequal(printername, aprinter)) {
697 DEBUGADD(10, ("printername: %s\n", printername));
703 if (cache_key != NULL) {
704 gencache_set(cache_key, printer_not_found,
706 TALLOC_FREE(cache_key);
708 DEBUGADD(4,("Printer not found\n"));
709 return WERR_INVALID_PRINTER_NAME;
712 if (cache_key != NULL) {
713 gencache_set(cache_key, sname, time(NULL)+300);
714 TALLOC_FREE(cache_key);
717 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
719 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
724 /****************************************************************************
725 Find first available printer slot. creates a printer handle for you.
726 ****************************************************************************/
728 static WERROR open_printer_hnd(struct pipes_struct *p,
729 struct policy_handle *hnd,
731 uint32_t access_granted)
733 struct printer_handle *new_printer;
736 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
738 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
739 if (new_printer == NULL) {
742 talloc_set_destructor(new_printer, printer_entry_destructor);
744 /* This also steals the printer_handle on the policy_handle */
745 if (!create_policy_hnd(p, hnd, new_printer)) {
746 TALLOC_FREE(new_printer);
747 return WERR_INVALID_HANDLE;
750 /* Add to the internal list. */
751 DLIST_ADD(printers_list, new_printer);
753 new_printer->notify.option=NULL;
755 if (!set_printer_hnd_printertype(new_printer, name)) {
756 close_printer_handle(p, hnd);
757 return WERR_INVALID_HANDLE;
760 result = set_printer_hnd_name(p->mem_ctx,
761 get_session_info_system(),
764 if (!W_ERROR_IS_OK(result)) {
765 close_printer_handle(p, hnd);
769 new_printer->access_granted = access_granted;
771 DEBUG(5, ("%d printer handles active\n",
772 (int)num_pipe_handles(p)));
777 /***************************************************************************
778 check to see if the client motify handle is monitoring the notification
779 given by (notify_type, notify_field).
780 **************************************************************************/
782 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
783 uint16_t notify_field)
788 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
789 uint16_t notify_field)
791 struct spoolss_NotifyOption *option = p->notify.option;
795 * Flags should always be zero when the change notify
796 * is registered by the client's spooler. A user Win32 app
797 * might use the flags though instead of the NOTIFY_OPTION_INFO
806 return is_monitoring_event_flags(
807 p->notify.flags, notify_type, notify_field);
809 for (i = 0; i < option->count; i++) {
811 /* Check match for notify_type */
813 if (option->types[i].type != notify_type)
816 /* Check match for field */
818 for (j = 0; j < option->types[i].count; j++) {
819 if (option->types[i].fields[j].field == notify_field) {
825 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
826 p->servername, p->sharename, notify_type, notify_field));
831 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
832 _data->data.integer[0] = _integer; \
833 _data->data.integer[1] = 0;
836 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
837 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
838 if (!_data->data.string.string) {\
839 _data->data.string.size = 0; \
841 _data->data.string.size = strlen_m_term(_p) * 2;
843 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
844 _data->data.devmode.devmode = _devmode;
846 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
847 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
848 if (!_data->data.sd.sd) { \
849 _data->data.sd.sd_size = 0; \
851 _data->data.sd.sd_size = \
852 ndr_size_security_descriptor(_data->data.sd.sd, 0);
854 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
859 struct spoolss_Time st;
863 if (!init_systemtime(&st, t)) {
867 p = talloc_array(mem_ctx, char, len);
873 * Systemtime must be linearized as a set of UINT16's.
874 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
877 SSVAL(p, 0, st.year);
878 SSVAL(p, 2, st.month);
879 SSVAL(p, 4, st.day_of_week);
881 SSVAL(p, 8, st.hour);
882 SSVAL(p, 10, st.minute);
883 SSVAL(p, 12, st.second);
884 SSVAL(p, 14, st.millisecond);
890 /* Convert a notification message to a struct spoolss_Notify */
892 static void notify_one_value(struct spoolss_notify_msg *msg,
893 struct spoolss_Notify *data,
896 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
899 static void notify_string(struct spoolss_notify_msg *msg,
900 struct spoolss_Notify *data,
903 /* The length of the message includes the trailing \0 */
905 data->data.string.size = msg->len * 2;
906 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
907 if (!data->data.string.string) {
908 data->data.string.size = 0;
913 static void notify_system_time(struct spoolss_notify_msg *msg,
914 struct spoolss_Notify *data,
917 data->data.string.string = NULL;
918 data->data.string.size = 0;
920 if (msg->len != sizeof(time_t)) {
921 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
926 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
927 &data->data.string.string,
928 &data->data.string.size);
931 struct notify2_message_table {
933 void (*fn)(struct spoolss_notify_msg *msg,
934 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
937 static struct notify2_message_table printer_notify_table[] = {
938 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
939 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
940 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
941 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
942 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
943 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
944 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
945 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
946 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
947 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
948 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
949 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
950 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
951 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
952 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
953 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
954 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
955 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
956 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
959 static struct notify2_message_table job_notify_table[] = {
960 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
961 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
962 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
963 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
964 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
965 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
966 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
967 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
968 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
969 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
970 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
971 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
972 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
973 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
974 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
975 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
976 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
977 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
978 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
979 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
980 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
981 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
982 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
983 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
987 /***********************************************************************
988 Allocate talloc context for container object
989 **********************************************************************/
991 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
996 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1001 /***********************************************************************
1002 release all allocated memory and zero out structure
1003 **********************************************************************/
1005 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1011 talloc_destroy(ctr->ctx);
1018 /***********************************************************************
1019 **********************************************************************/
1021 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1029 /***********************************************************************
1030 **********************************************************************/
1032 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1034 if ( !ctr || !ctr->msg_groups )
1037 if ( idx >= ctr->num_groups )
1040 return &ctr->msg_groups[idx];
1044 /***********************************************************************
1045 How many groups of change messages do we have ?
1046 **********************************************************************/
1048 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1053 return ctr->num_groups;
1056 /***********************************************************************
1057 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1058 **********************************************************************/
1060 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1062 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1063 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1064 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1070 /* loop over all groups looking for a matching printer name */
1072 for ( i=0; i<ctr->num_groups; i++ ) {
1073 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1077 /* add a new group? */
1079 if ( i == ctr->num_groups ) {
1082 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1083 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1086 ctr->msg_groups = groups;
1088 /* clear the new entry and set the printer name */
1090 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1091 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1094 /* add the change messages; 'i' is the correct index now regardless */
1096 msg_grp = &ctr->msg_groups[i];
1098 msg_grp->num_msgs++;
1100 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1101 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1104 msg_grp->msgs = msg_list;
1106 new_slot = msg_grp->num_msgs-1;
1107 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1109 /* need to allocate own copy of data */
1111 if ( msg->len != 0 )
1112 msg_grp->msgs[new_slot].notify.data = (char *)
1113 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1115 return ctr->num_groups;
1118 static void construct_info_data(struct spoolss_Notify *info_data,
1119 enum spoolss_NotifyType type,
1120 uint16_t field, int id);
1122 /***********************************************************************
1123 Send a change notication message on all handles which have a call
1125 **********************************************************************/
1127 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1128 struct printer_handle *prn_hnd,
1129 SPOOLSS_NOTIFY_MSG *messages,
1131 struct spoolss_Notify **_notifies,
1134 struct spoolss_Notify *notifies;
1135 SPOOLSS_NOTIFY_MSG *msg;
1140 notifies = talloc_zero_array(mem_ctx,
1141 struct spoolss_Notify, num_msgs);
1146 for (i = 0; i < num_msgs; i++) {
1150 /* Are we monitoring this event? */
1152 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1156 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1157 "for printer [%s]\n",
1158 msg->type, msg->field, prn_hnd->sharename));
1161 * if the is a printer notification handle and not a job
1162 * notification type, then set the id to 0.
1163 * Otherwise just use what was specified in the message.
1165 * When registering change notification on a print server
1166 * handle we always need to send back the id (snum) matching
1167 * the printer for which the change took place.
1168 * For change notify registered on a printer handle,
1169 * this does not matter and the id should be 0.
1174 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1175 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1181 /* Convert unix jobid to smb jobid */
1183 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1184 id = sysjob_to_jobid(msg->id);
1187 DEBUG(3, ("no such unix jobid %d\n",
1193 construct_info_data(¬ifies[count],
1194 msg->type, msg->field, id);
1197 case PRINTER_NOTIFY_TYPE:
1198 if (printer_notify_table[msg->field].fn) {
1199 printer_notify_table[msg->field].fn(msg,
1200 ¬ifies[count], mem_ctx);
1204 case JOB_NOTIFY_TYPE:
1205 if (job_notify_table[msg->field].fn) {
1206 job_notify_table[msg->field].fn(msg,
1207 ¬ifies[count], mem_ctx);
1212 DEBUG(5, ("Unknown notification type %d\n",
1220 *_notifies = notifies;
1226 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1227 struct printer_handle *prn_hnd,
1228 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1230 struct spoolss_Notify *notifies;
1232 union spoolss_ReplyPrinterInfo info;
1233 struct spoolss_NotifyInfo info0;
1234 uint32_t reply_result;
1239 /* Is there notification on this handle? */
1240 if (prn_hnd->notify.cli_chan == NULL ||
1241 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1242 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1243 prn_hnd->notify.cli_chan->active_connections == 0) {
1247 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1248 prn_hnd->servername, prn_hnd->sharename));
1250 /* For this printer? Print servers always receive notifications. */
1251 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1252 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1256 DEBUG(10,("Our printer\n"));
1258 /* build the array of change notifications */
1259 ret = build_notify2_messages(mem_ctx, prn_hnd,
1261 msg_group->num_msgs,
1267 info0.version = 0x2;
1268 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1269 info0.count = count;
1270 info0.notifies = notifies;
1272 info.info0 = &info0;
1274 status = dcerpc_spoolss_RouterReplyPrinterEx(
1275 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1277 &prn_hnd->notify.cli_hnd,
1278 prn_hnd->notify.change, /* color */
1279 prn_hnd->notify.flags,
1281 0, /* reply_type, must be 0 */
1283 if (!NT_STATUS_IS_OK(status)) {
1284 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1286 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1287 nt_errstr(status)));
1288 werr = ntstatus_to_werror(status);
1289 } else if (!W_ERROR_IS_OK(werr)) {
1290 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1292 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1295 switch (reply_result) {
1298 case PRINTER_NOTIFY_INFO_DISCARDED:
1299 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1300 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1309 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1311 struct printer_handle *p;
1312 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1313 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1317 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1321 if (!msg_group->msgs) {
1322 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1326 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1328 /* loop over all printers */
1330 for (p = printers_list; p; p = p->next) {
1331 ret = send_notify2_printer(mem_ctx, p, msg_group);
1338 DEBUG(8,("send_notify2_changes: Exit...\n"));
1342 /***********************************************************************
1343 **********************************************************************/
1345 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1348 uint32_t tv_sec, tv_usec;
1351 /* Unpack message */
1353 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1356 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1358 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1361 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1362 &msg->notify.value[0], &msg->notify.value[1]);
1364 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1365 &msg->len, &msg->notify.data);
1367 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1368 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1370 tv->tv_sec = tv_sec;
1371 tv->tv_usec = tv_usec;
1374 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1375 msg->notify.value[1]));
1377 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1382 /********************************************************************
1383 Receive a notify2 message list
1384 ********************************************************************/
1386 static void receive_notify2_message_list(struct messaging_context *msg,
1389 struct server_id server_id,
1392 size_t msg_count, i;
1393 char *buf = (char *)data->data;
1396 SPOOLSS_NOTIFY_MSG notify;
1397 SPOOLSS_NOTIFY_MSG_CTR messages;
1400 if (data->length < 4) {
1401 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1405 msg_count = IVAL(buf, 0);
1408 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1410 if (msg_count == 0) {
1411 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1415 /* initialize the container */
1417 ZERO_STRUCT( messages );
1418 notify_msg_ctr_init( &messages );
1421 * build message groups for each printer identified
1422 * in a change_notify msg. Remember that a PCN message
1423 * includes the handle returned for the srv_spoolss_replyopenprinter()
1424 * call. Therefore messages are grouped according to printer handle.
1427 for ( i=0; i<msg_count; i++ ) {
1428 struct timeval msg_tv;
1430 if (msg_ptr + 4 - buf > data->length) {
1431 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1435 msg_len = IVAL(msg_ptr,0);
1438 if (msg_ptr + msg_len - buf > data->length) {
1439 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1443 /* unpack messages */
1445 ZERO_STRUCT( notify );
1446 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1449 /* add to correct list in container */
1451 notify_msg_ctr_addmsg( &messages, ¬ify );
1453 /* free memory that might have been allocated by notify2_unpack_msg() */
1455 if ( notify.len != 0 )
1456 SAFE_FREE( notify.notify.data );
1459 /* process each group of messages */
1461 num_groups = notify_msg_ctr_numgroups( &messages );
1462 for ( i=0; i<num_groups; i++ )
1463 send_notify2_changes( &messages, i );
1468 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1469 (uint32_t)msg_count ));
1471 notify_msg_ctr_destroy( &messages );
1476 /********************************************************************
1477 Send a message to ourself about new driver being installed
1478 so we can upgrade the information for each printer bound to this
1480 ********************************************************************/
1482 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1483 struct messaging_context *msg_ctx)
1485 int len = strlen(drivername);
1490 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1493 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1494 MSG_PRINTER_DRVUPGRADE,
1495 (const uint8_t *)drivername, len+1);
1500 void srv_spoolss_cleanup(void)
1502 struct printer_session_counter *session_counter;
1504 for (session_counter = counter_list;
1505 session_counter != NULL;
1506 session_counter = counter_list) {
1507 DLIST_REMOVE(counter_list, session_counter);
1508 TALLOC_FREE(session_counter);
1512 /**********************************************************************
1513 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1514 over all printers, upgrading ones as necessary
1515 **********************************************************************/
1517 void do_drv_upgrade_printer(struct messaging_context *msg,
1520 struct server_id server_id,
1523 TALLOC_CTX *tmp_ctx;
1524 const struct auth_session_info *session_info = get_session_info_system();
1525 struct spoolss_PrinterInfo2 *pinfo2;
1527 const char *drivername;
1529 int n_services = lp_numservices();
1530 struct dcerpc_binding_handle *b = NULL;
1532 tmp_ctx = talloc_new(NULL);
1533 if (!tmp_ctx) return;
1535 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1537 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1541 DEBUG(10, ("do_drv_upgrade_printer: "
1542 "Got message for new driver [%s]\n", drivername));
1544 /* Iterate the printer list */
1546 for (snum = 0; snum < n_services; snum++) {
1547 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1551 /* ignore [printers] share */
1552 if (strequal(lp_const_servicename(snum), "printers")) {
1557 result = winreg_printer_binding_handle(tmp_ctx,
1561 if (!W_ERROR_IS_OK(result)) {
1566 result = winreg_get_printer(tmp_ctx, b,
1567 lp_const_servicename(snum),
1570 if (!W_ERROR_IS_OK(result)) {
1574 if (!pinfo2->drivername) {
1578 if (strcmp(drivername, pinfo2->drivername) != 0) {
1582 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1584 /* all we care about currently is the change_id */
1585 result = winreg_printer_update_changeid(tmp_ctx, b,
1586 pinfo2->printername);
1588 if (!W_ERROR_IS_OK(result)) {
1589 DEBUG(3, ("do_drv_upgrade_printer: "
1590 "Failed to update changeid [%s]\n",
1591 win_errstr(result)));
1597 talloc_free(tmp_ctx);
1600 /********************************************************************
1601 Update the cache for all printq's with a registered client
1603 ********************************************************************/
1605 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1607 struct printer_handle *printer = printers_list;
1610 /* loop through all printers and update the cache where
1611 a client is connected */
1613 if ((printer->printer_type == SPLHND_PRINTER) &&
1614 ((printer->notify.cli_chan != NULL) &&
1615 (printer->notify.cli_chan->active_connections > 0))) {
1616 snum = print_queue_snum(printer->sharename);
1617 print_queue_status(msg_ctx, snum, NULL, NULL);
1620 printer = printer->next;
1626 /****************************************************************
1627 _spoolss_OpenPrinter
1628 ****************************************************************/
1630 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1631 struct spoolss_OpenPrinter *r)
1633 struct spoolss_OpenPrinterEx e;
1636 ZERO_STRUCT(e.in.userlevel);
1638 e.in.printername = r->in.printername;
1639 e.in.datatype = r->in.datatype;
1640 e.in.devmode_ctr = r->in.devmode_ctr;
1641 e.in.access_mask = r->in.access_mask;
1644 e.out.handle = r->out.handle;
1646 werr = _spoolss_OpenPrinterEx(p, &e);
1648 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1649 /* OpenPrinterEx returns this for a bad
1650 * printer name. We must return WERR_INVALID_PRINTER_NAME
1653 werr = WERR_INVALID_PRINTER_NAME;
1659 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1660 struct spoolss_DeviceMode *orig,
1661 struct spoolss_DeviceMode **dest)
1663 struct spoolss_DeviceMode *dm;
1665 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1670 /* copy all values, then duplicate strings and structs */
1673 dm->devicename = talloc_strdup(dm, orig->devicename);
1674 if (!dm->devicename) {
1677 dm->formname = talloc_strdup(dm, orig->formname);
1678 if (!dm->formname) {
1681 if (orig->driverextra_data.data) {
1682 dm->driverextra_data.data =
1683 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1684 orig->driverextra_data.length);
1685 if (!dm->driverextra_data.data) {
1694 /****************************************************************
1695 _spoolss_OpenPrinterEx
1696 ****************************************************************/
1698 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1699 struct spoolss_OpenPrinterEx *r)
1704 struct printer_handle *Printer=NULL;
1708 if (!r->in.printername) {
1709 return WERR_INVALID_PARAM;
1712 if (!*r->in.printername) {
1713 return WERR_INVALID_PARAM;
1716 if (r->in.level > 3) {
1717 return WERR_INVALID_PARAM;
1719 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1720 (r->in.level == 2 && !r->in.userlevel.level2) ||
1721 (r->in.level == 3 && !r->in.userlevel.level3)) {
1722 return WERR_INVALID_PARAM;
1725 /* some sanity check because you can open a printer or a print server */
1726 /* aka: \\server\printer or \\server */
1728 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1730 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1731 if (!W_ERROR_IS_OK(result)) {
1732 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1733 "for printer %s\n", r->in.printername));
1734 ZERO_STRUCTP(r->out.handle);
1738 Printer = find_printer_index_by_hnd(p, r->out.handle);
1740 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1741 "handle we created for printer %s\n", r->in.printername));
1742 close_printer_handle(p, r->out.handle);
1743 ZERO_STRUCTP(r->out.handle);
1744 return WERR_INVALID_PARAM;
1748 * First case: the user is opening the print server:
1750 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1751 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1753 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1754 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1755 * or if the user is listed in the smb.conf printer admin parameter.
1757 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1758 * client view printer folder, but does not show the MSAPW.
1760 * Note: this test needs code to check access rights here too. Jeremy
1761 * could you look at this?
1763 * Second case: the user is opening a printer:
1764 * NT doesn't let us connect to a printer if the connecting user
1765 * doesn't have print permission.
1767 * Third case: user is opening a Port Monitor
1768 * access checks same as opening a handle to the print server.
1771 switch (Printer->printer_type )
1774 case SPLHND_PORTMON_TCP:
1775 case SPLHND_PORTMON_LOCAL:
1776 /* Printserver handles use global struct... */
1780 /* Map standard access rights to object specific access rights */
1782 se_map_standard(&r->in.access_mask,
1783 &printserver_std_mapping);
1785 /* Deny any object specific bits that don't apply to print
1786 servers (i.e printer and job specific bits) */
1788 r->in.access_mask &= SEC_MASK_SPECIFIC;
1790 if (r->in.access_mask &
1791 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1792 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1793 close_printer_handle(p, r->out.handle);
1794 ZERO_STRUCTP(r->out.handle);
1795 return WERR_ACCESS_DENIED;
1798 /* Allow admin access */
1800 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1802 if (!lp_ms_add_printer_wizard()) {
1803 close_printer_handle(p, r->out.handle);
1804 ZERO_STRUCTP(r->out.handle);
1805 return WERR_ACCESS_DENIED;
1808 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1809 and not a printer admin, then fail */
1811 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1812 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1813 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1814 !token_contains_name_in_list(
1815 uidtoname(p->session_info->unix_token->uid),
1816 p->session_info->info->domain_name,
1818 p->session_info->security_token,
1819 lp_printer_admin(snum))) {
1820 close_printer_handle(p, r->out.handle);
1821 ZERO_STRUCTP(r->out.handle);
1822 DEBUG(3,("access DENIED as user is not root, "
1823 "has no printoperator privilege, "
1824 "not a member of the printoperator builtin group and "
1825 "is not in printer admin list"));
1826 return WERR_ACCESS_DENIED;
1829 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1833 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1836 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1837 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1839 /* We fall through to return WERR_OK */
1842 case SPLHND_PRINTER:
1843 /* NT doesn't let us connect to a printer if the connecting user
1844 doesn't have print permission. */
1846 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1847 close_printer_handle(p, r->out.handle);
1848 ZERO_STRUCTP(r->out.handle);
1852 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1853 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1856 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1858 /* map an empty access mask to the minimum access mask */
1859 if (r->in.access_mask == 0x0)
1860 r->in.access_mask = PRINTER_ACCESS_USE;
1863 * If we are not serving the printer driver for this printer,
1864 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1865 * will keep NT clients happy --jerry
1868 if (lp_use_client_driver(snum)
1869 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1871 r->in.access_mask = PRINTER_ACCESS_USE;
1874 /* check smb.conf parameters and the the sec_desc */
1875 raddr = tsocket_address_inet_addr_string(p->remote_address,
1877 if (raddr == NULL) {
1881 rc = get_remote_hostname(p->remote_address,
1887 if (strequal(rhost, "UNKNOWN")) {
1891 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1893 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1894 ZERO_STRUCTP(r->out.handle);
1895 return WERR_ACCESS_DENIED;
1898 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1899 p->session_info->security_token, snum) ||
1900 !print_access_check(p->session_info,
1903 r->in.access_mask)) {
1904 DEBUG(3, ("access DENIED for printer open\n"));
1905 close_printer_handle(p, r->out.handle);
1906 ZERO_STRUCTP(r->out.handle);
1907 return WERR_ACCESS_DENIED;
1910 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1911 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1912 close_printer_handle(p, r->out.handle);
1913 ZERO_STRUCTP(r->out.handle);
1914 return WERR_ACCESS_DENIED;
1917 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1918 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1920 r->in.access_mask = PRINTER_ACCESS_USE;
1922 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1923 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1925 winreg_create_printer_internal(p->mem_ctx,
1926 get_session_info_system(),
1928 lp_const_servicename(snum));
1933 /* sanity check to prevent programmer error */
1934 ZERO_STRUCTP(r->out.handle);
1938 Printer->access_granted = r->in.access_mask;
1941 * If the client sent a devmode in the OpenPrinter() call, then
1942 * save it here in case we get a job submission on this handle
1945 if ((Printer->printer_type != SPLHND_SERVER) &&
1946 r->in.devmode_ctr.devmode) {
1947 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1951 #if 0 /* JERRY -- I'm doubtful this is really effective */
1952 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1953 optimization in Windows 2000 clients --jerry */
1955 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1956 && (RA_WIN2K == get_remote_arch()) )
1958 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1966 /****************************************************************
1967 _spoolss_ClosePrinter
1968 ****************************************************************/
1970 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1971 struct spoolss_ClosePrinter *r)
1973 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1975 if (Printer && Printer->document_started) {
1976 struct spoolss_EndDocPrinter e;
1978 e.in.handle = r->in.handle;
1980 _spoolss_EndDocPrinter(p, &e);
1983 if (!close_printer_handle(p, r->in.handle))
1986 /* clear the returned printer handle. Observed behavior
1987 from Win2k server. Don't think this really matters.
1988 Previous code just copied the value of the closed
1991 ZERO_STRUCTP(r->out.handle);
1996 /****************************************************************
1997 _spoolss_DeletePrinter
1998 ****************************************************************/
2000 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2001 struct spoolss_DeletePrinter *r)
2003 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2007 if (Printer && Printer->document_started) {
2008 struct spoolss_EndDocPrinter e;
2010 e.in.handle = r->in.handle;
2012 _spoolss_EndDocPrinter(p, &e);
2015 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2016 winreg_delete_printer_key_internal(p->mem_ctx,
2017 get_session_info_system(),
2019 lp_const_servicename(snum),
2023 result = delete_printer_handle(p, r->in.handle);
2028 /*******************************************************************
2029 * static function to lookup the version id corresponding to an
2030 * long architecture string
2031 ******************************************************************/
2033 static const struct print_architecture_table_node archi_table[]= {
2035 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2036 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2037 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2038 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2039 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2040 {"Windows IA64", SPL_ARCH_IA64, 3 },
2041 {"Windows x64", SPL_ARCH_X64, 3 },
2045 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2046 SPOOLSS_DRIVER_VERSION_NT35,
2047 SPOOLSS_DRIVER_VERSION_NT4,
2048 SPOOLSS_DRIVER_VERSION_200X,
2051 static int get_version_id(const char *arch)
2055 for (i=0; archi_table[i].long_archi != NULL; i++)
2057 if (strcmp(arch, archi_table[i].long_archi) == 0)
2058 return (archi_table[i].version);
2064 /****************************************************************
2065 _spoolss_DeletePrinterDriver
2066 ****************************************************************/
2068 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2069 struct spoolss_DeletePrinterDriver *r)
2072 struct spoolss_DriverInfo8 *info = NULL;
2075 struct dcerpc_binding_handle *b;
2076 TALLOC_CTX *tmp_ctx = NULL;
2080 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2081 and not a printer admin, then fail */
2083 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2084 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2085 && !token_contains_name_in_list(
2086 uidtoname(p->session_info->unix_token->uid),
2087 p->session_info->info->domain_name,
2089 p->session_info->security_token,
2090 lp_printer_admin(-1)) )
2092 return WERR_ACCESS_DENIED;
2095 /* check that we have a valid driver name first */
2097 if ((version = get_version_id(r->in.architecture)) == -1) {
2098 return WERR_INVALID_ENVIRONMENT;
2101 tmp_ctx = talloc_new(p->mem_ctx);
2106 status = winreg_printer_binding_handle(tmp_ctx,
2107 get_session_info_system(),
2110 if (!W_ERROR_IS_OK(status)) {
2114 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2115 status = winreg_get_driver(tmp_ctx, b,
2116 r->in.architecture, r->in.driver,
2117 drv_cversion[i], &info);
2118 if (!W_ERROR_IS_OK(status)) {
2119 DEBUG(5, ("skipping del of driver with version %d\n",
2125 if (printer_driver_in_use(tmp_ctx, b, info)) {
2126 status = WERR_PRINTER_DRIVER_IN_USE;
2130 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2131 if (!W_ERROR_IS_OK(status)) {
2132 DEBUG(0, ("failed del of driver with version %d\n",
2137 if (found == false) {
2138 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2139 status = WERR_UNKNOWN_PRINTER_DRIVER;
2145 talloc_free(tmp_ctx);
2150 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2151 struct pipes_struct *p,
2152 struct spoolss_DeletePrinterDriverEx *r,
2153 struct dcerpc_binding_handle *b,
2154 struct spoolss_DriverInfo8 *info)
2159 if (printer_driver_in_use(mem_ctx, b, info)) {
2160 status = WERR_PRINTER_DRIVER_IN_USE;
2165 * we have a couple of cases to consider.
2166 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2167 * then the delete should fail if **any** files overlap with
2169 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2170 * non-overlapping files
2171 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2172 * are set, then do not delete any files
2173 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2176 delete_files = r->in.delete_flags
2177 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2181 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2182 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2183 status = WERR_PRINTER_DRIVER_IN_USE;
2187 * printer_driver_files_in_use() has trimmed overlapping files
2188 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2193 status = winreg_del_driver(mem_ctx, b, info, info->version);
2194 if (!W_ERROR_IS_OK(status)) {
2199 * now delete any associated files if delete_files is
2200 * true. Even if this part failes, we return succes
2201 * because the driver doesn not exist any more
2204 delete_driver_files(get_session_info_system(), info);
2211 /****************************************************************
2212 _spoolss_DeletePrinterDriverEx
2213 ****************************************************************/
2215 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2216 struct spoolss_DeletePrinterDriverEx *r)
2218 struct spoolss_DriverInfo8 *info = NULL;
2220 struct dcerpc_binding_handle *b;
2221 TALLOC_CTX *tmp_ctx = NULL;
2225 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2226 and not a printer admin, then fail */
2228 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2229 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2230 && !token_contains_name_in_list(
2231 uidtoname(p->session_info->unix_token->uid),
2232 p->session_info->info->domain_name,
2234 p->session_info->security_token, lp_printer_admin(-1)) )
2236 return WERR_ACCESS_DENIED;
2239 /* check that we have a valid driver name first */
2240 if (get_version_id(r->in.architecture) == -1) {
2241 /* this is what NT returns */
2242 return WERR_INVALID_ENVIRONMENT;
2245 tmp_ctx = talloc_new(p->mem_ctx);
2250 status = winreg_printer_binding_handle(tmp_ctx,
2251 get_session_info_system(),
2254 if (!W_ERROR_IS_OK(status)) {
2258 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2259 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2260 && (drv_cversion[i] != r->in.version)) {
2264 /* check if a driver with this version exists before delete */
2265 status = winreg_get_driver(tmp_ctx, b,
2266 r->in.architecture, r->in.driver,
2267 drv_cversion[i], &info);
2268 if (!W_ERROR_IS_OK(status)) {
2269 DEBUG(5, ("skipping del of driver with version %d\n",
2275 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2276 if (!W_ERROR_IS_OK(status)) {
2277 DEBUG(0, ("failed to delete driver with version %d\n",
2282 if (found == false) {
2283 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2284 status = WERR_UNKNOWN_PRINTER_DRIVER;
2290 talloc_free(tmp_ctx);
2295 /********************************************************************
2296 GetPrinterData on a printer server Handle.
2297 ********************************************************************/
2299 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2301 enum winreg_Type *type,
2302 union spoolss_PrinterData *data)
2304 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2306 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2312 if (!strcasecmp_m(value, "BeepEnabled")) {
2318 if (!strcasecmp_m(value, "EventLog")) {
2320 /* formally was 0x1b */
2325 if (!strcasecmp_m(value, "NetPopup")) {
2331 if (!strcasecmp_m(value, "MajorVersion")) {
2334 /* Windows NT 4.0 seems to not allow uploading of drivers
2335 to a server that reports 0x3 as the MajorVersion.
2336 need to investigate more how Win2k gets around this .
2339 if (RA_WINNT == get_remote_arch()) {
2348 if (!strcasecmp_m(value, "MinorVersion")) {
2355 * uint32_t size = 0x114
2356 * uint32_t major = 5
2357 * uint32_t minor = [0|1]
2358 * uint32_t build = [2195|2600]
2359 * extra unicode string = e.g. "Service Pack 3"
2361 if (!strcasecmp_m(value, "OSVersion")) {
2363 enum ndr_err_code ndr_err;
2364 struct spoolss_OSVersion os;
2366 os.major = 5; /* Windows 2000 == 5.0 */
2368 os.build = 2195; /* build */
2369 os.extra_string = ""; /* leave extra string empty */
2371 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2372 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2373 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2374 return WERR_GENERAL_FAILURE;
2378 data->binary = blob;
2384 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2387 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2388 W_ERROR_HAVE_NO_MEMORY(data->string);
2393 if (!strcasecmp_m(value, "Architecture")) {
2395 data->string = talloc_strdup(mem_ctx,
2396 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2397 W_ERROR_HAVE_NO_MEMORY(data->string);
2402 if (!strcasecmp_m(value, "DsPresent")) {
2405 /* only show the publish check box if we are a
2406 member of a AD domain */
2408 if (lp_security() == SEC_ADS) {
2416 if (!strcasecmp_m(value, "DNSMachineName")) {
2417 const char *hostname = get_mydnsfullname();
2420 return WERR_BADFILE;
2424 data->string = talloc_strdup(mem_ctx, hostname);
2425 W_ERROR_HAVE_NO_MEMORY(data->string);
2432 return WERR_INVALID_PARAM;
2435 /****************************************************************
2436 _spoolss_GetPrinterData
2437 ****************************************************************/
2439 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2440 struct spoolss_GetPrinterData *r)
2442 struct spoolss_GetPrinterDataEx r2;
2444 r2.in.handle = r->in.handle;
2445 r2.in.key_name = "PrinterDriverData";
2446 r2.in.value_name = r->in.value_name;
2447 r2.in.offered = r->in.offered;
2448 r2.out.type = r->out.type;
2449 r2.out.data = r->out.data;
2450 r2.out.needed = r->out.needed;
2452 return _spoolss_GetPrinterDataEx(p, &r2);
2455 /*********************************************************
2456 Connect to the client machine.
2457 **********************************************************/
2459 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2460 struct sockaddr_storage *client_ss, const char *remote_machine)
2463 struct cli_state *the_cli;
2464 struct sockaddr_storage rm_addr;
2465 char addr[INET6_ADDRSTRLEN];
2467 if ( is_zero_addr(client_ss) ) {
2468 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2470 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2471 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2474 print_sockaddr(addr, sizeof(addr), &rm_addr);
2476 rm_addr = *client_ss;
2477 print_sockaddr(addr, sizeof(addr), &rm_addr);
2478 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2482 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2483 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2488 /* setup the connection */
2489 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2490 &rm_addr, 0, "IPC$", "IPC",
2494 0, lp_client_signing());
2496 if ( !NT_STATUS_IS_OK( ret ) ) {
2497 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2502 if ( cli_state_protocol(the_cli) != PROTOCOL_NT1 ) {
2503 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2504 cli_shutdown(the_cli);
2509 * Ok - we have an anonymous connection to the IPC$ share.
2510 * Now start the NT Domain stuff :-).
2513 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2514 if (!NT_STATUS_IS_OK(ret)) {
2515 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2516 remote_machine, nt_errstr(ret)));
2517 cli_shutdown(the_cli);
2524 /***************************************************************************
2525 Connect to the client.
2526 ****************************************************************************/
2528 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2529 uint32_t localprinter,
2530 enum winreg_Type type,
2531 struct policy_handle *handle,
2532 struct notify_back_channel **_chan,
2533 struct sockaddr_storage *client_ss,
2534 struct messaging_context *msg_ctx)
2538 struct notify_back_channel *chan;
2540 for (chan = back_channels; chan; chan = chan->next) {
2541 if (memcmp(&chan->client_address, client_ss,
2542 sizeof(struct sockaddr_storage)) == 0) {
2548 * If it's the first connection, contact the client
2549 * and connect to the IPC$ share anonymously
2552 fstring unix_printer;
2554 /* the +2 is to strip the leading 2 backslashs */
2555 fstrcpy(unix_printer, printer + 2);
2557 chan = talloc_zero(NULL, struct notify_back_channel);
2561 chan->client_address = *client_ss;
2563 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2568 DLIST_ADD(back_channels, chan);
2570 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2571 receive_notify2_message_list);
2574 if (chan->cli_pipe == NULL ||
2575 chan->cli_pipe->binding_handle == NULL) {
2576 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2577 "NULL %s for printer %s\n",
2578 chan->cli_pipe == NULL ?
2579 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2585 * Tell the specific printing tdb we want messages for this printer
2586 * by registering our PID.
2589 if (!print_notify_register_pid(snum)) {
2590 DEBUG(0, ("Failed to register our pid for printer %s\n",
2594 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2603 if (!NT_STATUS_IS_OK(status)) {
2604 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2605 result = ntstatus_to_werror(status);
2606 } else if (!W_ERROR_IS_OK(result)) {
2607 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2610 chan->active_connections++;
2613 return (W_ERROR_IS_OK(result));
2616 /****************************************************************
2617 ****************************************************************/
2619 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2620 const struct spoolss_NotifyOption *r)
2622 struct spoolss_NotifyOption *option;
2629 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2636 if (!option->count) {
2640 option->types = talloc_zero_array(option,
2641 struct spoolss_NotifyOptionType, option->count);
2642 if (!option->types) {
2643 talloc_free(option);
2647 for (i=0; i < option->count; i++) {
2648 option->types[i] = r->types[i];
2650 if (option->types[i].count) {
2651 option->types[i].fields = talloc_zero_array(option,
2652 union spoolss_Field, option->types[i].count);
2653 if (!option->types[i].fields) {
2654 talloc_free(option);
2657 for (k=0; k<option->types[i].count; k++) {
2658 option->types[i].fields[k] =
2659 r->types[i].fields[k];
2667 /****************************************************************
2668 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2670 * before replying OK: status=0 a rpc call is made to the workstation
2671 * asking ReplyOpenPrinter
2673 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2674 * called from api_spoolss_rffpcnex
2675 ****************************************************************/
2677 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2678 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2681 struct spoolss_NotifyOption *option = r->in.notify_options;
2682 struct sockaddr_storage client_ss;
2685 /* store the notify value in the printer struct */
2687 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2690 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2691 "Invalid handle (%s:%u:%u).\n",
2692 OUR_HANDLE(r->in.handle)));
2696 Printer->notify.flags = r->in.flags;
2697 Printer->notify.options = r->in.options;
2698 Printer->notify.printerlocal = r->in.printer_local;
2699 Printer->notify.msg_ctx = p->msg_ctx;
2701 TALLOC_FREE(Printer->notify.option);
2702 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2704 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2706 /* Connect to the client machine and send a ReplyOpenPrinter */
2708 if ( Printer->printer_type == SPLHND_SERVER)
2710 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2711 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2714 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2715 "remote_address is %s\n",
2716 tsocket_address_string(p->remote_address, p->mem_ctx)));
2718 if (!lp_print_notify_backchannel(snum)) {
2719 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2720 "backchannel disabled\n"));
2721 return WERR_SERVER_UNAVAILABLE;
2724 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2725 (struct sockaddr *) &client_ss,
2726 sizeof(struct sockaddr_storage));
2727 if (client_len < 0) {
2731 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2732 Printer->notify.printerlocal, REG_SZ,
2733 &Printer->notify.cli_hnd,
2734 &Printer->notify.cli_chan,
2735 &client_ss, p->msg_ctx)) {
2736 return WERR_SERVER_UNAVAILABLE;
2742 /*******************************************************************
2743 * fill a notify_info_data with the servername
2744 ********************************************************************/
2746 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2748 struct spoolss_Notify *data,
2749 print_queue_struct *queue,
2750 struct spoolss_PrinterInfo2 *pinfo2,
2751 TALLOC_CTX *mem_ctx)
2753 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2756 /*******************************************************************
2757 * fill a notify_info_data with the printername (not including the servername).
2758 ********************************************************************/
2760 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2762 struct spoolss_Notify *data,
2763 print_queue_struct *queue,
2764 struct spoolss_PrinterInfo2 *pinfo2,
2765 TALLOC_CTX *mem_ctx)
2767 /* the notify name should not contain the \\server\ part */
2768 const char *p = strrchr(pinfo2->printername, '\\');
2771 p = pinfo2->printername;
2776 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2779 /*******************************************************************
2780 * fill a notify_info_data with the servicename
2781 ********************************************************************/
2783 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2785 struct spoolss_Notify *data,
2786 print_queue_struct *queue,
2787 struct spoolss_PrinterInfo2 *pinfo2,
2788 TALLOC_CTX *mem_ctx)
2790 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2793 /*******************************************************************
2794 * fill a notify_info_data with the port name
2795 ********************************************************************/
2797 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2799 struct spoolss_Notify *data,
2800 print_queue_struct *queue,
2801 struct spoolss_PrinterInfo2 *pinfo2,
2802 TALLOC_CTX *mem_ctx)
2804 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2807 /*******************************************************************
2808 * fill a notify_info_data with the printername
2809 * but it doesn't exist, have to see what to do
2810 ********************************************************************/
2812 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2814 struct spoolss_Notify *data,
2815 print_queue_struct *queue,
2816 struct spoolss_PrinterInfo2 *pinfo2,
2817 TALLOC_CTX *mem_ctx)
2819 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2822 /*******************************************************************
2823 * fill a notify_info_data with the comment
2824 ********************************************************************/
2826 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2828 struct spoolss_Notify *data,
2829 print_queue_struct *queue,
2830 struct spoolss_PrinterInfo2 *pinfo2,
2831 TALLOC_CTX *mem_ctx)
2835 if (*pinfo2->comment == '\0') {
2836 p = lp_comment(snum);
2838 p = pinfo2->comment;
2841 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2844 /*******************************************************************
2845 * fill a notify_info_data with the comment
2846 * location = "Room 1, floor 2, building 3"
2847 ********************************************************************/
2849 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2851 struct spoolss_Notify *data,
2852 print_queue_struct *queue,
2853 struct spoolss_PrinterInfo2 *pinfo2,
2854 TALLOC_CTX *mem_ctx)
2856 const char *loc = pinfo2->location;
2859 status = printer_list_get_printer(mem_ctx,
2864 if (NT_STATUS_IS_OK(status)) {
2866 loc = pinfo2->location;
2870 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2873 /*******************************************************************
2874 * fill a notify_info_data with the device mode
2875 * jfm:xxxx don't to it for know but that's a real problem !!!
2876 ********************************************************************/
2878 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2880 struct spoolss_Notify *data,
2881 print_queue_struct *queue,
2882 struct spoolss_PrinterInfo2 *pinfo2,
2883 TALLOC_CTX *mem_ctx)
2885 /* for a dummy implementation we have to zero the fields */
2886 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2889 /*******************************************************************
2890 * fill a notify_info_data with the separator file name
2891 ********************************************************************/
2893 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2895 struct spoolss_Notify *data,
2896 print_queue_struct *queue,
2897 struct spoolss_PrinterInfo2 *pinfo2,
2898 TALLOC_CTX *mem_ctx)
2900 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2903 /*******************************************************************
2904 * fill a notify_info_data with the print processor
2905 * jfm:xxxx return always winprint to indicate we don't do anything to it
2906 ********************************************************************/
2908 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2910 struct spoolss_Notify *data,
2911 print_queue_struct *queue,
2912 struct spoolss_PrinterInfo2 *pinfo2,
2913 TALLOC_CTX *mem_ctx)
2915 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2918 /*******************************************************************
2919 * fill a notify_info_data with the print processor options
2920 * jfm:xxxx send an empty string
2921 ********************************************************************/
2923 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2925 struct spoolss_Notify *data,
2926 print_queue_struct *queue,
2927 struct spoolss_PrinterInfo2 *pinfo2,
2928 TALLOC_CTX *mem_ctx)
2930 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2933 /*******************************************************************
2934 * fill a notify_info_data with the data type
2935 * jfm:xxxx always send RAW as data type
2936 ********************************************************************/
2938 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2940 struct spoolss_Notify *data,
2941 print_queue_struct *queue,
2942 struct spoolss_PrinterInfo2 *pinfo2,
2943 TALLOC_CTX *mem_ctx)
2945 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2948 /*******************************************************************
2949 * fill a notify_info_data with the security descriptor
2950 * jfm:xxxx send an null pointer to say no security desc
2951 * have to implement security before !
2952 ********************************************************************/
2954 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2956 struct spoolss_Notify *data,
2957 print_queue_struct *queue,
2958 struct spoolss_PrinterInfo2 *pinfo2,
2959 TALLOC_CTX *mem_ctx)
2961 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2964 /*******************************************************************
2965 * fill a notify_info_data with the attributes
2966 * jfm:xxxx a samba printer is always shared
2967 ********************************************************************/
2969 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2971 struct spoolss_Notify *data,
2972 print_queue_struct *queue,
2973 struct spoolss_PrinterInfo2 *pinfo2,
2974 TALLOC_CTX *mem_ctx)
2976 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2979 /*******************************************************************
2980 * fill a notify_info_data with the priority
2981 ********************************************************************/
2983 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2985 struct spoolss_Notify *data,
2986 print_queue_struct *queue,
2987 struct spoolss_PrinterInfo2 *pinfo2,
2988 TALLOC_CTX *mem_ctx)
2990 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2993 /*******************************************************************
2994 * fill a notify_info_data with the default priority
2995 ********************************************************************/
2997 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2999 struct spoolss_Notify *data,
3000 print_queue_struct *queue,
3001 struct spoolss_PrinterInfo2 *pinfo2,
3002 TALLOC_CTX *mem_ctx)
3004 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3007 /*******************************************************************
3008 * fill a notify_info_data with the start time
3009 ********************************************************************/
3011 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3013 struct spoolss_Notify *data,
3014 print_queue_struct *queue,
3015 struct spoolss_PrinterInfo2 *pinfo2,
3016 TALLOC_CTX *mem_ctx)
3018 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3021 /*******************************************************************
3022 * fill a notify_info_data with the until time
3023 ********************************************************************/
3025 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3027 struct spoolss_Notify *data,
3028 print_queue_struct *queue,
3029 struct spoolss_PrinterInfo2 *pinfo2,
3030 TALLOC_CTX *mem_ctx)
3032 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3035 /*******************************************************************
3036 * fill a notify_info_data with the status
3037 ********************************************************************/
3039 static void spoolss_notify_status(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 print_status_struct status;
3048 print_queue_length(msg_ctx, snum, &status);
3049 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3052 /*******************************************************************
3053 * fill a notify_info_data with the number of jobs queued
3054 ********************************************************************/
3056 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3058 struct spoolss_Notify *data,
3059 print_queue_struct *queue,
3060 struct spoolss_PrinterInfo2 *pinfo2,
3061 TALLOC_CTX *mem_ctx)
3063 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3064 data, print_queue_length(msg_ctx, snum, NULL));
3067 /*******************************************************************
3068 * fill a notify_info_data with the average ppm
3069 ********************************************************************/
3071 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3073 struct spoolss_Notify *data,
3074 print_queue_struct *queue,
3075 struct spoolss_PrinterInfo2 *pinfo2,
3076 TALLOC_CTX *mem_ctx)
3078 /* always respond 8 pages per minutes */
3079 /* a little hard ! */
3080 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3083 /*******************************************************************
3084 * fill a notify_info_data with username
3085 ********************************************************************/
3087 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3089 struct spoolss_Notify *data,
3090 print_queue_struct *queue,
3091 struct spoolss_PrinterInfo2 *pinfo2,
3092 TALLOC_CTX *mem_ctx)
3094 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3097 /*******************************************************************
3098 * fill a notify_info_data with job status
3099 ********************************************************************/
3101 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3103 struct spoolss_Notify *data,
3104 print_queue_struct *queue,
3105 struct spoolss_PrinterInfo2 *pinfo2,
3106 TALLOC_CTX *mem_ctx)
3108 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3111 /*******************************************************************
3112 * fill a notify_info_data with job name
3113 ********************************************************************/
3115 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3117 struct spoolss_Notify *data,
3118 print_queue_struct *queue,
3119 struct spoolss_PrinterInfo2 *pinfo2,
3120 TALLOC_CTX *mem_ctx)
3122 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3125 /*******************************************************************
3126 * fill a notify_info_data with job status
3127 ********************************************************************/
3129 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3131 struct spoolss_Notify *data,
3132 print_queue_struct *queue,
3133 struct spoolss_PrinterInfo2 *pinfo2,
3134 TALLOC_CTX *mem_ctx)
3137 * Now we're returning job status codes we just return a "" here. JRA.
3142 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3145 switch (queue->status) {
3150 p = ""; /* NT provides the paused string */
3159 #endif /* NO LONGER NEEDED. */
3161 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3164 /*******************************************************************
3165 * fill a notify_info_data with job time
3166 ********************************************************************/
3168 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3170 struct spoolss_Notify *data,
3171 print_queue_struct *queue,
3172 struct spoolss_PrinterInfo2 *pinfo2,
3173 TALLOC_CTX *mem_ctx)
3175 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3178 /*******************************************************************
3179 * fill a notify_info_data with job size
3180 ********************************************************************/
3182 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3184 struct spoolss_Notify *data,
3185 print_queue_struct *queue,
3186 struct spoolss_PrinterInfo2 *pinfo2,
3187 TALLOC_CTX *mem_ctx)
3189 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3192 /*******************************************************************
3193 * fill a notify_info_data with page info
3194 ********************************************************************/
3195 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3197 struct spoolss_Notify *data,
3198 print_queue_struct *queue,
3199 struct spoolss_PrinterInfo2 *pinfo2,
3200 TALLOC_CTX *mem_ctx)
3202 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3205 /*******************************************************************
3206 * fill a notify_info_data with pages printed info.
3207 ********************************************************************/
3208 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3210 struct spoolss_Notify *data,
3211 print_queue_struct *queue,
3212 struct spoolss_PrinterInfo2 *pinfo2,
3213 TALLOC_CTX *mem_ctx)
3215 /* Add code when back-end tracks this */
3216 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3219 /*******************************************************************
3220 Fill a notify_info_data with job position.
3221 ********************************************************************/
3223 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3225 struct spoolss_Notify *data,
3226 print_queue_struct *queue,
3227 struct spoolss_PrinterInfo2 *pinfo2,
3228 TALLOC_CTX *mem_ctx)
3230 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3233 /*******************************************************************
3234 Fill a notify_info_data with submitted time.
3235 ********************************************************************/
3237 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3239 struct spoolss_Notify *data,
3240 print_queue_struct *queue,
3241 struct spoolss_PrinterInfo2 *pinfo2,
3242 TALLOC_CTX *mem_ctx)
3244 data->data.string.string = NULL;
3245 data->data.string.size = 0;
3247 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3248 &data->data.string.string,
3249 &data->data.string.size);
3253 struct s_notify_info_data_table
3255 enum spoolss_NotifyType type;
3258 enum spoolss_NotifyTable variable_type;
3259 void (*fn) (struct messaging_context *msg_ctx,
3260 int snum, struct spoolss_Notify *data,
3261 print_queue_struct *queue,
3262 struct spoolss_PrinterInfo2 *pinfo2,
3263 TALLOC_CTX *mem_ctx);
3266 /* A table describing the various print notification constants and
3267 whether the notification data is a pointer to a variable sized
3268 buffer, a one value uint32_t or a two value uint32_t. */
3270 static const struct s_notify_info_data_table notify_info_data_table[] =
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3283 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3284 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3285 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3286 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3287 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3288 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3289 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3290 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3291 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3292 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3293 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3294 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3295 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3296 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3297 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3306 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3307 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3308 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3309 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3310 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3311 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3312 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3313 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3314 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3315 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3316 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3317 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3318 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3319 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3320 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3323 /*******************************************************************
3324 Return the variable_type of info_data structure.
3325 ********************************************************************/
3327 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3332 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3333 if ( (notify_info_data_table[i].type == type) &&
3334 (notify_info_data_table[i].field == field) ) {
3335 return notify_info_data_table[i].variable_type;
3339 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3341 return (enum spoolss_NotifyTable) 0;
3344 /****************************************************************************
3345 ****************************************************************************/
3347 static bool search_notify(enum spoolss_NotifyType type,
3353 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3354 if (notify_info_data_table[i].type == type &&
3355 notify_info_data_table[i].field == field &&
3356 notify_info_data_table[i].fn != NULL) {
3365 /****************************************************************************
3366 ****************************************************************************/
3368 static void construct_info_data(struct spoolss_Notify *info_data,
3369 enum spoolss_NotifyType type,
3370 uint16_t field, int id)
3372 info_data->type = type;
3373 info_data->field.field = field;
3374 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3375 info_data->job_id = id;
3378 /*******************************************************************
3380 * fill a notify_info struct with info asked
3382 ********************************************************************/
3384 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3385 struct printer_handle *print_hnd,
3386 struct spoolss_NotifyInfo *info,
3387 struct spoolss_PrinterInfo2 *pinfo2,
3389 const struct spoolss_NotifyOptionType *option_type,
3391 TALLOC_CTX *mem_ctx)
3394 enum spoolss_NotifyType type;
3397 struct spoolss_Notify *current_data;
3399 type = option_type->type;
3401 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3402 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3403 option_type->count, lp_servicename(snum)));
3405 for(field_num=0; field_num < option_type->count; field_num++) {
3406 field = option_type->fields[field_num].field;
3408 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3410 if (!search_notify(type, field, &j) )
3413 info->notifies = talloc_realloc(info, info->notifies,
3414 struct spoolss_Notify,
3416 if (info->notifies == NULL) {
3417 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3421 current_data = &info->notifies[info->count];
3423 construct_info_data(current_data, type, field, id);
3425 DEBUG(10, ("construct_notify_printer_info: "
3426 "calling [%s] snum=%d printername=[%s])\n",
3427 notify_info_data_table[j].name, snum,
3428 pinfo2->printername));
3430 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3431 NULL, pinfo2, mem_ctx);
3439 /*******************************************************************
3441 * fill a notify_info struct with info asked
3443 ********************************************************************/
3445 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3446 print_queue_struct *queue,
3447 struct spoolss_NotifyInfo *info,
3448 struct spoolss_PrinterInfo2 *pinfo2,
3450 const struct spoolss_NotifyOptionType *option_type,
3452 TALLOC_CTX *mem_ctx)
3455 enum spoolss_NotifyType type;
3457 struct spoolss_Notify *current_data;
3459 DEBUG(4,("construct_notify_jobs_info\n"));
3461 type = option_type->type;
3463 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3464 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3465 option_type->count));
3467 for(field_num=0; field_num<option_type->count; field_num++) {
3468 field = option_type->fields[field_num].field;
3470 if (!search_notify(type, field, &j) )
3473 info->notifies = talloc_realloc(info, info->notifies,
3474 struct spoolss_Notify,
3476 if (info->notifies == NULL) {
3477 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3481 current_data=&(info->notifies[info->count]);
3483 construct_info_data(current_data, type, field, id);
3484 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3485 queue, pinfo2, mem_ctx);
3493 * JFM: The enumeration is not that simple, it's even non obvious.
3495 * let's take an example: I want to monitor the PRINTER SERVER for
3496 * the printer's name and the number of jobs currently queued.
3497 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3498 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3500 * I have 3 printers on the back of my server.
3502 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3505 * 1 printer 1 name 1
3506 * 2 printer 1 cjob 1
3507 * 3 printer 2 name 2
3508 * 4 printer 2 cjob 2
3509 * 5 printer 3 name 3
3510 * 6 printer 3 name 3
3512 * that's the print server case, the printer case is even worse.
3515 /*******************************************************************
3517 * enumerate all printers on the printserver
3518 * fill a notify_info struct with info asked
3520 ********************************************************************/
3522 static WERROR printserver_notify_info(struct pipes_struct *p,
3523 struct policy_handle *hnd,
3524 struct spoolss_NotifyInfo *info,
3525 TALLOC_CTX *mem_ctx)
3528 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3529 int n_services=lp_numservices();
3531 struct spoolss_NotifyOption *option;
3532 struct spoolss_NotifyOptionType option_type;
3533 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3536 DEBUG(4,("printserver_notify_info\n"));
3541 option = Printer->notify.option;
3544 info->notifies = NULL;
3547 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3548 sending a ffpcn() request first */
3553 for (i=0; i<option->count; i++) {
3554 option_type = option->types[i];
3556 if (option_type.type != PRINTER_NOTIFY_TYPE)
3559 for (snum = 0; snum < n_services; snum++) {
3560 if (!lp_browseable(snum) ||
3561 !lp_snum_ok(snum) ||
3562 !lp_print_ok(snum)) {
3563 continue; /* skip */
3566 /* Maybe we should use the SYSTEM session_info here... */
3567 result = winreg_get_printer_internal(mem_ctx,
3568 get_session_info_system(),
3570 lp_servicename(snum),
3572 if (!W_ERROR_IS_OK(result)) {
3573 DEBUG(4, ("printserver_notify_info: "
3574 "Failed to get printer [%s]\n",
3575 lp_servicename(snum)));
3580 construct_notify_printer_info(p->msg_ctx,
3586 TALLOC_FREE(pinfo2);
3592 * Debugging information, don't delete.
3595 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3596 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3597 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3599 for (i=0; i<info->count; i++) {
3600 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3601 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3602 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3609 /*******************************************************************
3611 * fill a notify_info struct with info asked
3613 ********************************************************************/
3615 static WERROR printer_notify_info(struct pipes_struct *p,
3616 struct policy_handle *hnd,
3617 struct spoolss_NotifyInfo *info,
3618 TALLOC_CTX *mem_ctx)
3621 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3624 struct spoolss_NotifyOption *option;
3625 struct spoolss_NotifyOptionType option_type;
3627 print_queue_struct *queue=NULL;
3628 print_status_struct status;
3629 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3632 DEBUG(4,("printer_notify_info\n"));
3637 option = Printer->notify.option;
3641 info->notifies = NULL;
3644 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3645 sending a ffpcn() request first */
3650 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3654 /* Maybe we should use the SYSTEM session_info here... */
3655 result = winreg_get_printer_internal(mem_ctx,
3656 get_session_info_system(),
3658 lp_servicename(snum), &pinfo2);
3659 if (!W_ERROR_IS_OK(result)) {
3664 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3665 * correct servername.
3667 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3668 if (pinfo2->servername == NULL) {
3672 for (i=0; i<option->count; i++) {
3673 option_type = option->types[i];
3675 switch (option_type.type) {
3676 case PRINTER_NOTIFY_TYPE:
3677 if (construct_notify_printer_info(p->msg_ctx,
3686 case JOB_NOTIFY_TYPE:
3688 count = print_queue_status(p->msg_ctx, snum, &queue,
3691 for (j=0; j<count; j++) {
3692 construct_notify_jobs_info(p->msg_ctx,
3706 * Debugging information, don't delete.
3709 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3710 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3711 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3713 for (i=0; i<info->count; i++) {
3714 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3715 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3716 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3720 talloc_free(pinfo2);
3724 /****************************************************************
3725 _spoolss_RouterRefreshPrinterChangeNotify
3726 ****************************************************************/
3728 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3729 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3731 struct spoolss_NotifyInfo *info;
3733 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3734 WERROR result = WERR_BADFID;
3736 /* we always have a spoolss_NotifyInfo struct */
3737 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3739 result = WERR_NOMEM;
3743 *r->out.info = info;
3746 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3747 "Invalid handle (%s:%u:%u).\n",
3748 OUR_HANDLE(r->in.handle)));
3752 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3755 * We are now using the change value, and
3756 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3757 * I don't have a global notification system, I'm sending back all the
3758 * information even when _NOTHING_ has changed.
3761 /* We need to keep track of the change value to send back in
3762 RRPCN replies otherwise our updates are ignored. */
3764 Printer->notify.fnpcn = true;
3766 if (Printer->notify.cli_chan != NULL &&
3767 Printer->notify.cli_chan->active_connections > 0) {
3768 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3769 "Saving change value in request [%x]\n",
3771 Printer->notify.change = r->in.change_low;
3774 /* just ignore the spoolss_NotifyOption */
3776 switch (Printer->printer_type) {
3778 result = printserver_notify_info(p, r->in.handle,
3782 case SPLHND_PRINTER:
3783 result = printer_notify_info(p, r->in.handle,
3788 Printer->notify.fnpcn = false;
3794 /********************************************************************
3795 ********************************************************************/
3797 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3798 const char *servername,
3799 const char *printername,
3800 const char **printername_p)
3802 /* FIXME: add lp_force_printername() */
3804 if (servername == NULL) {
3805 *printername_p = talloc_strdup(mem_ctx, printername);
3806 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3810 if (servername[0] == '\\' && servername[1] == '\\') {
3814 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3815 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3820 /********************************************************************
3821 ********************************************************************/
3823 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3824 const char *printername)
3830 dm->devicename = talloc_strndup(dm, printername,
3831 MIN(strlen(printername), 31));
3834 /********************************************************************
3835 * construct_printer_info_0
3836 * fill a printer_info_0 struct
3837 ********************************************************************/
3839 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3840 const struct auth_session_info *session_info,
3841 struct messaging_context *msg_ctx,
3842 struct spoolss_PrinterInfo2 *info2,
3843 const char *servername,
3844 struct spoolss_PrinterInfo0 *r,
3848 struct printer_session_counter *session_counter;
3849 struct timeval setuptime;
3850 print_status_struct status;
3853 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3854 if (!W_ERROR_IS_OK(result)) {
3859 r->servername = talloc_strdup(mem_ctx, servername);
3860 W_ERROR_HAVE_NO_MEMORY(r->servername);
3862 r->servername = NULL;
3865 count = print_queue_length(msg_ctx, snum, &status);
3867 /* check if we already have a counter for this printer */
3868 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3869 if (session_counter->snum == snum)
3873 /* it's the first time, add it to the list */
3874 if (session_counter == NULL) {
3875 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3876 W_ERROR_HAVE_NO_MEMORY(session_counter);
3877 session_counter->snum = snum;
3878 session_counter->counter = 0;
3879 DLIST_ADD(counter_list, session_counter);
3883 session_counter->counter++;
3889 get_startup_time(&setuptime);
3890 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3893 * the global_counter should be stored in a TDB as it's common to all the clients
3894 * and should be zeroed on samba startup
3896 r->global_counter = session_counter->counter;
3898 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3899 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3900 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3901 r->free_build = SPOOLSS_RELEASE_BUILD;
3903 r->max_spooling = 0;
3904 r->session_counter = session_counter->counter;
3905 r->num_error_out_of_paper = 0x0;
3906 r->num_error_not_ready = 0x0; /* number of print failure */
3908 r->number_of_processors = 0x1;
3909 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3910 r->high_part_total_bytes = 0x0;
3912 /* ChangeID in milliseconds*/
3913 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3914 info2->sharename, &r->change_id);
3916 r->last_error = WERR_OK;
3917 r->status = nt_printq_status(status.status);
3918 r->enumerate_network_printers = 0x0;
3919 r->c_setprinter = 0x0;
3920 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3921 r->processor_level = 0x6; /* 6 ???*/
3930 /********************************************************************
3931 * construct_printer_info1
3932 * fill a spoolss_PrinterInfo1 struct
3933 ********************************************************************/
3935 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3936 const struct spoolss_PrinterInfo2 *info2,
3938 const char *servername,
3939 struct spoolss_PrinterInfo1 *r,
3946 if (info2->comment == NULL || info2->comment[0] == '\0') {
3947 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3949 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3951 W_ERROR_HAVE_NO_MEMORY(r->comment);
3953 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3954 if (!W_ERROR_IS_OK(result)) {
3958 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3962 W_ERROR_HAVE_NO_MEMORY(r->description);
3967 /********************************************************************
3968 * construct_printer_info2
3969 * fill a spoolss_PrinterInfo2 struct
3970 ********************************************************************/
3972 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3973 struct messaging_context *msg_ctx,
3974 const struct spoolss_PrinterInfo2 *info2,
3975 const char *servername,
3976 struct spoolss_PrinterInfo2 *r,
3980 print_status_struct status;
3983 count = print_queue_length(msg_ctx, snum, &status);
3986 r->servername = talloc_strdup(mem_ctx, servername);
3987 W_ERROR_HAVE_NO_MEMORY(r->servername);
3989 r->servername = NULL;
3992 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3993 if (!W_ERROR_IS_OK(result)) {
3997 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3998 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3999 r->portname = talloc_strdup(mem_ctx, info2->portname);
4000 W_ERROR_HAVE_NO_MEMORY(r->portname);
4001 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4002 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4004 if (info2->comment[0] == '\0') {
4005 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4007 r->comment = talloc_strdup(mem_ctx, info2->comment);
4009 W_ERROR_HAVE_NO_MEMORY(r->comment);
4011 r->location = talloc_strdup(mem_ctx, info2->location);
4012 if (info2->location[0] == '\0') {
4013 const char *loc = NULL;
4016 nt_status = printer_list_get_printer(mem_ctx,
4021 if (NT_STATUS_IS_OK(nt_status)) {
4023 r->location = talloc_strdup(mem_ctx, loc);
4027 W_ERROR_HAVE_NO_MEMORY(r->location);
4029 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4030 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4031 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4032 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4033 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4034 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4035 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4036 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4038 r->attributes = info2->attributes;
4040 r->priority = info2->priority;
4041 r->defaultpriority = info2->defaultpriority;
4042 r->starttime = info2->starttime;
4043 r->untiltime = info2->untiltime;
4044 r->status = nt_printq_status(status.status);
4046 r->averageppm = info2->averageppm;
4048 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4050 DEBUG(8,("Returning NULL Devicemode!\n"));
4053 compose_devicemode_devicename(r->devmode, r->printername);
4057 if (info2->secdesc != NULL) {
4058 /* don't use talloc_steal() here unless you do a deep steal of all
4059 the SEC_DESC members */
4061 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4067 /********************************************************************
4068 * construct_printer_info3
4069 * fill a spoolss_PrinterInfo3 struct
4070 ********************************************************************/
4072 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4073 const struct spoolss_PrinterInfo2 *info2,
4074 const char *servername,
4075 struct spoolss_PrinterInfo3 *r,
4078 /* These are the components of the SD we are returning. */
4080 if (info2->secdesc != NULL) {
4081 /* don't use talloc_steal() here unless you do a deep steal of all
4082 the SEC_DESC members */
4084 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4085 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4091 /********************************************************************
4092 * construct_printer_info4
4093 * fill a spoolss_PrinterInfo4 struct
4094 ********************************************************************/
4096 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4097 const struct spoolss_PrinterInfo2 *info2,
4098 const char *servername,
4099 struct spoolss_PrinterInfo4 *r,
4104 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4105 if (!W_ERROR_IS_OK(result)) {
4110 r->servername = talloc_strdup(mem_ctx, servername);
4111 W_ERROR_HAVE_NO_MEMORY(r->servername);
4113 r->servername = NULL;
4116 r->attributes = info2->attributes;
4121 /********************************************************************
4122 * construct_printer_info5
4123 * fill a spoolss_PrinterInfo5 struct
4124 ********************************************************************/
4126 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4127 const struct spoolss_PrinterInfo2 *info2,
4128 const char *servername,
4129 struct spoolss_PrinterInfo5 *r,
4134 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4135 if (!W_ERROR_IS_OK(result)) {
4139 r->portname = talloc_strdup(mem_ctx, info2->portname);
4140 W_ERROR_HAVE_NO_MEMORY(r->portname);
4142 r->attributes = info2->attributes;
4144 /* these two are not used by NT+ according to MSDN */
4145 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4146 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4151 /********************************************************************
4152 * construct_printer_info_6
4153 * fill a spoolss_PrinterInfo6 struct
4154 ********************************************************************/
4156 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4157 struct messaging_context *msg_ctx,
4158 const struct spoolss_PrinterInfo2 *info2,
4159 const char *servername,
4160 struct spoolss_PrinterInfo6 *r,
4163 print_status_struct status;
4165 print_queue_length(msg_ctx, snum, &status);
4167 r->status = nt_printq_status(status.status);
4172 /********************************************************************
4173 * construct_printer_info7
4174 * fill a spoolss_PrinterInfo7 struct
4175 ********************************************************************/
4177 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4178 struct messaging_context *msg_ctx,
4179 const char *servername,
4180 struct spoolss_PrinterInfo7 *r,
4183 const struct auth_session_info *session_info = get_session_info_system();
4186 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4188 lp_servicename(snum), &guid, NULL)) {
4189 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4190 r->action = DSPRINT_PUBLISH;
4192 r->guid = talloc_strdup(mem_ctx, "");
4193 r->action = DSPRINT_UNPUBLISH;
4195 W_ERROR_HAVE_NO_MEMORY(r->guid);
4200 /********************************************************************
4201 * construct_printer_info8
4202 * fill a spoolss_PrinterInfo8 struct
4203 ********************************************************************/
4205 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4206 const struct spoolss_PrinterInfo2 *info2,
4207 const char *servername,
4208 struct spoolss_DeviceModeInfo *r,
4212 const char *printername;
4214 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4215 if (!W_ERROR_IS_OK(result)) {
4219 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4221 DEBUG(8,("Returning NULL Devicemode!\n"));
4224 compose_devicemode_devicename(r->devmode, printername);
4230 /********************************************************************
4231 ********************************************************************/
4233 static bool snum_is_shared_printer(int snum)
4235 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4238 /********************************************************************
4239 Spoolss_enumprinters.
4240 ********************************************************************/
4242 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4243 const struct auth_session_info *session_info,
4244 struct messaging_context *msg_ctx,
4245 const char *servername,
4248 union spoolss_PrinterInfo **info_p,
4252 int n_services = lp_numservices();
4253 union spoolss_PrinterInfo *info = NULL;
4255 WERROR result = WERR_OK;
4256 struct dcerpc_binding_handle *b = NULL;
4257 TALLOC_CTX *tmp_ctx = NULL;
4259 tmp_ctx = talloc_new(mem_ctx);
4267 for (snum = 0; snum < n_services; snum++) {
4269 const char *printer;
4270 struct spoolss_PrinterInfo2 *info2;
4272 if (!snum_is_shared_printer(snum)) {
4276 printer = lp_const_servicename(snum);
4278 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4282 result = winreg_printer_binding_handle(tmp_ctx,
4286 if (!W_ERROR_IS_OK(result)) {
4291 result = winreg_create_printer(tmp_ctx, b,
4293 if (!W_ERROR_IS_OK(result)) {
4297 info = talloc_realloc(tmp_ctx, info,
4298 union spoolss_PrinterInfo,
4301 result = WERR_NOMEM;
4305 result = winreg_get_printer(tmp_ctx, b,
4307 if (!W_ERROR_IS_OK(result)) {
4313 result = construct_printer_info0(info, session_info,
4316 &info[count].info0, snum);
4319 result = construct_printer_info1(info, info2, flags,
4321 &info[count].info1, snum);
4324 result = construct_printer_info2(info, msg_ctx, info2,
4326 &info[count].info2, snum);
4329 result = construct_printer_info4(info, info2,
4331 &info[count].info4, snum);
4334 result = construct_printer_info5(info, info2,
4336 &info[count].info5, snum);
4340 result = WERR_UNKNOWN_LEVEL;
4344 if (!W_ERROR_IS_OK(result)) {
4352 if (W_ERROR_IS_OK(result)) {
4353 *info_p = talloc_move(mem_ctx, &info);
4357 talloc_free(tmp_ctx);
4362 /********************************************************************
4363 * handle enumeration of printers at level 0
4364 ********************************************************************/
4366 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4367 const struct auth_session_info *session_info,
4368 struct messaging_context *msg_ctx,
4370 const char *servername,
4371 union spoolss_PrinterInfo **info,
4374 DEBUG(4,("enum_all_printers_info_0\n"));
4376 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4377 servername, 0, flags, info, count);
4381 /********************************************************************
4382 ********************************************************************/
4384 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4385 const struct auth_session_info *session_info,
4386 struct messaging_context *msg_ctx,
4387 const char *servername,
4389 union spoolss_PrinterInfo **info,
4392 DEBUG(4,("enum_all_printers_info_1\n"));
4394 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4395 servername, 1, flags, info, count);
4398 /********************************************************************
4399 enum_all_printers_info_1_local.
4400 *********************************************************************/
4402 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4403 const struct auth_session_info *session_info,
4404 struct messaging_context *msg_ctx,
4405 const char *servername,
4406 union spoolss_PrinterInfo **info,
4409 DEBUG(4,("enum_all_printers_info_1_local\n"));
4411 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4412 servername, PRINTER_ENUM_ICON8, info, count);
4415 /********************************************************************
4416 enum_all_printers_info_1_name.
4417 *********************************************************************/
4419 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4420 const struct auth_session_info *session_info,
4421 struct messaging_context *msg_ctx,
4422 const char *servername,
4423 union spoolss_PrinterInfo **info,
4426 const char *s = servername;
4428 DEBUG(4,("enum_all_printers_info_1_name\n"));
4430 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4434 if (!is_myname_or_ipaddr(s)) {
4435 return WERR_INVALID_NAME;
4438 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4439 servername, PRINTER_ENUM_ICON8, info, count);
4442 /********************************************************************
4443 enum_all_printers_info_1_network.
4444 *********************************************************************/
4446 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4447 const struct auth_session_info *session_info,
4448 struct messaging_context *msg_ctx,
4449 const char *servername,
4450 union spoolss_PrinterInfo **info,
4453 const char *s = servername;
4455 DEBUG(4,("enum_all_printers_info_1_network\n"));
4457 /* If we respond to a enum_printers level 1 on our name with flags
4458 set to PRINTER_ENUM_REMOTE with a list of printers then these
4459 printers incorrectly appear in the APW browse list.
4460 Specifically the printers for the server appear at the workgroup
4461 level where all the other servers in the domain are
4462 listed. Windows responds to this call with a
4463 WERR_CAN_NOT_COMPLETE so we should do the same. */
4465 if (servername[0] == '\\' && servername[1] == '\\') {
4469 if (is_myname_or_ipaddr(s)) {
4470 return WERR_CAN_NOT_COMPLETE;
4473 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4474 servername, PRINTER_ENUM_NAME, info, count);
4477 /********************************************************************
4478 * api_spoolss_enumprinters
4480 * called from api_spoolss_enumprinters (see this to understand)
4481 ********************************************************************/
4483 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4484 const struct auth_session_info *session_info,
4485 struct messaging_context *msg_ctx,
4486 const char *servername,
4487 union spoolss_PrinterInfo **info,
4490 DEBUG(4,("enum_all_printers_info_2\n"));
4492 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4493 servername, 2, 0, info, count);
4496 /********************************************************************
4497 * handle enumeration of printers at level 1
4498 ********************************************************************/
4500 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4501 const struct auth_session_info *session_info,
4502 struct messaging_context *msg_ctx,
4504 const char *servername,
4505 union spoolss_PrinterInfo **info,
4508 /* Not all the flags are equals */
4510 if (flags & PRINTER_ENUM_LOCAL) {
4511 return enum_all_printers_info_1_local(mem_ctx, session_info,
4512 msg_ctx, servername, info, count);
4515 if (flags & PRINTER_ENUM_NAME) {
4516 return enum_all_printers_info_1_name(mem_ctx, session_info,
4517 msg_ctx, servername, info,
4521 if (flags & PRINTER_ENUM_NETWORK) {
4522 return enum_all_printers_info_1_network(mem_ctx, session_info,
4523 msg_ctx, servername, info,
4527 return WERR_OK; /* NT4sp5 does that */
4530 /********************************************************************
4531 * handle enumeration of printers at level 2
4532 ********************************************************************/
4534 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4535 const struct auth_session_info *session_info,
4536 struct messaging_context *msg_ctx,
4538 const char *servername,
4539 union spoolss_PrinterInfo **info,
4542 if (flags & PRINTER_ENUM_LOCAL) {
4544 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4549 if (flags & PRINTER_ENUM_NAME) {
4550 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4551 return WERR_INVALID_NAME;
4554 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4559 if (flags & PRINTER_ENUM_REMOTE) {
4560 return WERR_UNKNOWN_LEVEL;
4566 /********************************************************************
4567 * handle enumeration of printers at level 4
4568 ********************************************************************/
4570 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4571 const struct auth_session_info *session_info,
4572 struct messaging_context *msg_ctx,
4574 const char *servername,
4575 union spoolss_PrinterInfo **info,
4578 DEBUG(4,("enum_all_printers_info_4\n"));
4580 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4581 servername, 4, flags, info, count);
4585 /********************************************************************
4586 * handle enumeration of printers at level 5
4587 ********************************************************************/
4589 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4590 const struct auth_session_info *session_info,
4591 struct messaging_context *msg_ctx,
4593 const char *servername,
4594 union spoolss_PrinterInfo **info,
4597 DEBUG(4,("enum_all_printers_info_5\n"));
4599 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4600 servername, 5, flags, info, count);
4603 /****************************************************************
4604 _spoolss_EnumPrinters
4605 ****************************************************************/
4607 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4608 struct spoolss_EnumPrinters *r)
4610 const struct auth_session_info *session_info = get_session_info_system();
4613 /* that's an [in out] buffer */
4615 if (!r->in.buffer && (r->in.offered != 0)) {
4616 return WERR_INVALID_PARAM;
4619 DEBUG(4,("_spoolss_EnumPrinters\n"));
4623 *r->out.info = NULL;
4627 * flags==PRINTER_ENUM_NAME
4628 * if name=="" then enumerates all printers
4629 * if name!="" then enumerate the printer
4630 * flags==PRINTER_ENUM_REMOTE
4631 * name is NULL, enumerate printers
4632 * Level 2: name!="" enumerates printers, name can't be NULL
4633 * Level 3: doesn't exist
4634 * Level 4: does a local registry lookup
4635 * Level 5: same as Level 2
4638 if (r->in.server && r->in.server[0] == '\0') {
4639 r->in.server = NULL;
4642 switch (r->in.level) {
4644 result = enumprinters_level0(p->mem_ctx, session_info,
4645 p->msg_ctx, r->in.flags,
4647 r->out.info, r->out.count);
4650 result = enumprinters_level1(p->mem_ctx, session_info,
4651 p->msg_ctx, r->in.flags,
4653 r->out.info, r->out.count);
4656 result = enumprinters_level2(p->mem_ctx, session_info,
4657 p->msg_ctx, r->in.flags,
4659 r->out.info, r->out.count);
4662 result = enumprinters_level4(p->mem_ctx, session_info,
4663 p->msg_ctx, r->in.flags,
4665 r->out.info, r->out.count);
4668 result = enumprinters_level5(p->mem_ctx, session_info,
4669 p->msg_ctx, r->in.flags,
4671 r->out.info, r->out.count);
4674 return WERR_UNKNOWN_LEVEL;
4677 if (!W_ERROR_IS_OK(result)) {
4681 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4682 spoolss_EnumPrinters,
4683 *r->out.info, r->in.level,
4685 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4686 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4688 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4691 /****************************************************************
4693 ****************************************************************/
4695 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4696 struct spoolss_GetPrinter *r)
4698 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4699 struct spoolss_PrinterInfo2 *info2 = NULL;
4700 WERROR result = WERR_OK;
4703 /* that's an [in out] buffer */
4705 if (!r->in.buffer && (r->in.offered != 0)) {
4706 return WERR_INVALID_PARAM;
4711 if (Printer == NULL) {
4715 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4719 result = winreg_get_printer_internal(p->mem_ctx,
4720 get_session_info_system(),
4722 lp_const_servicename(snum),
4724 if (!W_ERROR_IS_OK(result)) {
4728 switch (r->in.level) {
4730 result = construct_printer_info0(p->mem_ctx,
4731 get_session_info_system(),
4734 Printer->servername,
4735 &r->out.info->info0,
4739 result = construct_printer_info1(p->mem_ctx, info2,
4741 Printer->servername,
4742 &r->out.info->info1, snum);
4745 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4746 Printer->servername,
4747 &r->out.info->info2, snum);
4750 result = construct_printer_info3(p->mem_ctx, info2,
4751 Printer->servername,
4752 &r->out.info->info3, snum);
4755 result = construct_printer_info4(p->mem_ctx, info2,
4756 Printer->servername,
4757 &r->out.info->info4, snum);
4760 result = construct_printer_info5(p->mem_ctx, info2,
4761 Printer->servername,
4762 &r->out.info->info5, snum);
4765 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4766 Printer->servername,
4767 &r->out.info->info6, snum);
4770 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4771 Printer->servername,
4772 &r->out.info->info7, snum);
4775 result = construct_printer_info8(p->mem_ctx, info2,
4776 Printer->servername,
4777 &r->out.info->info8, snum);
4780 result = WERR_UNKNOWN_LEVEL;
4786 if (!W_ERROR_IS_OK(result)) {
4787 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4788 r->in.level, win_errstr(result)));
4789 TALLOC_FREE(r->out.info);
4793 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4794 r->out.info, r->in.level);
4795 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4797 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4800 /********************************************************************
4801 ********************************************************************/
4803 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4805 if (in && strlen(in)) { \
4806 out = talloc_strdup(mem_ctx, in); \
4808 out = talloc_strdup(mem_ctx, ""); \
4810 W_ERROR_HAVE_NO_MEMORY(out); \
4813 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4815 if (in && strlen(in)) { \
4816 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4818 out = talloc_strdup(mem_ctx, ""); \
4820 W_ERROR_HAVE_NO_MEMORY(out); \
4823 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4824 const char **string_array,
4825 const char ***presult,
4826 const char *cservername,
4830 int i, num_strings = 0;
4831 const char **array = NULL;
4833 if (string_array == NULL) {
4834 return WERR_INVALID_PARAMETER;
4837 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4838 const char *str = NULL;
4840 if (cservername == NULL || arch == NULL) {
4841 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4843 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4846 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4853 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4854 &array, &num_strings);
4864 /********************************************************************
4865 * fill a spoolss_DriverInfo1 struct
4866 ********************************************************************/
4868 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4869 struct spoolss_DriverInfo1 *r,
4870 const struct spoolss_DriverInfo8 *driver,
4871 const char *servername)
4873 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4874 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4879 /********************************************************************
4880 * fill a spoolss_DriverInfo2 struct
4881 ********************************************************************/
4883 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4884 struct spoolss_DriverInfo2 *r,
4885 const struct spoolss_DriverInfo8 *driver,
4886 const char *servername)
4889 const char *cservername = canon_servername(servername);
4891 r->version = driver->version;
4893 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4894 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4895 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4896 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4898 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4899 driver->architecture,
4901 driver->driver_path,
4904 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4905 driver->architecture,
4910 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4911 driver->architecture,
4913 driver->config_file,
4919 /********************************************************************
4920 * fill a spoolss_DriverInfo3 struct
4921 ********************************************************************/
4923 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4924 struct spoolss_DriverInfo3 *r,
4925 const struct spoolss_DriverInfo8 *driver,
4926 const char *servername)
4928 const char *cservername = canon_servername(servername);
4930 r->version = driver->version;
4932 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4933 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4934 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4935 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4937 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4938 driver->architecture,
4940 driver->driver_path,
4943 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4944 driver->architecture,
4949 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4950 driver->architecture,
4952 driver->config_file,
4955 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4956 driver->architecture,
4961 FILL_DRIVER_STRING(mem_ctx,
4962 driver->monitor_name,
4965 FILL_DRIVER_STRING(mem_ctx,
4966 driver->default_datatype,
4967 r->default_datatype);
4969 return string_array_from_driver_info(mem_ctx,
4970 driver->dependent_files,
4971 &r->dependent_files,
4973 driver->architecture,
4977 /********************************************************************
4978 * fill a spoolss_DriverInfo4 struct
4979 ********************************************************************/
4981 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4982 struct spoolss_DriverInfo4 *r,
4983 const struct spoolss_DriverInfo8 *driver,
4984 const char *servername)
4986 const char *cservername = canon_servername(servername);
4989 r->version = driver->version;
4991 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4992 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4993 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4994 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4996 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4997 driver->architecture,
4999 driver->driver_path,
5002 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5003 driver->architecture,
5008 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5009 driver->architecture,
5011 driver->config_file,
5014 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5015 driver->architecture,
5020 result = string_array_from_driver_info(mem_ctx,
5021 driver->dependent_files,
5022 &r->dependent_files,
5024 driver->architecture,
5026 if (!W_ERROR_IS_OK(result)) {
5030 FILL_DRIVER_STRING(mem_ctx,
5031 driver->monitor_name,
5034 FILL_DRIVER_STRING(mem_ctx,
5035 driver->default_datatype,
5036 r->default_datatype);
5039 result = string_array_from_driver_info(mem_ctx,
5040 driver->previous_names,
5047 /********************************************************************
5048 * fill a spoolss_DriverInfo5 struct
5049 ********************************************************************/
5051 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5052 struct spoolss_DriverInfo5 *r,
5053 const struct spoolss_DriverInfo8 *driver,
5054 const char *servername)
5056 const char *cservername = canon_servername(servername);
5058 r->version = driver->version;
5060 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5061 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5062 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5063 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5065 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5066 driver->architecture,
5068 driver->driver_path,
5071 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5072 driver->architecture,
5077 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5078 driver->architecture,
5080 driver->config_file,
5083 r->driver_attributes = 0;
5084 r->config_version = 0;
5085 r->driver_version = 0;
5089 /********************************************************************
5090 * fill a spoolss_DriverInfo6 struct
5091 ********************************************************************/
5093 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5094 struct spoolss_DriverInfo6 *r,
5095 const struct spoolss_DriverInfo8 *driver,
5096 const char *servername)
5098 const char *cservername = canon_servername(servername);
5101 r->version = driver->version;
5103 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5104 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5105 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5106 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5108 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5109 driver->architecture,
5111 driver->driver_path,
5114 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5115 driver->architecture,
5120 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5121 driver->architecture,
5123 driver->config_file,
5126 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5127 driver->architecture,
5132 FILL_DRIVER_STRING(mem_ctx,
5133 driver->monitor_name,
5136 FILL_DRIVER_STRING(mem_ctx,
5137 driver->default_datatype,
5138 r->default_datatype);
5140 result = string_array_from_driver_info(mem_ctx,
5141 driver->dependent_files,
5142 &r->dependent_files,
5144 driver->architecture,
5146 if (!W_ERROR_IS_OK(result)) {
5150 result = string_array_from_driver_info(mem_ctx,
5151 driver->previous_names,
5154 if (!W_ERROR_IS_OK(result)) {
5158 r->driver_date = driver->driver_date;
5159 r->driver_version = driver->driver_version;
5161 FILL_DRIVER_STRING(mem_ctx,
5162 driver->manufacturer_name,
5163 r->manufacturer_name);
5164 FILL_DRIVER_STRING(mem_ctx,
5165 driver->manufacturer_url,
5166 r->manufacturer_url);
5167 FILL_DRIVER_STRING(mem_ctx,
5168 driver->hardware_id,
5170 FILL_DRIVER_STRING(mem_ctx,
5177 /********************************************************************
5178 * fill a spoolss_DriverInfo8 struct
5179 ********************************************************************/
5181 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5182 struct spoolss_DriverInfo8 *r,
5183 const struct spoolss_DriverInfo8 *driver,
5184 const char *servername)
5186 const char *cservername = canon_servername(servername);
5189 r->version = driver->version;
5191 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5192 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5193 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5194 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5196 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5197 driver->architecture,
5199 driver->driver_path,
5202 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5203 driver->architecture,
5208 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5209 driver->architecture,
5211 driver->config_file,
5214 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5215 driver->architecture,
5220 FILL_DRIVER_STRING(mem_ctx,
5221 driver->monitor_name,
5224 FILL_DRIVER_STRING(mem_ctx,
5225 driver->default_datatype,
5226 r->default_datatype);
5228 result = string_array_from_driver_info(mem_ctx,
5229 driver->dependent_files,
5230 &r->dependent_files,
5232 driver->architecture,
5234 if (!W_ERROR_IS_OK(result)) {
5238 result = string_array_from_driver_info(mem_ctx,
5239 driver->previous_names,
5242 if (!W_ERROR_IS_OK(result)) {
5246 r->driver_date = driver->driver_date;
5247 r->driver_version = driver->driver_version;
5249 FILL_DRIVER_STRING(mem_ctx,
5250 driver->manufacturer_name,
5251 r->manufacturer_name);
5252 FILL_DRIVER_STRING(mem_ctx,
5253 driver->manufacturer_url,
5254 r->manufacturer_url);
5255 FILL_DRIVER_STRING(mem_ctx,
5256 driver->hardware_id,
5258 FILL_DRIVER_STRING(mem_ctx,
5262 FILL_DRIVER_STRING(mem_ctx,
5263 driver->print_processor,
5264 r->print_processor);
5265 FILL_DRIVER_STRING(mem_ctx,
5266 driver->vendor_setup,
5269 result = string_array_from_driver_info(mem_ctx,
5270 driver->color_profiles,
5273 if (!W_ERROR_IS_OK(result)) {
5277 FILL_DRIVER_STRING(mem_ctx,
5281 r->printer_driver_attributes = driver->printer_driver_attributes;
5283 result = string_array_from_driver_info(mem_ctx,
5284 driver->core_driver_dependencies,
5285 &r->core_driver_dependencies,
5287 if (!W_ERROR_IS_OK(result)) {
5291 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5292 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5297 #if 0 /* disabled until marshalling issues are resolved - gd */
5298 /********************************************************************
5299 ********************************************************************/
5301 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5302 struct spoolss_DriverFileInfo *r,
5303 const char *cservername,
5304 const char *file_name,
5305 enum spoolss_DriverFileType file_type,
5306 uint32_t file_version)
5308 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5309 cservername, file_name);
5310 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5311 r->file_type = file_type;
5312 r->file_version = file_version;
5317 /********************************************************************
5318 ********************************************************************/
5320 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5321 const struct spoolss_DriverInfo8 *driver,
5322 const char *cservername,
5323 struct spoolss_DriverFileInfo **info_p,
5326 struct spoolss_DriverFileInfo *info = NULL;
5334 if (strlen(driver->driver_path)) {
5335 info = talloc_realloc(mem_ctx, info,
5336 struct spoolss_DriverFileInfo,
5338 W_ERROR_HAVE_NO_MEMORY(info);
5339 result = fill_spoolss_DriverFileInfo(info,
5342 driver->driver_path,
5343 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5345 W_ERROR_NOT_OK_RETURN(result);
5349 if (strlen(driver->config_file)) {
5350 info = talloc_realloc(mem_ctx, info,
5351 struct spoolss_DriverFileInfo,
5353 W_ERROR_HAVE_NO_MEMORY(info);
5354 result = fill_spoolss_DriverFileInfo(info,
5357 driver->config_file,
5358 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5360 W_ERROR_NOT_OK_RETURN(result);
5364 if (strlen(driver->data_file)) {
5365 info = talloc_realloc(mem_ctx, info,
5366 struct spoolss_DriverFileInfo,
5368 W_ERROR_HAVE_NO_MEMORY(info);
5369 result = fill_spoolss_DriverFileInfo(info,
5373 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5375 W_ERROR_NOT_OK_RETURN(result);
5379 if (strlen(driver->help_file)) {
5380 info = talloc_realloc(mem_ctx, info,
5381 struct spoolss_DriverFileInfo,
5383 W_ERROR_HAVE_NO_MEMORY(info);
5384 result = fill_spoolss_DriverFileInfo(info,
5388 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5390 W_ERROR_NOT_OK_RETURN(result);
5394 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5395 info = talloc_realloc(mem_ctx, info,
5396 struct spoolss_DriverFileInfo,
5398 W_ERROR_HAVE_NO_MEMORY(info);
5399 result = fill_spoolss_DriverFileInfo(info,
5402 driver->dependent_files[i],
5403 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5405 W_ERROR_NOT_OK_RETURN(result);
5415 /********************************************************************
5416 * fill a spoolss_DriverInfo101 struct
5417 ********************************************************************/
5419 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5420 struct spoolss_DriverInfo101 *r,
5421 const struct spoolss_DriverInfo8 *driver,
5422 const char *servername)
5424 const char *cservername = canon_servername(servername);
5427 r->version = driver->version;
5429 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5430 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5431 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5432 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5434 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5438 if (!W_ERROR_IS_OK(result)) {
5442 FILL_DRIVER_STRING(mem_ctx,
5443 driver->monitor_name,
5446 FILL_DRIVER_STRING(mem_ctx,
5447 driver->default_datatype,
5448 r->default_datatype);
5450 result = string_array_from_driver_info(mem_ctx,
5451 driver->previous_names,
5454 if (!W_ERROR_IS_OK(result)) {
5458 r->driver_date = driver->driver_date;
5459 r->driver_version = driver->driver_version;
5461 FILL_DRIVER_STRING(mem_ctx,
5462 driver->manufacturer_name,
5463 r->manufacturer_name);
5464 FILL_DRIVER_STRING(mem_ctx,
5465 driver->manufacturer_url,
5466 r->manufacturer_url);
5467 FILL_DRIVER_STRING(mem_ctx,
5468 driver->hardware_id,
5470 FILL_DRIVER_STRING(mem_ctx,
5477 /********************************************************************
5478 ********************************************************************/
5480 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5481 const struct auth_session_info *session_info,
5482 struct messaging_context *msg_ctx,
5484 union spoolss_DriverInfo *r,
5486 const char *servername,
5487 const char *architecture,
5490 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5491 struct spoolss_DriverInfo8 *driver;
5493 struct dcerpc_binding_handle *b;
5494 TALLOC_CTX *tmp_ctx = NULL;
5497 return WERR_UNKNOWN_LEVEL;
5500 tmp_ctx = talloc_new(mem_ctx);
5505 result = winreg_printer_binding_handle(tmp_ctx,
5509 if (!W_ERROR_IS_OK(result)) {
5513 result = winreg_get_printer(tmp_ctx, b,
5514 lp_const_servicename(snum),
5517 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5518 win_errstr(result)));
5520 if (!W_ERROR_IS_OK(result)) {
5521 result = WERR_INVALID_PRINTER_NAME;
5525 result = winreg_get_driver(tmp_ctx, b,
5527 pinfo2->drivername, version, &driver);
5529 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5530 win_errstr(result)));
5532 if (!W_ERROR_IS_OK(result)) {
5534 * Is this a W2k client ?
5538 result = WERR_UNKNOWN_PRINTER_DRIVER;
5542 /* Yes - try again with a WinNT driver. */
5544 result = winreg_get_driver(tmp_ctx, b,
5548 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5549 win_errstr(result)));
5550 if (!W_ERROR_IS_OK(result)) {
5551 result = WERR_UNKNOWN_PRINTER_DRIVER;
5556 /* these are allocated on mem_ctx and not tmp_ctx because they are
5557 * the 'return value' and need to utlive this call */
5560 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5563 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5566 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5569 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5572 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5575 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5578 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5580 #if 0 /* disabled until marshalling issues are resolved - gd */
5582 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5586 result = WERR_UNKNOWN_LEVEL;
5591 talloc_free(tmp_ctx);
5595 /****************************************************************
5596 _spoolss_GetPrinterDriver2
5597 ****************************************************************/
5599 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5600 struct spoolss_GetPrinterDriver2 *r)
5602 struct printer_handle *printer;
5607 /* that's an [in out] buffer */
5609 if (!r->in.buffer && (r->in.offered != 0)) {
5610 return WERR_INVALID_PARAM;
5613 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5615 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5616 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5617 return WERR_INVALID_PRINTER_NAME;
5621 *r->out.server_major_version = 0;
5622 *r->out.server_minor_version = 0;
5624 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5628 result = construct_printer_driver_info_level(p->mem_ctx,
5629 get_session_info_system(),
5631 r->in.level, r->out.info,
5632 snum, printer->servername,
5634 r->in.client_major_version);
5635 if (!W_ERROR_IS_OK(result)) {
5636 TALLOC_FREE(r->out.info);
5640 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5641 r->out.info, r->in.level);
5642 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5644 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5648 /****************************************************************
5649 _spoolss_StartPagePrinter
5650 ****************************************************************/
5652 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5653 struct spoolss_StartPagePrinter *r)
5655 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5658 DEBUG(3,("_spoolss_StartPagePrinter: "
5659 "Error in startpageprinter printer handle\n"));
5663 Printer->page_started = true;
5667 /****************************************************************
5668 _spoolss_EndPagePrinter
5669 ****************************************************************/
5671 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5672 struct spoolss_EndPagePrinter *r)
5676 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5679 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5680 OUR_HANDLE(r->in.handle)));
5684 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5687 Printer->page_started = false;
5688 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5693 /****************************************************************
5694 _spoolss_StartDocPrinter
5695 ****************************************************************/
5697 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5698 struct spoolss_StartDocPrinter *r)
5700 struct spoolss_DocumentInfo1 *info_1;
5702 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5708 DEBUG(2,("_spoolss_StartDocPrinter: "
5709 "Invalid handle (%s:%u:%u)\n",
5710 OUR_HANDLE(r->in.handle)));
5714 if (Printer->jobid) {
5715 DEBUG(2, ("_spoolss_StartDocPrinter: "
5716 "StartDocPrinter called twice! "
5717 "(existing jobid = %d)\n", Printer->jobid));
5718 return WERR_INVALID_HANDLE;
5721 if (r->in.level != 1) {
5722 return WERR_UNKNOWN_LEVEL;
5725 info_1 = r->in.info.info1;
5728 * a nice thing with NT is it doesn't listen to what you tell it.
5729 * when asked to send _only_ RAW datas, it tries to send datas
5732 * So I add checks like in NT Server ...
5735 if (info_1->datatype) {
5736 if (strcmp(info_1->datatype, "RAW") != 0) {
5738 return WERR_INVALID_DATATYPE;
5742 /* get the share number of the printer */
5743 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5747 rc = get_remote_hostname(p->remote_address,
5753 if (strequal(rhost,"UNKNOWN")) {
5754 rhost = tsocket_address_inet_addr_string(p->remote_address,
5756 if (rhost == NULL) {
5761 werr = print_job_start(p->session_info,
5765 info_1->document_name,
5766 info_1->output_file,
5770 /* An error occured in print_job_start() so return an appropriate
5773 if (!W_ERROR_IS_OK(werr)) {
5777 Printer->document_started = true;
5778 *r->out.job_id = Printer->jobid;
5783 /****************************************************************
5784 _spoolss_EndDocPrinter
5785 ****************************************************************/
5787 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5788 struct spoolss_EndDocPrinter *r)
5790 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5795 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5796 OUR_HANDLE(r->in.handle)));
5800 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5804 Printer->document_started = false;
5805 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5806 if (!NT_STATUS_IS_OK(status)) {
5807 DEBUG(2, ("_spoolss_EndDocPrinter: "
5808 "print_job_end failed [%s]\n",
5809 nt_errstr(status)));
5813 return ntstatus_to_werror(status);
5816 /****************************************************************
5817 _spoolss_WritePrinter
5818 ****************************************************************/
5820 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5821 struct spoolss_WritePrinter *r)
5823 ssize_t buffer_written;
5825 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5828 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5829 OUR_HANDLE(r->in.handle)));
5830 *r->out.num_written = r->in._data_size;
5834 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5837 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5838 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5839 snum, Printer->jobid,
5840 (const char *)r->in.data.data,
5841 (size_t)r->in._data_size);
5842 if (buffer_written == (ssize_t)-1) {
5843 *r->out.num_written = 0;
5844 if (errno == ENOSPC)
5845 return WERR_NO_SPOOL_SPACE;
5847 return WERR_ACCESS_DENIED;
5850 *r->out.num_written = r->in._data_size;
5855 /********************************************************************
5856 * api_spoolss_getprinter
5857 * called from the spoolss dispatcher
5859 ********************************************************************/
5861 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5862 struct pipes_struct *p)
5864 const struct auth_session_info *session_info = p->session_info;
5866 WERROR errcode = WERR_BADFUNC;
5867 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5870 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5871 OUR_HANDLE(handle)));
5875 if (!get_printer_snum(p, handle, &snum, NULL))
5879 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5880 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5882 case SPOOLSS_PRINTER_CONTROL_RESUME:
5883 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5884 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5886 case SPOOLSS_PRINTER_CONTROL_PURGE:
5887 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5890 return WERR_UNKNOWN_LEVEL;
5897 /****************************************************************
5898 _spoolss_AbortPrinter
5899 * From MSDN: "Deletes printer's spool file if printer is configured
5901 ****************************************************************/
5903 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5904 struct spoolss_AbortPrinter *r)
5906 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5908 WERROR errcode = WERR_OK;
5911 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5912 OUR_HANDLE(r->in.handle)));
5916 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5919 if (!Printer->document_started) {
5920 return WERR_SPL_NO_STARTDOC;
5923 errcode = print_job_delete(p->session_info,
5931 /********************************************************************
5932 * called by spoolss_api_setprinter
5933 * when updating a printer description
5934 ********************************************************************/
5936 static WERROR update_printer_sec(struct policy_handle *handle,
5937 struct pipes_struct *p,
5938 struct sec_desc_buf *secdesc_ctr)
5940 struct spoolss_security_descriptor *new_secdesc = NULL;
5941 struct spoolss_security_descriptor *old_secdesc = NULL;
5942 const char *printer;
5945 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5946 struct dcerpc_binding_handle *b;
5947 TALLOC_CTX *tmp_ctx = NULL;
5949 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5950 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5951 OUR_HANDLE(handle)));
5953 result = WERR_BADFID;
5957 if (secdesc_ctr == NULL) {
5958 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5959 result = WERR_INVALID_PARAM;
5962 printer = lp_const_servicename(snum);
5964 /* Check the user has permissions to change the security
5965 descriptor. By experimentation with two NT machines, the user
5966 requires Full Access to the printer to change security
5969 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5970 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5971 result = WERR_ACCESS_DENIED;
5975 tmp_ctx = talloc_new(p->mem_ctx);
5980 result = winreg_printer_binding_handle(tmp_ctx,
5981 get_session_info_system(),
5984 if (!W_ERROR_IS_OK(result)) {
5988 /* NT seems to like setting the security descriptor even though
5989 nothing may have actually changed. */
5990 result = winreg_get_printer_secdesc(tmp_ctx, b,
5993 if (!W_ERROR_IS_OK(result)) {
5994 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5995 result = WERR_BADFID;
5999 if (DEBUGLEVEL >= 10) {
6000 struct security_acl *the_acl;
6003 the_acl = old_secdesc->dacl;
6004 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6005 printer, the_acl->num_aces));
6007 for (i = 0; i < the_acl->num_aces; i++) {
6008 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6009 &the_acl->aces[i].trustee),
6010 the_acl->aces[i].access_mask));
6013 the_acl = secdesc_ctr->sd->dacl;
6016 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6017 printer, the_acl->num_aces));
6019 for (i = 0; i < the_acl->num_aces; i++) {
6020 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6021 &the_acl->aces[i].trustee),
6022 the_acl->aces[i].access_mask));
6025 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6029 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6030 if (new_secdesc == NULL) {
6031 result = WERR_NOMEM;
6035 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6040 result = winreg_set_printer_secdesc(tmp_ctx, b,
6045 talloc_free(tmp_ctx);
6049 /********************************************************************
6050 Canonicalize printer info from a client
6051 ********************************************************************/
6053 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6054 struct spoolss_SetPrinterInfo2 *info2,
6057 fstring printername;
6060 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6061 "portname=%s drivername=%s comment=%s location=%s\n",
6062 info2->servername, info2->printername, info2->sharename,
6063 info2->portname, info2->drivername, info2->comment,
6066 /* we force some elements to "correct" values */
6067 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6068 if (info2->servername == NULL) {
6071 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6072 if (info2->sharename == NULL) {
6076 /* check to see if we allow printername != sharename */
6077 if (lp_force_printername(snum)) {
6078 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6079 lp_netbios_name(), info2->sharename);
6081 /* make sure printername is in \\server\printername format */
6082 fstrcpy(printername, info2->printername);
6084 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6085 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6089 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6090 lp_netbios_name(), p);
6092 if (info2->printername == NULL) {
6096 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6097 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6102 /****************************************************************************
6103 ****************************************************************************/
6105 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6107 char *cmd = lp_addport_cmd();
6108 char *command = NULL;
6110 bool is_print_op = false;
6113 return WERR_ACCESS_DENIED;
6116 command = talloc_asprintf(ctx,
6117 "%s \"%s\" \"%s\"", cmd, portname, uri );
6123 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6125 DEBUG(10,("Running [%s]\n", command));
6127 /********* BEGIN SePrintOperatorPrivilege **********/
6132 ret = smbrun(command, NULL);
6137 /********* END SePrintOperatorPrivilege **********/
6139 DEBUGADD(10,("returned [%d]\n", ret));
6141 TALLOC_FREE(command);
6144 return WERR_ACCESS_DENIED;
6150 /****************************************************************************
6151 ****************************************************************************/
6153 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6157 * As we do not know if we are embedded in the file server process
6158 * or not, we have to pretend that all shares are in use.
6163 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6164 struct spoolss_SetPrinterInfo2 *info2,
6165 const char *remote_machine,
6166 struct messaging_context *msg_ctx)
6168 char *cmd = lp_addprinter_cmd();
6170 char *command = NULL;
6174 bool is_print_op = false;
6176 if (!remote_machine) {
6180 command = talloc_asprintf(ctx,
6181 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6182 cmd, info2->printername, info2->sharename,
6183 info2->portname, info2->drivername,
6184 info2->location, info2->comment, remote_machine);
6190 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6192 DEBUG(10,("Running [%s]\n", command));
6194 /********* BEGIN SePrintOperatorPrivilege **********/
6199 if ( (ret = smbrun(command, &fd)) == 0 ) {
6200 /* Tell everyone we updated smb.conf. */
6201 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6207 /********* END SePrintOperatorPrivilege **********/
6209 DEBUGADD(10,("returned [%d]\n", ret));
6211 TALLOC_FREE(command);
6219 /* reload our services immediately */
6221 reload_services(NULL, spoolss_conn_snum_used, false);
6225 /* Get lines and convert them back to dos-codepage */
6226 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6227 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6230 /* Set the portname to what the script says the portname should be. */
6231 /* but don't require anything to be return from the script exit a good error code */
6234 /* Set the portname to what the script says the portname should be. */
6235 info2->portname = talloc_strdup(ctx, qlines[0]);
6236 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6239 TALLOC_FREE(qlines);
6243 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6244 const struct auth_session_info *session_info,
6245 struct messaging_context *msg_ctx,
6247 struct spoolss_SetPrinterInfo2 *printer,
6248 struct spoolss_PrinterInfo2 *old_printer)
6250 bool force_update = (old_printer == NULL);
6251 const char *dnsdomname;
6252 const char *longname;
6253 const char *uncname;
6254 const char *spooling;
6256 WERROR result = WERR_OK;
6257 struct dcerpc_binding_handle *b;
6258 TALLOC_CTX *tmp_ctx;
6261 tmp_ctx = talloc_new(mem_ctx);
6266 result = winreg_printer_binding_handle(tmp_ctx,
6270 if (!W_ERROR_IS_OK(result)) {
6274 if (printer->drivername != NULL &&
6276 !strequal(printer->drivername, old_printer->drivername))) {
6277 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6279 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6280 result = WERR_INVALID_DATA;
6283 result = winreg_set_printer_dataex(tmp_ctx, b,
6285 SPOOL_DSSPOOLER_KEY,
6286 SPOOL_REG_DRIVERNAME,
6290 if (!W_ERROR_IS_OK(result)) {
6291 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6295 if (!force_update) {
6296 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6297 printer->drivername));
6299 notify_printer_driver(server_event_context(), msg_ctx,
6300 snum, printer->drivername ?
6301 printer->drivername : "");
6305 if (printer->comment != NULL &&
6307 !strequal(printer->comment, old_printer->comment))) {
6308 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6310 DEBUG(0, ("comment data corrupted\n"));
6311 result = WERR_INVALID_DATA;
6314 result = winreg_set_printer_dataex(tmp_ctx, b,
6316 SPOOL_DSSPOOLER_KEY,
6317 SPOOL_REG_DESCRIPTION,
6321 if (!W_ERROR_IS_OK(result)) {
6322 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6326 if (!force_update) {
6327 notify_printer_comment(server_event_context(), msg_ctx,
6328 snum, printer->comment ?
6329 printer->comment : "");
6333 if (printer->sharename != NULL &&
6335 !strequal(printer->sharename, old_printer->sharename))) {
6336 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6338 DEBUG(0, ("sharename data corrupted\n"));
6339 result = WERR_INVALID_DATA;
6342 result = winreg_set_printer_dataex(tmp_ctx, b,
6344 SPOOL_DSSPOOLER_KEY,
6345 SPOOL_REG_PRINTSHARENAME,
6349 if (!W_ERROR_IS_OK(result)) {
6350 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6354 if (!force_update) {
6355 notify_printer_sharename(server_event_context(),
6357 snum, printer->sharename ?
6358 printer->sharename : "");
6362 if (printer->printername != NULL &&
6364 !strequal(printer->printername, old_printer->printername))) {
6367 p = strrchr(printer->printername, '\\' );
6371 p = printer->printername;
6374 ok = push_reg_sz(tmp_ctx, &buffer, p);
6376 DEBUG(0, ("printername data corrupted\n"));
6377 result = WERR_INVALID_DATA;
6380 result = winreg_set_printer_dataex(tmp_ctx, b,
6382 SPOOL_DSSPOOLER_KEY,
6383 SPOOL_REG_PRINTERNAME,
6387 if (!W_ERROR_IS_OK(result)) {
6388 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6392 if (!force_update) {
6393 notify_printer_printername(server_event_context(),
6394 msg_ctx, snum, p ? p : "");
6398 if (printer->portname != NULL &&
6400 !strequal(printer->portname, old_printer->portname))) {
6401 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6403 DEBUG(0, ("portname data corrupted\n"));
6404 result = WERR_INVALID_DATA;
6407 result = winreg_set_printer_dataex(tmp_ctx, b,
6409 SPOOL_DSSPOOLER_KEY,
6414 if (!W_ERROR_IS_OK(result)) {
6415 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6419 if (!force_update) {
6420 notify_printer_port(server_event_context(),
6421 msg_ctx, snum, printer->portname ?
6422 printer->portname : "");
6426 if (printer->location != NULL &&
6428 !strequal(printer->location, old_printer->location))) {
6429 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6431 DEBUG(0, ("location data corrupted\n"));
6432 result = WERR_INVALID_DATA;
6435 result = winreg_set_printer_dataex(tmp_ctx, b,
6437 SPOOL_DSSPOOLER_KEY,
6442 if (!W_ERROR_IS_OK(result)) {
6443 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6447 if (!force_update) {
6448 notify_printer_location(server_event_context(),
6451 printer->location : "");
6455 if (printer->sepfile != NULL &&
6457 !strequal(printer->sepfile, old_printer->sepfile))) {
6458 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6460 DEBUG(0, ("sepfile data corrupted\n"));
6461 result = WERR_INVALID_DATA;
6464 result = winreg_set_printer_dataex(tmp_ctx, b,
6466 SPOOL_DSSPOOLER_KEY,
6467 SPOOL_REG_PRINTSEPARATORFILE,
6471 if (!W_ERROR_IS_OK(result)) {
6472 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6476 if (!force_update) {
6477 notify_printer_sepfile(server_event_context(),
6480 printer->sepfile : "");
6484 if (printer->starttime != 0 &&
6486 printer->starttime != old_printer->starttime)) {
6487 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6488 SIVAL(buffer.data, 0, printer->starttime);
6489 result = winreg_set_printer_dataex(tmp_ctx, b,
6491 SPOOL_DSSPOOLER_KEY,
6492 SPOOL_REG_PRINTSTARTTIME,
6496 if (!W_ERROR_IS_OK(result)) {
6497 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6502 if (printer->untiltime != 0 &&
6504 printer->untiltime != old_printer->untiltime)) {
6505 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6506 SIVAL(buffer.data, 0, printer->untiltime);
6507 result = winreg_set_printer_dataex(tmp_ctx, b,
6509 SPOOL_DSSPOOLER_KEY,
6510 SPOOL_REG_PRINTENDTIME,
6514 if (!W_ERROR_IS_OK(result)) {
6515 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6520 if (force_update || printer->priority != old_printer->priority) {
6521 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6522 SIVAL(buffer.data, 0, printer->priority);
6523 result = winreg_set_printer_dataex(tmp_ctx, b,
6525 SPOOL_DSSPOOLER_KEY,
6530 if (!W_ERROR_IS_OK(result)) {
6531 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6536 if (force_update || printer->attributes != old_printer->attributes) {
6537 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6538 SIVAL(buffer.data, 0, (printer->attributes &
6539 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6540 result = winreg_set_printer_dataex(tmp_ctx, b,
6542 SPOOL_DSSPOOLER_KEY,
6543 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6547 if (!W_ERROR_IS_OK(result)) {
6548 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6552 switch (printer->attributes & 0x3) {
6554 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6557 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6560 spooling = SPOOL_REGVAL_PRINTDIRECT;
6563 spooling = "unknown";
6565 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6567 DEBUG(0, ("printSpooling data corrupted\n"));
6568 result = WERR_INVALID_DATA;
6571 winreg_set_printer_dataex(tmp_ctx, b,
6573 SPOOL_DSSPOOLER_KEY,
6574 SPOOL_REG_PRINTSPOOLING,
6580 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6582 DEBUG(0, ("shortServerName data corrupted\n"));
6583 result = WERR_INVALID_DATA;
6586 result = winreg_set_printer_dataex(tmp_ctx, b,
6588 SPOOL_DSSPOOLER_KEY,
6589 SPOOL_REG_SHORTSERVERNAME,
6593 if (!W_ERROR_IS_OK(result)) {
6594 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6598 dnsdomname = get_mydnsfullname();
6599 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6600 longname = talloc_strdup(tmp_ctx, dnsdomname);
6602 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6604 if (longname == NULL) {
6605 result = WERR_NOMEM;
6609 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6611 DEBUG(0, ("longname data corrupted\n"));
6612 result = WERR_INVALID_DATA;
6615 result = winreg_set_printer_dataex(tmp_ctx, b,
6617 SPOOL_DSSPOOLER_KEY,
6618 SPOOL_REG_SERVERNAME,
6622 if (!W_ERROR_IS_OK(result)) {
6623 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6627 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6628 lp_netbios_name(), printer->sharename);
6629 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6631 DEBUG(0, ("uncName data corrupted\n"));
6632 result = WERR_INVALID_DATA;
6635 result = winreg_set_printer_dataex(tmp_ctx, b,
6637 SPOOL_DSSPOOLER_KEY,
6642 if (!W_ERROR_IS_OK(result)) {
6643 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6648 talloc_free(tmp_ctx);
6652 /********************************************************************
6653 * Called by spoolss_api_setprinter
6654 * when updating a printer description.
6655 ********************************************************************/
6657 static WERROR update_printer(struct pipes_struct *p,
6658 struct policy_handle *handle,
6659 struct spoolss_SetPrinterInfoCtr *info_ctr,
6660 struct spoolss_DeviceMode *devmode)
6662 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6663 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6664 struct spoolss_PrinterInfo2 *old_printer;
6665 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6667 WERROR result = WERR_OK;
6668 TALLOC_CTX *tmp_ctx;
6669 struct dcerpc_binding_handle *b;
6671 DEBUG(8,("update_printer\n"));
6673 tmp_ctx = talloc_new(p->mem_ctx);
6674 if (tmp_ctx == NULL) {
6679 result = WERR_BADFID;
6683 if (!get_printer_snum(p, handle, &snum, NULL)) {
6684 result = WERR_BADFID;
6688 result = winreg_printer_binding_handle(tmp_ctx,
6689 get_session_info_system(),
6692 if (!W_ERROR_IS_OK(result)) {
6696 result = winreg_get_printer(tmp_ctx, b,
6697 lp_const_servicename(snum),
6699 if (!W_ERROR_IS_OK(result)) {
6700 result = WERR_BADFID;
6704 /* Do sanity check on the requested changes for Samba */
6705 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6706 result = WERR_INVALID_PARAM;
6710 /* FIXME!!! If the driver has changed we really should verify that
6711 it is installed before doing much else --jerry */
6713 /* Check calling user has permission to update printer description */
6714 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6715 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6716 result = WERR_ACCESS_DENIED;
6720 /* Call addprinter hook */
6721 /* Check changes to see if this is really needed */
6723 if (*lp_addprinter_cmd() &&
6724 (!strequal(printer->drivername, old_printer->drivername) ||
6725 !strequal(printer->comment, old_printer->comment) ||
6726 !strequal(printer->portname, old_printer->portname) ||
6727 !strequal(printer->location, old_printer->location)) )
6731 raddr = tsocket_address_inet_addr_string(p->remote_address,
6733 if (raddr == NULL) {
6737 /* add_printer_hook() will call reload_services() */
6738 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6741 result = WERR_ACCESS_DENIED;
6746 result = update_dsspooler(tmp_ctx,
6747 get_session_info_system(),
6752 if (!W_ERROR_IS_OK(result)) {
6756 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6758 if (devmode == NULL) {
6759 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6761 result = winreg_update_printer(tmp_ctx, b,
6769 talloc_free(tmp_ctx);
6774 /****************************************************************************
6775 ****************************************************************************/
6776 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6777 struct policy_handle *handle,
6778 struct spoolss_SetPrinterInfo7 *info7)
6781 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6784 struct printer_handle *Printer;
6786 if ( lp_security() != SEC_ADS ) {
6787 return WERR_UNKNOWN_LEVEL;
6790 Printer = find_printer_index_by_hnd(p, handle);
6792 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6797 if (!get_printer_snum(p, handle, &snum, NULL))
6800 result = winreg_get_printer_internal(p->mem_ctx,
6801 get_session_info_system(),
6803 lp_servicename(snum),
6805 if (!W_ERROR_IS_OK(result)) {
6809 nt_printer_publish(pinfo2,
6810 get_session_info_system(),
6815 TALLOC_FREE(pinfo2);
6818 return WERR_UNKNOWN_LEVEL;
6822 /********************************************************************
6823 ********************************************************************/
6825 static WERROR update_printer_devmode(struct pipes_struct *p,
6826 struct policy_handle *handle,
6827 struct spoolss_DeviceMode *devmode)
6830 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6831 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6833 DEBUG(8,("update_printer_devmode\n"));
6839 if (!get_printer_snum(p, handle, &snum, NULL)) {
6843 /* Check calling user has permission to update printer description */
6844 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6845 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6846 return WERR_ACCESS_DENIED;
6849 return winreg_update_printer_internal(p->mem_ctx,
6850 get_session_info_system(),
6852 lp_const_servicename(snum),
6860 /****************************************************************
6862 ****************************************************************/
6864 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6865 struct spoolss_SetPrinter *r)
6869 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6872 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6873 OUR_HANDLE(r->in.handle)));
6877 /* check the level */
6878 switch (r->in.info_ctr->level) {
6880 return control_printer(r->in.handle, r->in.command, p);
6882 result = update_printer(p, r->in.handle,
6884 r->in.devmode_ctr->devmode);
6885 if (!W_ERROR_IS_OK(result))
6887 if (r->in.secdesc_ctr->sd)
6888 result = update_printer_sec(r->in.handle, p,
6892 return update_printer_sec(r->in.handle, p,
6895 return publish_or_unpublish_printer(p, r->in.handle,
6896 r->in.info_ctr->info.info7);
6898 return update_printer_devmode(p, r->in.handle,
6899 r->in.devmode_ctr->devmode);
6901 return WERR_UNKNOWN_LEVEL;
6905 /****************************************************************
6906 _spoolss_FindClosePrinterNotify
6907 ****************************************************************/
6909 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6910 struct spoolss_FindClosePrinterNotify *r)
6912 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6915 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6916 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6920 if (Printer->notify.cli_chan != NULL &&
6921 Printer->notify.cli_chan->active_connections > 0) {
6924 if (Printer->printer_type == SPLHND_PRINTER) {
6925 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6930 srv_spoolss_replycloseprinter(snum, Printer);
6933 Printer->notify.flags=0;
6934 Printer->notify.options=0;
6935 Printer->notify.localmachine[0]='\0';
6936 Printer->notify.printerlocal=0;
6937 TALLOC_FREE(Printer->notify.option);
6942 /****************************************************************
6944 ****************************************************************/
6946 WERROR _spoolss_AddJob(struct pipes_struct *p,
6947 struct spoolss_AddJob *r)
6949 if (!r->in.buffer && (r->in.offered != 0)) {
6950 return WERR_INVALID_PARAM;
6953 /* this is what a NT server returns for AddJob. AddJob must fail on
6954 * non-local printers */
6956 if (r->in.level != 1) {
6957 return WERR_UNKNOWN_LEVEL;
6960 return WERR_INVALID_PARAM;
6963 /****************************************************************************
6965 ****************************************************************************/
6967 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6968 struct spoolss_JobInfo1 *r,
6969 const print_queue_struct *queue,
6970 int position, int snum,
6971 struct spoolss_PrinterInfo2 *pinfo2)
6975 t = gmtime(&queue->time);
6977 r->job_id = queue->job;
6979 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6980 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6981 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6982 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6983 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6984 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6985 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6986 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6987 r->data_type = talloc_strdup(mem_ctx, "RAW");
6988 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6989 r->text_status = talloc_strdup(mem_ctx, "");
6990 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6992 r->status = nt_printj_status(queue->status);
6993 r->priority = queue->priority;
6994 r->position = position;
6995 r->total_pages = queue->page_count;
6996 r->pages_printed = 0; /* ??? */
6998 init_systemtime(&r->submitted, t);
7003 /****************************************************************************
7005 ****************************************************************************/
7007 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7008 struct spoolss_JobInfo2 *r,
7009 const print_queue_struct *queue,
7010 int position, int snum,
7011 struct spoolss_PrinterInfo2 *pinfo2,
7012 struct spoolss_DeviceMode *devmode)
7016 t = gmtime(&queue->time);
7018 r->job_id = queue->job;
7020 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
7021 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7022 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7023 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7024 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7025 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7026 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7027 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7028 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7029 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7030 r->data_type = talloc_strdup(mem_ctx, "RAW");
7031 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7032 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7033 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7034 r->parameters = talloc_strdup(mem_ctx, "");
7035 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7036 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7037 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7039 r->devmode = devmode;
7041 r->text_status = talloc_strdup(mem_ctx, "");
7042 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7046 r->status = nt_printj_status(queue->status);
7047 r->priority = queue->priority;
7048 r->position = position;
7051 r->total_pages = queue->page_count;
7052 r->size = queue->size;
7053 init_systemtime(&r->submitted, t);
7055 r->pages_printed = 0; /* ??? */
7060 /****************************************************************************
7062 ****************************************************************************/
7064 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7065 struct spoolss_JobInfo3 *r,
7066 const print_queue_struct *queue,
7067 const print_queue_struct *next_queue,
7068 int position, int snum,
7069 struct spoolss_PrinterInfo2 *pinfo2)
7071 r->job_id = queue->job;
7074 r->next_job_id = next_queue->job;
7081 /****************************************************************************
7082 Enumjobs at level 1.
7083 ****************************************************************************/
7085 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7086 const print_queue_struct *queue,
7087 uint32_t num_queues, int snum,
7088 struct spoolss_PrinterInfo2 *pinfo2,
7089 union spoolss_JobInfo **info_p,
7092 union spoolss_JobInfo *info;
7094 WERROR result = WERR_OK;
7096 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7097 W_ERROR_HAVE_NO_MEMORY(info);
7099 *count = num_queues;
7101 for (i=0; i<*count; i++) {
7102 result = fill_job_info1(info,
7108 if (!W_ERROR_IS_OK(result)) {
7114 if (!W_ERROR_IS_OK(result)) {
7125 /****************************************************************************
7126 Enumjobs at level 2.
7127 ****************************************************************************/
7129 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7130 const print_queue_struct *queue,
7131 uint32_t num_queues, int snum,
7132 struct spoolss_PrinterInfo2 *pinfo2,
7133 union spoolss_JobInfo **info_p,
7136 union spoolss_JobInfo *info;
7138 WERROR result = WERR_OK;
7140 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7141 W_ERROR_HAVE_NO_MEMORY(info);
7143 *count = num_queues;
7145 for (i=0; i<*count; i++) {
7146 struct spoolss_DeviceMode *devmode;
7148 result = spoolss_create_default_devmode(info,
7149 pinfo2->printername,
7151 if (!W_ERROR_IS_OK(result)) {
7152 DEBUG(3, ("Can't proceed w/o a devmode!"));
7156 result = fill_job_info2(info,
7163 if (!W_ERROR_IS_OK(result)) {
7169 if (!W_ERROR_IS_OK(result)) {
7180 /****************************************************************************
7181 Enumjobs at level 3.
7182 ****************************************************************************/
7184 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7185 const print_queue_struct *queue,
7186 uint32_t num_queues, int snum,
7187 struct spoolss_PrinterInfo2 *pinfo2,
7188 union spoolss_JobInfo **info_p,
7191 union spoolss_JobInfo *info;
7193 WERROR result = WERR_OK;
7195 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7196 W_ERROR_HAVE_NO_MEMORY(info);
7198 *count = num_queues;
7200 for (i=0; i<*count; i++) {
7201 const print_queue_struct *next_queue = NULL;
7204 next_queue = &queue[i+1];
7207 result = fill_job_info3(info,
7214 if (!W_ERROR_IS_OK(result)) {
7220 if (!W_ERROR_IS_OK(result)) {
7231 /****************************************************************
7233 ****************************************************************/
7235 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7236 struct spoolss_EnumJobs *r)
7239 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7241 print_status_struct prt_status;
7242 print_queue_struct *queue = NULL;
7245 /* that's an [in out] buffer */
7247 if (!r->in.buffer && (r->in.offered != 0)) {
7248 return WERR_INVALID_PARAM;
7251 DEBUG(4,("_spoolss_EnumJobs\n"));
7255 *r->out.info = NULL;
7257 /* lookup the printer snum and tdb entry */
7259 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7263 result = winreg_get_printer_internal(p->mem_ctx,
7264 get_session_info_system(),
7266 lp_const_servicename(snum),
7268 if (!W_ERROR_IS_OK(result)) {
7272 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7273 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7274 count, prt_status.status, prt_status.message));
7278 TALLOC_FREE(pinfo2);
7282 switch (r->in.level) {
7284 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7285 pinfo2, r->out.info, r->out.count);
7288 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7289 pinfo2, r->out.info, r->out.count);
7292 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7293 pinfo2, r->out.info, r->out.count);
7296 result = WERR_UNKNOWN_LEVEL;
7301 TALLOC_FREE(pinfo2);
7303 if (!W_ERROR_IS_OK(result)) {
7307 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7309 *r->out.info, r->in.level,
7311 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7312 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7314 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7317 /****************************************************************
7318 _spoolss_ScheduleJob
7319 ****************************************************************/
7321 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7322 struct spoolss_ScheduleJob *r)
7327 /****************************************************************
7328 ****************************************************************/
7330 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7331 struct messaging_context *msg_ctx,
7332 const char *printer_name,
7334 struct spoolss_SetJobInfo1 *r)
7338 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7342 if (strequal(old_doc_name, r->document_name)) {
7346 if (!print_job_set_name(server_event_context(), msg_ctx,
7347 printer_name, job_id, r->document_name)) {
7354 /****************************************************************
7356 ****************************************************************/
7358 WERROR _spoolss_SetJob(struct pipes_struct *p,
7359 struct spoolss_SetJob *r)
7361 const struct auth_session_info *session_info = p->session_info;
7363 WERROR errcode = WERR_BADFUNC;
7365 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7369 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7370 return WERR_INVALID_PRINTER_NAME;
7373 switch (r->in.command) {
7374 case SPOOLSS_JOB_CONTROL_CANCEL:
7375 case SPOOLSS_JOB_CONTROL_DELETE:
7376 errcode = print_job_delete(session_info, p->msg_ctx,
7377 snum, r->in.job_id);
7378 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7382 case SPOOLSS_JOB_CONTROL_PAUSE:
7383 if (print_job_pause(session_info, p->msg_ctx,
7384 snum, r->in.job_id, &errcode)) {
7388 case SPOOLSS_JOB_CONTROL_RESTART:
7389 case SPOOLSS_JOB_CONTROL_RESUME:
7390 if (print_job_resume(session_info, p->msg_ctx,
7391 snum, r->in.job_id, &errcode)) {
7399 return WERR_UNKNOWN_LEVEL;
7402 if (!W_ERROR_IS_OK(errcode)) {
7406 if (r->in.ctr == NULL) {
7410 switch (r->in.ctr->level) {
7412 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7413 lp_const_servicename(snum),
7415 r->in.ctr->info.info1);
7421 return WERR_UNKNOWN_LEVEL;
7427 /****************************************************************************
7428 Enumerates all printer drivers by level and architecture.
7429 ****************************************************************************/
7431 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7432 const struct auth_session_info *session_info,
7433 struct messaging_context *msg_ctx,
7434 const char *servername,
7435 const char *architecture,
7437 union spoolss_DriverInfo **info_p,
7442 struct spoolss_DriverInfo8 *driver;
7443 union spoolss_DriverInfo *info = NULL;
7445 WERROR result = WERR_OK;
7446 uint32_t num_drivers;
7447 const char **drivers;
7448 struct dcerpc_binding_handle *b;
7449 TALLOC_CTX *tmp_ctx = NULL;
7454 tmp_ctx = talloc_new(mem_ctx);
7459 result = winreg_printer_binding_handle(tmp_ctx,
7463 if (!W_ERROR_IS_OK(result)) {
7467 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7468 result = winreg_get_driver_list(tmp_ctx, b,
7469 architecture, version,
7470 &num_drivers, &drivers);
7471 if (!W_ERROR_IS_OK(result)) {
7474 DEBUG(4, ("we have:[%d] drivers in environment"
7475 " [%s] and version [%d]\n",
7476 num_drivers, architecture, version));
7478 if (num_drivers != 0) {
7479 info = talloc_realloc(tmp_ctx, info,
7480 union spoolss_DriverInfo,
7481 count + num_drivers);
7483 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7484 "failed to enlarge driver info buffer!\n"));
7485 result = WERR_NOMEM;
7490 for (i = 0; i < num_drivers; i++) {
7491 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7493 result = winreg_get_driver(tmp_ctx, b,
7494 architecture, drivers[i],
7496 if (!W_ERROR_IS_OK(result)) {
7502 result = fill_printer_driver_info1(info, &info[count+i].info1,
7503 driver, servername);
7506 result = fill_printer_driver_info2(info, &info[count+i].info2,
7507 driver, servername);
7510 result = fill_printer_driver_info3(info, &info[count+i].info3,
7511 driver, servername);
7514 result = fill_printer_driver_info4(info, &info[count+i].info4,
7515 driver, servername);
7518 result = fill_printer_driver_info5(info, &info[count+i].info5,
7519 driver, servername);
7522 result = fill_printer_driver_info6(info, &info[count+i].info6,
7523 driver, servername);
7526 result = fill_printer_driver_info8(info, &info[count+i].info8,
7527 driver, servername);
7530 result = WERR_UNKNOWN_LEVEL;
7534 TALLOC_FREE(driver);
7536 if (!W_ERROR_IS_OK(result)) {
7541 count += num_drivers;
7542 TALLOC_FREE(drivers);
7546 if (W_ERROR_IS_OK(result)) {
7547 *info_p = talloc_move(mem_ctx, &info);
7551 talloc_free(tmp_ctx);
7555 /****************************************************************************
7556 Enumerates all printer drivers by level.
7557 ****************************************************************************/
7559 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7560 const struct auth_session_info *session_info,
7561 struct messaging_context *msg_ctx,
7562 const char *servername,
7563 const char *architecture,
7565 union spoolss_DriverInfo **info_p,
7569 WERROR result = WERR_OK;
7571 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7573 for (a=0; archi_table[a].long_archi != NULL; a++) {
7575 union spoolss_DriverInfo *info = NULL;
7578 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7582 archi_table[a].long_archi,
7586 if (!W_ERROR_IS_OK(result)) {
7590 for (i=0; i < count; i++) {
7591 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7592 info[i], info_p, count_p);
7599 return enumprinterdrivers_level_by_architecture(mem_ctx,
7609 /****************************************************************
7610 _spoolss_EnumPrinterDrivers
7611 ****************************************************************/
7613 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7614 struct spoolss_EnumPrinterDrivers *r)
7616 const char *cservername;
7619 /* that's an [in out] buffer */
7621 if (!r->in.buffer && (r->in.offered != 0)) {
7622 return WERR_INVALID_PARAM;
7625 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7629 *r->out.info = NULL;
7631 cservername = canon_servername(r->in.server);
7633 if (!is_myname_or_ipaddr(cservername)) {
7634 return WERR_UNKNOWN_PRINTER_DRIVER;
7637 result = enumprinterdrivers_level(p->mem_ctx,
7638 get_session_info_system(),
7645 if (!W_ERROR_IS_OK(result)) {
7649 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7650 spoolss_EnumPrinterDrivers,
7651 *r->out.info, r->in.level,
7653 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7654 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7656 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7659 /****************************************************************
7661 ****************************************************************/
7663 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7664 struct spoolss_EnumForms *r)
7670 *r->out.info = NULL;
7672 /* that's an [in out] buffer */
7674 if (!r->in.buffer && (r->in.offered != 0) ) {
7675 return WERR_INVALID_PARAM;
7678 DEBUG(4,("_spoolss_EnumForms\n"));
7679 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7680 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7682 switch (r->in.level) {
7684 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7685 get_session_info_system(),
7691 result = WERR_UNKNOWN_LEVEL;
7695 if (!W_ERROR_IS_OK(result)) {
7699 if (*r->out.count == 0) {
7700 return WERR_NO_MORE_ITEMS;
7703 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7705 *r->out.info, r->in.level,
7707 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7708 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7710 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7713 /****************************************************************
7715 ****************************************************************/
7717 WERROR _spoolss_GetForm(struct pipes_struct *p,
7718 struct spoolss_GetForm *r)
7722 /* that's an [in out] buffer */
7724 if (!r->in.buffer && (r->in.offered != 0)) {
7725 return WERR_INVALID_PARAM;
7728 DEBUG(4,("_spoolss_GetForm\n"));
7729 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7730 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7732 switch (r->in.level) {
7734 result = winreg_printer_getform1_internal(p->mem_ctx,
7735 get_session_info_system(),
7738 &r->out.info->info1);
7741 result = WERR_UNKNOWN_LEVEL;
7745 if (!W_ERROR_IS_OK(result)) {
7746 TALLOC_FREE(r->out.info);
7750 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7751 r->out.info, r->in.level);
7752 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7754 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7757 /****************************************************************************
7758 ****************************************************************************/
7760 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7761 struct spoolss_PortInfo1 *r,
7764 r->port_name = talloc_strdup(mem_ctx, name);
7765 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7770 /****************************************************************************
7771 TODO: This probably needs distinguish between TCP/IP and Local ports
7773 ****************************************************************************/
7775 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7776 struct spoolss_PortInfo2 *r,
7779 r->port_name = talloc_strdup(mem_ctx, name);
7780 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7782 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7783 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7785 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7786 W_ERROR_HAVE_NO_MEMORY(r->description);
7788 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7795 /****************************************************************************
7796 wrapper around the enumer ports command
7797 ****************************************************************************/
7799 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7801 char *cmd = lp_enumports_cmd();
7802 char **qlines = NULL;
7803 char *command = NULL;
7811 /* if no hook then just fill in the default port */
7814 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7817 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7818 TALLOC_FREE(qlines);
7825 /* we have a valid enumport command */
7827 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7832 DEBUG(10,("Running [%s]\n", command));
7833 ret = smbrun(command, &fd);
7834 DEBUG(10,("Returned [%d]\n", ret));
7835 TALLOC_FREE(command);
7840 return WERR_ACCESS_DENIED;
7844 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7845 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7855 /****************************************************************************
7857 ****************************************************************************/
7859 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7860 union spoolss_PortInfo **info_p,
7863 union spoolss_PortInfo *info = NULL;
7865 WERROR result = WERR_OK;
7866 char **qlines = NULL;
7869 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7870 if (!W_ERROR_IS_OK(result)) {
7875 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7877 DEBUG(10,("Returning WERR_NOMEM\n"));
7878 result = WERR_NOMEM;
7882 for (i=0; i<numlines; i++) {
7883 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7884 result = fill_port_1(info, &info[i].info1, qlines[i]);
7885 if (!W_ERROR_IS_OK(result)) {
7890 TALLOC_FREE(qlines);
7893 if (!W_ERROR_IS_OK(result)) {
7895 TALLOC_FREE(qlines);
7907 /****************************************************************************
7909 ****************************************************************************/
7911 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7912 union spoolss_PortInfo **info_p,
7915 union spoolss_PortInfo *info = NULL;
7917 WERROR result = WERR_OK;
7918 char **qlines = NULL;
7921 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7922 if (!W_ERROR_IS_OK(result)) {
7927 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7929 DEBUG(10,("Returning WERR_NOMEM\n"));
7930 result = WERR_NOMEM;
7934 for (i=0; i<numlines; i++) {
7935 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7936 result = fill_port_2(info, &info[i].info2, qlines[i]);
7937 if (!W_ERROR_IS_OK(result)) {
7942 TALLOC_FREE(qlines);
7945 if (!W_ERROR_IS_OK(result)) {
7947 TALLOC_FREE(qlines);
7959 /****************************************************************
7961 ****************************************************************/
7963 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7964 struct spoolss_EnumPorts *r)
7968 /* that's an [in out] buffer */
7970 if (!r->in.buffer && (r->in.offered != 0)) {
7971 return WERR_INVALID_PARAM;
7974 DEBUG(4,("_spoolss_EnumPorts\n"));
7978 *r->out.info = NULL;
7980 switch (r->in.level) {
7982 result = enumports_level_1(p->mem_ctx, r->out.info,
7986 result = enumports_level_2(p->mem_ctx, r->out.info,
7990 return WERR_UNKNOWN_LEVEL;
7993 if (!W_ERROR_IS_OK(result)) {
7997 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7999 *r->out.info, r->in.level,
8001 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8002 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8004 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8007 /****************************************************************************
8008 ****************************************************************************/
8010 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8012 struct spoolss_SetPrinterInfoCtr *info_ctr,
8013 struct spoolss_DeviceMode *devmode,
8014 struct security_descriptor *secdesc,
8015 struct spoolss_UserLevelCtr *user_ctr,
8016 struct policy_handle *handle)
8018 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8019 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8021 WERROR err = WERR_OK;
8023 /* samba does not have a concept of local, non-shared printers yet, so
8024 * make sure we always setup sharename - gd */
8025 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8026 (info2->printername != NULL && info2->printername[0] != '\0')) {
8027 DEBUG(5, ("spoolss_addprinterex_level_2: "
8028 "no sharename has been set, setting printername %s as sharename\n",
8029 info2->printername));
8030 info2->sharename = info2->printername;
8033 /* check to see if the printer already exists */
8034 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8035 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8037 return WERR_PRINTER_ALREADY_EXISTS;
8040 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8041 if ((snum = print_queue_snum(info2->printername)) != -1) {
8042 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8043 info2->printername));
8044 return WERR_PRINTER_ALREADY_EXISTS;
8048 /* validate printer info struct */
8049 if (!info2->printername || strlen(info2->printername) == 0) {
8050 return WERR_INVALID_PRINTER_NAME;
8052 if (!info2->portname || strlen(info2->portname) == 0) {
8053 return WERR_UNKNOWN_PORT;
8055 if (!info2->drivername || strlen(info2->drivername) == 0) {
8056 return WERR_UNKNOWN_PRINTER_DRIVER;
8058 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8059 return WERR_UNKNOWN_PRINTPROCESSOR;
8062 /* FIXME!!! smbd should check to see if the driver is installed before
8063 trying to add a printer like this --jerry */
8065 if (*lp_addprinter_cmd() ) {
8068 raddr = tsocket_address_inet_addr_string(p->remote_address,
8070 if (raddr == NULL) {
8074 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8077 return WERR_ACCESS_DENIED;
8080 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8081 "smb.conf parameter \"addprinter command\" is defined. This "
8082 "parameter must exist for this call to succeed\n",
8083 info2->sharename ));
8086 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8087 return WERR_ACCESS_DENIED;
8090 /* you must be a printer admin to add a new printer */
8091 if (!print_access_check(p->session_info,
8094 PRINTER_ACCESS_ADMINISTER)) {
8095 return WERR_ACCESS_DENIED;
8099 * Do sanity check on the requested changes for Samba.
8102 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8103 return WERR_INVALID_PARAM;
8106 if (devmode == NULL) {
8107 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8110 err = update_dsspooler(p->mem_ctx,
8111 get_session_info_system(),
8116 if (!W_ERROR_IS_OK(err)) {
8120 err = winreg_update_printer_internal(p->mem_ctx,
8121 get_session_info_system(),
8128 if (!W_ERROR_IS_OK(err)) {
8132 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8133 if (!W_ERROR_IS_OK(err)) {
8134 /* Handle open failed - remove addition. */
8135 ZERO_STRUCTP(handle);
8142 /****************************************************************
8143 _spoolss_AddPrinterEx
8144 ****************************************************************/
8146 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8147 struct spoolss_AddPrinterEx *r)
8149 switch (r->in.info_ctr->level) {
8151 /* we don't handle yet */
8152 /* but I know what to do ... */
8153 return WERR_UNKNOWN_LEVEL;
8155 return spoolss_addprinterex_level_2(p, r->in.server,
8157 r->in.devmode_ctr->devmode,
8158 r->in.secdesc_ctr->sd,
8159 r->in.userlevel_ctr,
8162 return WERR_UNKNOWN_LEVEL;
8166 /****************************************************************
8168 ****************************************************************/
8170 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8171 struct spoolss_AddPrinter *r)
8173 struct spoolss_AddPrinterEx a;
8174 struct spoolss_UserLevelCtr userlevel_ctr;
8176 ZERO_STRUCT(userlevel_ctr);
8178 userlevel_ctr.level = 1;
8180 a.in.server = r->in.server;
8181 a.in.info_ctr = r->in.info_ctr;
8182 a.in.devmode_ctr = r->in.devmode_ctr;
8183 a.in.secdesc_ctr = r->in.secdesc_ctr;
8184 a.in.userlevel_ctr = &userlevel_ctr;
8185 a.out.handle = r->out.handle;
8187 return _spoolss_AddPrinterEx(p, &a);
8190 /****************************************************************
8191 _spoolss_AddPrinterDriverEx
8192 ****************************************************************/
8194 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8195 struct spoolss_AddPrinterDriverEx *r)
8197 WERROR err = WERR_OK;
8198 const char *driver_name = NULL;
8203 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8204 fn = "_spoolss_AddPrinterDriver";
8206 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8207 fn = "_spoolss_AddPrinterDriverEx";
8210 return WERR_INVALID_PARAM;
8214 * we only support the semantics of AddPrinterDriver()
8215 * i.e. only copy files that are newer than existing ones
8218 if (r->in.flags == 0) {
8219 return WERR_INVALID_PARAM;
8222 if (r->in.flags != APD_COPY_NEW_FILES) {
8223 return WERR_ACCESS_DENIED;
8227 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8228 /* Clever hack from Martin Zielinski <mz@seh.de>
8229 * to allow downgrade from level 8 (Vista).
8231 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8232 r->in.info_ctr->level));
8233 return WERR_UNKNOWN_LEVEL;
8236 DEBUG(5,("Cleaning driver's information\n"));
8237 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8238 if (!W_ERROR_IS_OK(err))
8241 DEBUG(5,("Moving driver to final destination\n"));
8242 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8243 if (!W_ERROR_IS_OK(err)) {
8247 err = winreg_add_driver_internal(p->mem_ctx,
8248 get_session_info_system(),
8253 if (!W_ERROR_IS_OK(err)) {
8258 * I think this is where he DrvUpgradePrinter() hook would be
8259 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8260 * server. Right now, we just need to send ourselves a message
8261 * to update each printer bound to this driver. --jerry
8264 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8265 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8273 /****************************************************************
8274 _spoolss_AddPrinterDriver
8275 ****************************************************************/
8277 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8278 struct spoolss_AddPrinterDriver *r)
8280 struct spoolss_AddPrinterDriverEx a;
8282 switch (r->in.info_ctr->level) {
8289 return WERR_UNKNOWN_LEVEL;
8292 a.in.servername = r->in.servername;
8293 a.in.info_ctr = r->in.info_ctr;
8294 a.in.flags = APD_COPY_NEW_FILES;
8296 return _spoolss_AddPrinterDriverEx(p, &a);
8299 /****************************************************************************
8300 ****************************************************************************/
8302 struct _spoolss_paths {
8308 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8310 static const struct _spoolss_paths spoolss_paths[]= {
8311 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8312 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8315 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8316 const char *servername,
8317 const char *environment,
8321 const char *pservername = NULL;
8322 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8323 const char *short_archi;
8327 /* environment may be empty */
8328 if (environment && strlen(environment)) {
8329 long_archi = environment;
8332 /* servername may be empty */
8333 if (servername && strlen(servername)) {
8334 pservername = canon_servername(servername);
8336 if (!is_myname_or_ipaddr(pservername)) {
8337 return WERR_INVALID_PARAM;
8341 if (!(short_archi = get_short_archi(long_archi))) {
8342 return WERR_INVALID_ENVIRONMENT;
8345 switch (component) {
8346 case SPOOLSS_PRTPROCS_PATH:
8347 case SPOOLSS_DRIVER_PATH:
8349 *path = talloc_asprintf(mem_ctx,
8352 spoolss_paths[component].share,
8355 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8356 SPOOLSS_DEFAULT_SERVER_PATH,
8357 spoolss_paths[component].dir,
8362 return WERR_INVALID_PARAM;
8372 /****************************************************************************
8373 ****************************************************************************/
8375 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8376 const char *servername,
8377 const char *environment,
8378 struct spoolss_DriverDirectoryInfo1 *r)
8383 werr = compose_spoolss_server_path(mem_ctx,
8386 SPOOLSS_DRIVER_PATH,
8388 if (!W_ERROR_IS_OK(werr)) {
8392 DEBUG(4,("printer driver directory: [%s]\n", path));
8394 r->directory_name = path;
8399 /****************************************************************
8400 _spoolss_GetPrinterDriverDirectory
8401 ****************************************************************/
8403 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8404 struct spoolss_GetPrinterDriverDirectory *r)
8408 /* that's an [in out] buffer */
8410 if (!r->in.buffer && (r->in.offered != 0)) {
8411 return WERR_INVALID_PARAM;
8414 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8419 /* r->in.level is ignored */
8421 werror = getprinterdriverdir_level_1(p->mem_ctx,
8424 &r->out.info->info1);
8425 if (!W_ERROR_IS_OK(werror)) {
8426 TALLOC_FREE(r->out.info);
8430 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8431 r->out.info, r->in.level);
8432 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8434 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8437 /****************************************************************
8438 _spoolss_EnumPrinterData
8439 ****************************************************************/
8441 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8442 struct spoolss_EnumPrinterData *r)
8445 struct spoolss_EnumPrinterDataEx r2;
8447 struct spoolss_PrinterEnumValues *info, *val = NULL;
8450 r2.in.handle = r->in.handle;
8451 r2.in.key_name = "PrinterDriverData";
8453 r2.out.count = &count;
8454 r2.out.info = &info;
8455 r2.out.needed = &needed;
8457 result = _spoolss_EnumPrinterDataEx(p, &r2);
8458 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8459 r2.in.offered = needed;
8460 result = _spoolss_EnumPrinterDataEx(p, &r2);
8462 if (!W_ERROR_IS_OK(result)) {
8467 * The NT machine wants to know the biggest size of value and data
8469 * cf: MSDN EnumPrinterData remark section
8472 if (!r->in.value_offered && !r->in.data_offered) {
8473 uint32_t biggest_valuesize = 0;
8474 uint32_t biggest_datasize = 0;
8477 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8479 for (i=0; i<count; i++) {
8481 name_length = strlen(info[i].value_name);
8482 if (strlen(info[i].value_name) > biggest_valuesize) {
8483 biggest_valuesize = name_length;
8486 if (info[i].data_length > biggest_datasize) {
8487 biggest_datasize = info[i].data_length;
8490 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8494 /* the value is an UNICODE string but real_value_size is the length
8495 in bytes including the trailing 0 */
8497 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8498 *r->out.data_needed = biggest_datasize;
8500 DEBUG(6,("final values: [%d], [%d]\n",
8501 *r->out.value_needed, *r->out.data_needed));
8506 if (r->in.enum_index < count) {
8507 val = &info[r->in.enum_index];
8511 /* out_value should default to "" or else NT4 has
8512 problems unmarshalling the response */
8514 if (r->in.value_offered) {
8515 *r->out.value_needed = 1;
8516 r->out.value_name = talloc_strdup(r, "");
8517 if (!r->out.value_name) {
8521 r->out.value_name = NULL;
8522 *r->out.value_needed = 0;
8525 /* the data is counted in bytes */
8527 *r->out.data_needed = r->in.data_offered;
8529 result = WERR_NO_MORE_ITEMS;
8533 * - counted in bytes in the request
8534 * - counted in UNICODE chars in the max reply
8535 * - counted in bytes in the real size
8537 * take a pause *before* coding not *during* coding
8541 if (r->in.value_offered) {
8542 r->out.value_name = talloc_strdup(r, val->value_name);
8543 if (!r->out.value_name) {
8546 *r->out.value_needed = val->value_name_len;
8548 r->out.value_name = NULL;
8549 *r->out.value_needed = 0;
8554 *r->out.type = val->type;
8556 /* data - counted in bytes */
8559 * See the section "Dynamically Typed Query Parameters"
8563 if (r->out.data && val->data && val->data->data &&
8564 val->data_length && r->in.data_offered) {
8565 memcpy(r->out.data, val->data->data,
8566 MIN(val->data_length,r->in.data_offered));
8569 *r->out.data_needed = val->data_length;
8577 /****************************************************************
8578 _spoolss_SetPrinterData
8579 ****************************************************************/
8581 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8582 struct spoolss_SetPrinterData *r)
8584 struct spoolss_SetPrinterDataEx r2;
8586 r2.in.handle = r->in.handle;
8587 r2.in.key_name = "PrinterDriverData";
8588 r2.in.value_name = r->in.value_name;
8589 r2.in.type = r->in.type;
8590 r2.in.data = r->in.data;
8591 r2.in.offered = r->in.offered;
8593 return _spoolss_SetPrinterDataEx(p, &r2);
8596 /****************************************************************
8597 _spoolss_ResetPrinter
8598 ****************************************************************/
8600 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8601 struct spoolss_ResetPrinter *r)
8603 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8606 DEBUG(5,("_spoolss_ResetPrinter\n"));
8609 * All we do is to check to see if the handle and queue is valid.
8610 * This call really doesn't mean anything to us because we only
8611 * support RAW printing. --jerry
8615 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8616 OUR_HANDLE(r->in.handle)));
8620 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8624 /* blindly return success */
8628 /****************************************************************
8629 _spoolss_DeletePrinterData
8630 ****************************************************************/
8632 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8633 struct spoolss_DeletePrinterData *r)
8635 struct spoolss_DeletePrinterDataEx r2;
8637 r2.in.handle = r->in.handle;
8638 r2.in.key_name = "PrinterDriverData";
8639 r2.in.value_name = r->in.value_name;
8641 return _spoolss_DeletePrinterDataEx(p, &r2);
8644 /****************************************************************
8646 ****************************************************************/
8648 WERROR _spoolss_AddForm(struct pipes_struct *p,
8649 struct spoolss_AddForm *r)
8651 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8653 WERROR status = WERR_OK;
8654 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8655 struct dcerpc_binding_handle *b;
8656 TALLOC_CTX *tmp_ctx = NULL;
8658 DEBUG(5,("_spoolss_AddForm\n"));
8661 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8662 OUR_HANDLE(r->in.handle)));
8666 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8667 and not a printer admin, then fail */
8669 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8670 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8671 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8672 p->session_info->info->domain_name,
8674 p->session_info->security_token,
8675 lp_printer_admin(snum))) {
8676 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8677 return WERR_ACCESS_DENIED;
8680 switch (form->flags) {
8681 case SPOOLSS_FORM_USER:
8682 case SPOOLSS_FORM_BUILTIN:
8683 case SPOOLSS_FORM_PRINTER:
8686 return WERR_INVALID_PARAM;
8689 tmp_ctx = talloc_new(p->mem_ctx);
8694 status = winreg_printer_binding_handle(tmp_ctx,
8695 get_session_info_system(),
8698 if (!W_ERROR_IS_OK(status)) {
8702 status = winreg_printer_addform1(tmp_ctx, b, form);
8703 if (!W_ERROR_IS_OK(status)) {
8708 * ChangeID must always be set if this is a printer
8710 if (Printer->printer_type == SPLHND_PRINTER) {
8711 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8712 status = WERR_BADFID;
8716 status = winreg_printer_update_changeid(tmp_ctx, b,
8717 lp_const_servicename(snum));
8721 talloc_free(tmp_ctx);
8725 /****************************************************************
8727 ****************************************************************/
8729 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8730 struct spoolss_DeleteForm *r)
8732 const char *form_name = r->in.form_name;
8733 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8735 WERROR status = WERR_OK;
8736 struct dcerpc_binding_handle *b;
8737 TALLOC_CTX *tmp_ctx = NULL;
8739 DEBUG(5,("_spoolss_DeleteForm\n"));
8742 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8743 OUR_HANDLE(r->in.handle)));
8747 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8748 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8749 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8750 p->session_info->info->domain_name,
8752 p->session_info->security_token,
8753 lp_printer_admin(snum))) {
8754 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8755 return WERR_ACCESS_DENIED;
8758 tmp_ctx = talloc_new(p->mem_ctx);
8763 status = winreg_printer_binding_handle(tmp_ctx,
8764 get_session_info_system(),
8767 if (!W_ERROR_IS_OK(status)) {
8771 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8772 if (!W_ERROR_IS_OK(status)) {
8777 * ChangeID must always be set if this is a printer
8779 if (Printer->printer_type == SPLHND_PRINTER) {
8780 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8781 status = WERR_BADFID;
8785 status = winreg_printer_update_changeid(tmp_ctx, b,
8786 lp_const_servicename(snum));
8790 talloc_free(tmp_ctx);
8794 /****************************************************************
8796 ****************************************************************/
8798 WERROR _spoolss_SetForm(struct pipes_struct *p,
8799 struct spoolss_SetForm *r)
8801 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8802 const char *form_name = r->in.form_name;
8804 WERROR status = WERR_OK;
8805 struct dcerpc_binding_handle *b;
8806 TALLOC_CTX *tmp_ctx = NULL;
8808 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8810 DEBUG(5,("_spoolss_SetForm\n"));
8813 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8814 OUR_HANDLE(r->in.handle)));
8818 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8819 and not a printer admin, then fail */
8821 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8822 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8823 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8824 p->session_info->info->domain_name,
8826 p->session_info->security_token,
8827 lp_printer_admin(snum))) {
8828 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8829 return WERR_ACCESS_DENIED;
8832 tmp_ctx = talloc_new(p->mem_ctx);
8837 status = winreg_printer_binding_handle(tmp_ctx,
8838 get_session_info_system(),
8841 if (!W_ERROR_IS_OK(status)) {
8845 status = winreg_printer_setform1(tmp_ctx, b,
8848 if (!W_ERROR_IS_OK(status)) {
8853 * ChangeID must always be set if this is a printer
8855 if (Printer->printer_type == SPLHND_PRINTER) {
8856 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8857 status = WERR_BADFID;
8861 status = winreg_printer_update_changeid(tmp_ctx, b,
8862 lp_const_servicename(snum));
8866 talloc_free(tmp_ctx);
8870 /****************************************************************************
8871 fill_print_processor1
8872 ****************************************************************************/
8874 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8875 struct spoolss_PrintProcessorInfo1 *r,
8876 const char *print_processor_name)
8878 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8879 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8884 /****************************************************************************
8885 enumprintprocessors level 1.
8886 ****************************************************************************/
8888 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8889 union spoolss_PrintProcessorInfo **info_p,
8892 union spoolss_PrintProcessorInfo *info;
8895 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8896 W_ERROR_HAVE_NO_MEMORY(info);
8900 result = fill_print_processor1(info, &info[0].info1, "winprint");
8901 if (!W_ERROR_IS_OK(result)) {
8906 if (!W_ERROR_IS_OK(result)) {
8917 /****************************************************************
8918 _spoolss_EnumPrintProcessors
8919 ****************************************************************/
8921 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8922 struct spoolss_EnumPrintProcessors *r)
8926 /* that's an [in out] buffer */
8928 if (!r->in.buffer && (r->in.offered != 0)) {
8929 return WERR_INVALID_PARAM;
8932 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8935 * Enumerate the print processors ...
8937 * Just reply with "winprint", to keep NT happy
8938 * and I can use my nice printer checker.
8943 *r->out.info = NULL;
8945 if (!get_short_archi(r->in.environment)) {
8946 return WERR_INVALID_ENVIRONMENT;
8949 switch (r->in.level) {
8951 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8955 return WERR_UNKNOWN_LEVEL;
8958 if (!W_ERROR_IS_OK(result)) {
8962 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8963 spoolss_EnumPrintProcessors,
8964 *r->out.info, r->in.level,
8966 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8967 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8969 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8972 /****************************************************************************
8973 fill_printprocdatatype1
8974 ****************************************************************************/
8976 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8977 struct spoolss_PrintProcDataTypesInfo1 *r,
8978 const char *name_array)
8980 r->name_array = talloc_strdup(mem_ctx, name_array);
8981 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8986 /****************************************************************************
8987 enumprintprocdatatypes level 1.
8988 ****************************************************************************/
8990 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8991 union spoolss_PrintProcDataTypesInfo **info_p,
8995 union spoolss_PrintProcDataTypesInfo *info;
8997 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8998 W_ERROR_HAVE_NO_MEMORY(info);
9002 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9003 if (!W_ERROR_IS_OK(result)) {
9008 if (!W_ERROR_IS_OK(result)) {
9019 /****************************************************************
9020 _spoolss_EnumPrintProcDataTypes
9021 ****************************************************************/
9023 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9024 struct spoolss_EnumPrintProcDataTypes *r)
9028 /* that's an [in out] buffer */
9030 if (!r->in.buffer && (r->in.offered != 0)) {
9031 return WERR_INVALID_PARAM;
9034 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9038 *r->out.info = NULL;
9040 if (r->in.print_processor_name == NULL ||
9041 !strequal(r->in.print_processor_name, "winprint")) {
9042 return WERR_UNKNOWN_PRINTPROCESSOR;
9045 switch (r->in.level) {
9047 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9051 return WERR_UNKNOWN_LEVEL;
9054 if (!W_ERROR_IS_OK(result)) {
9058 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9059 spoolss_EnumPrintProcDataTypes,
9060 *r->out.info, r->in.level,
9062 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9063 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9065 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9068 /****************************************************************************
9070 ****************************************************************************/
9072 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9073 struct spoolss_MonitorInfo1 *r,
9074 const char *monitor_name)
9076 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9077 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9082 /****************************************************************************
9084 ****************************************************************************/
9086 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9087 struct spoolss_MonitorInfo2 *r,
9088 const char *monitor_name,
9089 const char *environment,
9090 const char *dll_name)
9092 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9093 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9094 r->environment = talloc_strdup(mem_ctx, environment);
9095 W_ERROR_HAVE_NO_MEMORY(r->environment);
9096 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9097 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9102 /****************************************************************************
9103 enumprintmonitors level 1.
9104 ****************************************************************************/
9106 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9107 union spoolss_MonitorInfo **info_p,
9110 union spoolss_MonitorInfo *info;
9111 WERROR result = WERR_OK;
9113 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9114 W_ERROR_HAVE_NO_MEMORY(info);
9118 result = fill_monitor_1(info, &info[0].info1,
9120 if (!W_ERROR_IS_OK(result)) {
9124 result = fill_monitor_1(info, &info[1].info1,
9126 if (!W_ERROR_IS_OK(result)) {
9131 if (!W_ERROR_IS_OK(result)) {
9142 /****************************************************************************
9143 enumprintmonitors level 2.
9144 ****************************************************************************/
9146 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9147 union spoolss_MonitorInfo **info_p,
9150 union spoolss_MonitorInfo *info;
9151 WERROR result = WERR_OK;
9153 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9154 W_ERROR_HAVE_NO_MEMORY(info);
9158 result = fill_monitor_2(info, &info[0].info2,
9160 "Windows NT X86", /* FIXME */
9162 if (!W_ERROR_IS_OK(result)) {
9166 result = fill_monitor_2(info, &info[1].info2,
9168 "Windows NT X86", /* FIXME */
9170 if (!W_ERROR_IS_OK(result)) {
9175 if (!W_ERROR_IS_OK(result)) {
9186 /****************************************************************
9187 _spoolss_EnumMonitors
9188 ****************************************************************/
9190 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9191 struct spoolss_EnumMonitors *r)
9195 /* that's an [in out] buffer */
9197 if (!r->in.buffer && (r->in.offered != 0)) {
9198 return WERR_INVALID_PARAM;
9201 DEBUG(5,("_spoolss_EnumMonitors\n"));
9204 * Enumerate the print monitors ...
9206 * Just reply with "Local Port", to keep NT happy
9207 * and I can use my nice printer checker.
9212 *r->out.info = NULL;
9214 switch (r->in.level) {
9216 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9220 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9224 return WERR_UNKNOWN_LEVEL;
9227 if (!W_ERROR_IS_OK(result)) {
9231 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9232 spoolss_EnumMonitors,
9233 *r->out.info, r->in.level,
9235 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9236 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9238 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9241 /****************************************************************************
9242 ****************************************************************************/
9244 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9245 const print_queue_struct *queue,
9246 int count, int snum,
9247 struct spoolss_PrinterInfo2 *pinfo2,
9249 struct spoolss_JobInfo1 *r)
9254 for (i=0; i<count; i++) {
9255 if (queue[i].job == (int)jobid) {
9261 if (found == false) {
9262 /* NT treats not found as bad param... yet another bad choice */
9263 return WERR_INVALID_PARAM;
9266 return fill_job_info1(mem_ctx,
9274 /****************************************************************************
9275 ****************************************************************************/
9277 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9278 const print_queue_struct *queue,
9279 int count, int snum,
9280 struct spoolss_PrinterInfo2 *pinfo2,
9282 struct spoolss_JobInfo2 *r)
9286 struct spoolss_DeviceMode *devmode;
9289 for (i=0; i<count; i++) {
9290 if (queue[i].job == (int)jobid) {
9296 if (found == false) {
9297 /* NT treats not found as bad param... yet another bad
9299 return WERR_INVALID_PARAM;
9303 * if the print job does not have a DEVMODE associated with it,
9304 * just use the one for the printer. A NULL devicemode is not
9305 * a failure condition
9308 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9310 result = spoolss_create_default_devmode(mem_ctx,
9311 pinfo2->printername,
9313 if (!W_ERROR_IS_OK(result)) {
9314 DEBUG(3, ("Can't proceed w/o a devmode!"));
9319 return fill_job_info2(mem_ctx,
9328 /****************************************************************
9330 ****************************************************************/
9332 WERROR _spoolss_GetJob(struct pipes_struct *p,
9333 struct spoolss_GetJob *r)
9335 WERROR result = WERR_OK;
9336 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9339 print_queue_struct *queue = NULL;
9340 print_status_struct prt_status;
9342 /* that's an [in out] buffer */
9344 if (!r->in.buffer && (r->in.offered != 0)) {
9345 return WERR_INVALID_PARAM;
9348 DEBUG(5,("_spoolss_GetJob\n"));
9352 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9356 result = winreg_get_printer_internal(p->mem_ctx,
9357 get_session_info_system(),
9359 lp_const_servicename(snum),
9361 if (!W_ERROR_IS_OK(result)) {
9365 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9367 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9368 count, prt_status.status, prt_status.message));
9370 switch (r->in.level) {
9372 result = getjob_level_1(p->mem_ctx,
9373 queue, count, snum, pinfo2,
9374 r->in.job_id, &r->out.info->info1);
9377 result = getjob_level_2(p->mem_ctx,
9378 queue, count, snum, pinfo2,
9379 r->in.job_id, &r->out.info->info2);
9382 result = WERR_UNKNOWN_LEVEL;
9387 TALLOC_FREE(pinfo2);
9389 if (!W_ERROR_IS_OK(result)) {
9390 TALLOC_FREE(r->out.info);
9394 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9396 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9398 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9401 /****************************************************************
9402 _spoolss_GetPrinterDataEx
9403 ****************************************************************/
9405 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9406 struct spoolss_GetPrinterDataEx *r)
9409 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9410 const char *printer;
9412 WERROR result = WERR_OK;
9414 enum winreg_Type val_type = REG_NONE;
9415 uint8_t *val_data = NULL;
9416 uint32_t val_size = 0;
9417 struct dcerpc_binding_handle *b;
9418 TALLOC_CTX *tmp_ctx;
9420 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9422 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9423 r->in.key_name, r->in.value_name));
9425 /* in case of problem, return some default values */
9428 *r->out.type = REG_NONE;
9430 tmp_ctx = talloc_new(p->mem_ctx);
9436 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9437 OUR_HANDLE(r->in.handle)));
9438 result = WERR_BADFID;
9442 /* check to see if the keyname is valid */
9443 if (!strlen(r->in.key_name)) {
9444 result = WERR_INVALID_PARAM;
9448 /* Is the handle to a printer or to the server? */
9450 if (Printer->printer_type == SPLHND_SERVER) {
9452 union spoolss_PrinterData data;
9454 result = getprinterdata_printer_server(tmp_ctx,
9458 if (!W_ERROR_IS_OK(result)) {
9462 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9463 *r->out.type, &data);
9464 if (!W_ERROR_IS_OK(result)) {
9468 *r->out.needed = blob.length;
9470 if (r->in.offered >= *r->out.needed) {
9471 memcpy(r->out.data, blob.data, blob.length);
9478 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9479 result = WERR_BADFID;
9482 printer = lp_const_servicename(snum);
9484 result = winreg_printer_binding_handle(tmp_ctx,
9485 get_session_info_system(),
9488 if (!W_ERROR_IS_OK(result)) {
9492 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9493 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9494 strequal(r->in.value_name, "ChangeId")) {
9495 *r->out.type = REG_DWORD;
9497 if (r->in.offered >= *r->out.needed) {
9498 uint32_t changeid = 0;
9500 result = winreg_printer_get_changeid(tmp_ctx, b,
9503 if (!W_ERROR_IS_OK(result)) {
9507 SIVAL(r->out.data, 0, changeid);
9513 result = winreg_get_printer_dataex(tmp_ctx, b,
9520 if (!W_ERROR_IS_OK(result)) {
9524 *r->out.needed = val_size;
9525 *r->out.type = val_type;
9527 if (r->in.offered >= *r->out.needed) {
9528 memcpy(r->out.data, val_data, val_size);
9532 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9534 if (W_ERROR_IS_OK(result)) {
9535 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9538 talloc_free(tmp_ctx);
9542 /****************************************************************
9543 _spoolss_SetPrinterDataEx
9544 ****************************************************************/
9546 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9547 struct spoolss_SetPrinterDataEx *r)
9549 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9551 WERROR result = WERR_OK;
9552 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9554 struct dcerpc_binding_handle *b;
9555 TALLOC_CTX *tmp_ctx;
9557 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9559 /* From MSDN documentation of SetPrinterDataEx: pass request to
9560 SetPrinterData if key is "PrinterDriverData" */
9563 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9564 OUR_HANDLE(r->in.handle)));
9568 if (Printer->printer_type == SPLHND_SERVER) {
9569 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9570 "Not implemented for server handles yet\n"));
9571 return WERR_INVALID_PARAM;
9574 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9579 * Access check : NT returns "access denied" if you make a
9580 * SetPrinterData call without the necessary privildge.
9581 * we were originally returning OK if nothing changed
9582 * which made Win2k issue **a lot** of SetPrinterData
9583 * when connecting to a printer --jerry
9586 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9587 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9588 "change denied by handle access permissions\n"));
9589 return WERR_ACCESS_DENIED;
9592 tmp_ctx = talloc_new(p->mem_ctx);
9597 result = winreg_printer_binding_handle(tmp_ctx,
9598 get_session_info_system(),
9601 if (!W_ERROR_IS_OK(result)) {
9605 result = winreg_get_printer(tmp_ctx, b,
9606 lp_servicename(snum),
9608 if (!W_ERROR_IS_OK(result)) {
9612 /* check for OID in valuename */
9614 oid_string = strchr(r->in.value_name, ',');
9620 /* save the registry data */
9622 result = winreg_set_printer_dataex(tmp_ctx, b,
9630 if (W_ERROR_IS_OK(result)) {
9631 /* save the OID if one was specified */
9633 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9634 r->in.key_name, SPOOL_OID_KEY);
9636 result = WERR_NOMEM;
9641 * I'm not checking the status here on purpose. Don't know
9642 * if this is right, but I'm returning the status from the
9643 * previous set_printer_dataex() call. I have no idea if
9644 * this is right. --jerry
9646 winreg_set_printer_dataex(tmp_ctx, b,
9651 (uint8_t *) oid_string,
9652 strlen(oid_string) + 1);
9655 result = winreg_printer_update_changeid(tmp_ctx, b,
9656 lp_const_servicename(snum));
9661 talloc_free(tmp_ctx);
9665 /****************************************************************
9666 _spoolss_DeletePrinterDataEx
9667 ****************************************************************/
9669 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9670 struct spoolss_DeletePrinterDataEx *r)
9672 const char *printer;
9674 WERROR status = WERR_OK;
9675 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9677 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9680 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9681 "Invalid handle (%s:%u:%u).\n",
9682 OUR_HANDLE(r->in.handle)));
9686 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9687 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9688 "printer properties change denied by handle\n"));
9689 return WERR_ACCESS_DENIED;
9692 if (!r->in.value_name || !r->in.key_name) {
9696 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9699 printer = lp_const_servicename(snum);
9701 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9702 get_session_info_system(),
9707 if (W_ERROR_IS_OK(status)) {
9708 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9709 get_session_info_system(),
9717 /****************************************************************
9718 _spoolss_EnumPrinterKey
9719 ****************************************************************/
9721 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9722 struct spoolss_EnumPrinterKey *r)
9725 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9727 WERROR result = WERR_BADFILE;
9728 const char **array = NULL;
9731 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9734 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9735 OUR_HANDLE(r->in.handle)));
9739 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9743 result = winreg_enum_printer_key_internal(p->mem_ctx,
9744 get_session_info_system(),
9746 lp_const_servicename(snum),
9750 if (!W_ERROR_IS_OK(result)) {
9754 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9755 result = WERR_NOMEM;
9759 *r->out._ndr_size = r->in.offered / 2;
9760 *r->out.needed = blob.length;
9762 if (r->in.offered < *r->out.needed) {
9763 result = WERR_MORE_DATA;
9766 r->out.key_buffer->string_array = array;
9770 if (!W_ERROR_IS_OK(result)) {
9772 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9780 /****************************************************************
9781 _spoolss_DeletePrinterKey
9782 ****************************************************************/
9784 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9785 struct spoolss_DeletePrinterKey *r)
9787 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9790 const char *printer;
9791 struct dcerpc_binding_handle *b;
9792 TALLOC_CTX *tmp_ctx;
9794 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9797 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9798 OUR_HANDLE(r->in.handle)));
9802 /* if keyname == NULL, return error */
9803 if ( !r->in.key_name )
9804 return WERR_INVALID_PARAM;
9806 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9810 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9811 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9812 "printer properties change denied by handle\n"));
9813 return WERR_ACCESS_DENIED;
9816 printer = lp_const_servicename(snum);
9818 tmp_ctx = talloc_new(p->mem_ctx);
9823 status = winreg_printer_binding_handle(tmp_ctx,
9824 get_session_info_system(),
9827 if (!W_ERROR_IS_OK(status)) {
9831 /* delete the key and all subkeys */
9832 status = winreg_delete_printer_key(tmp_ctx, b,
9835 if (W_ERROR_IS_OK(status)) {
9836 status = winreg_printer_update_changeid(tmp_ctx, b,
9841 talloc_free(tmp_ctx);
9845 /****************************************************************
9846 _spoolss_EnumPrinterDataEx
9847 ****************************************************************/
9849 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9850 struct spoolss_EnumPrinterDataEx *r)
9853 struct spoolss_PrinterEnumValues *info = NULL;
9854 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9858 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9862 *r->out.info = NULL;
9865 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9866 OUR_HANDLE(r->in.handle)));
9871 * first check for a keyname of NULL or "". Win2k seems to send
9872 * this a lot and we should send back WERR_INVALID_PARAM
9873 * no need to spend time looking up the printer in this case.
9877 if (!strlen(r->in.key_name)) {
9878 result = WERR_INVALID_PARAM;
9882 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9886 /* now look for a match on the key name */
9887 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9888 get_session_info_system(),
9890 lp_const_servicename(snum),
9894 if (!W_ERROR_IS_OK(result)) {
9898 #if 0 /* FIXME - gd */
9899 /* housekeeping information in the reply */
9901 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9902 * the hand marshalled container size is a multiple
9903 * of 4 bytes for RPC alignment.
9907 needed += 4-(needed % 4);
9910 *r->out.count = count;
9911 *r->out.info = info;
9914 if (!W_ERROR_IS_OK(result)) {
9918 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9919 spoolss_EnumPrinterDataEx,
9922 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9923 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9925 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9928 /****************************************************************************
9929 ****************************************************************************/
9931 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9932 const char *servername,
9933 const char *environment,
9934 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9939 werr = compose_spoolss_server_path(mem_ctx,
9942 SPOOLSS_PRTPROCS_PATH,
9944 if (!W_ERROR_IS_OK(werr)) {
9948 DEBUG(4,("print processor directory: [%s]\n", path));
9950 r->directory_name = path;
9955 /****************************************************************
9956 _spoolss_GetPrintProcessorDirectory
9957 ****************************************************************/
9959 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9960 struct spoolss_GetPrintProcessorDirectory *r)
9963 char *prnproc_share = NULL;
9964 bool prnproc_share_exists = false;
9967 /* that's an [in out] buffer */
9969 if (!r->in.buffer && (r->in.offered != 0)) {
9970 return WERR_INVALID_PARAM;
9973 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9978 /* r->in.level is ignored */
9980 /* We always should reply with a local print processor directory so that
9981 * users are not forced to have a [prnproc$] share on the Samba spoolss
9982 * server, if users decide to do so, lets announce it though - Guenther */
9984 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9985 if (!prnproc_share) {
9989 prnproc_share_exists = true;
9992 result = getprintprocessordirectory_level_1(p->mem_ctx,
9993 prnproc_share_exists ? r->in.server : NULL,
9995 &r->out.info->info1);
9996 if (!W_ERROR_IS_OK(result)) {
9997 TALLOC_FREE(r->out.info);
10001 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
10002 r->out.info, r->in.level);
10003 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10005 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10008 /*******************************************************************
10009 ********************************************************************/
10011 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10012 const char *dllname)
10014 enum ndr_err_code ndr_err;
10015 struct spoolss_MonitorUi ui;
10017 ui.dll_name = dllname;
10019 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10020 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10021 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10022 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10024 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10027 /*******************************************************************
10028 Streams the monitor UI DLL name in UNICODE
10029 *******************************************************************/
10031 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10032 struct security_token *token, DATA_BLOB *in,
10033 DATA_BLOB *out, uint32_t *needed)
10035 const char *dllname = "tcpmonui.dll";
10037 *needed = (strlen(dllname)+1) * 2;
10039 if (out->length < *needed) {
10040 return WERR_INSUFFICIENT_BUFFER;
10043 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10050 /*******************************************************************
10051 ********************************************************************/
10053 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10054 struct spoolss_PortData1 *port1,
10055 const DATA_BLOB *buf)
10057 enum ndr_err_code ndr_err;
10058 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10059 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10060 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10061 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10063 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10066 /*******************************************************************
10067 ********************************************************************/
10069 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10070 struct spoolss_PortData2 *port2,
10071 const DATA_BLOB *buf)
10073 enum ndr_err_code ndr_err;
10074 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10075 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10076 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10077 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10079 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10082 /*******************************************************************
10083 Create a new TCP/IP port
10084 *******************************************************************/
10086 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10087 struct security_token *token, DATA_BLOB *in,
10088 DATA_BLOB *out, uint32_t *needed)
10090 struct spoolss_PortData1 port1;
10091 struct spoolss_PortData2 port2;
10092 char *device_uri = NULL;
10095 const char *portname;
10096 const char *hostaddress;
10098 uint32_t port_number;
10101 /* peek for spoolss_PortData version */
10103 if (!in || (in->length < (128 + 4))) {
10104 return WERR_GENERAL_FAILURE;
10107 version = IVAL(in->data, 128);
10111 ZERO_STRUCT(port1);
10113 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10117 portname = port1.portname;
10118 hostaddress = port1.hostaddress;
10119 queue = port1.queue;
10120 protocol = port1.protocol;
10121 port_number = port1.port_number;
10125 ZERO_STRUCT(port2);
10127 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10131 portname = port2.portname;
10132 hostaddress = port2.hostaddress;
10133 queue = port2.queue;
10134 protocol = port2.protocol;
10135 port_number = port2.port_number;
10139 DEBUG(1,("xcvtcp_addport: "
10140 "unknown version of port_data: %d\n", version));
10141 return WERR_UNKNOWN_PORT;
10144 /* create the device URI and call the add_port_hook() */
10146 switch (protocol) {
10147 case PROTOCOL_RAWTCP_TYPE:
10148 device_uri = talloc_asprintf(mem_ctx,
10149 "socket://%s:%d/", hostaddress,
10153 case PROTOCOL_LPR_TYPE:
10154 device_uri = talloc_asprintf(mem_ctx,
10155 "lpr://%s/%s", hostaddress, queue );
10159 return WERR_UNKNOWN_PORT;
10166 return add_port_hook(mem_ctx, token, portname, device_uri);
10169 /*******************************************************************
10170 *******************************************************************/
10172 struct xcv_api_table xcvtcp_cmds[] = {
10173 { "MonitorUI", xcvtcp_monitorui },
10174 { "AddPort", xcvtcp_addport},
10178 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10179 struct security_token *token, const char *command,
10186 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10188 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10189 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10190 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10193 return WERR_BADFUNC;
10196 /*******************************************************************
10197 *******************************************************************/
10198 #if 0 /* don't support management using the "Local Port" monitor */
10200 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10201 struct security_token *token, DATA_BLOB *in,
10202 DATA_BLOB *out, uint32_t *needed)
10204 const char *dllname = "localui.dll";
10206 *needed = (strlen(dllname)+1) * 2;
10208 if (out->length < *needed) {
10209 return WERR_INSUFFICIENT_BUFFER;
10212 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10219 /*******************************************************************
10220 *******************************************************************/
10222 struct xcv_api_table xcvlocal_cmds[] = {
10223 { "MonitorUI", xcvlocal_monitorui },
10227 struct xcv_api_table xcvlocal_cmds[] = {
10234 /*******************************************************************
10235 *******************************************************************/
10237 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10238 struct security_token *token, const char *command,
10239 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10244 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10246 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10247 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10248 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10250 return WERR_BADFUNC;
10253 /****************************************************************
10255 ****************************************************************/
10257 WERROR _spoolss_XcvData(struct pipes_struct *p,
10258 struct spoolss_XcvData *r)
10260 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10261 DATA_BLOB out_data = data_blob_null;
10265 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10266 OUR_HANDLE(r->in.handle)));
10267 return WERR_BADFID;
10270 /* Has to be a handle to the TCP/IP port monitor */
10272 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10273 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10274 return WERR_BADFID;
10277 /* requires administrative access to the server */
10279 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10280 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10281 return WERR_ACCESS_DENIED;
10284 /* Allocate the outgoing buffer */
10286 if (r->in.out_data_size) {
10287 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10288 if (out_data.data == NULL) {
10293 switch ( Printer->printer_type ) {
10294 case SPLHND_PORTMON_TCP:
10295 werror = process_xcvtcp_command(p->mem_ctx,
10296 p->session_info->security_token,
10297 r->in.function_name,
10298 &r->in.in_data, &out_data,
10301 case SPLHND_PORTMON_LOCAL:
10302 werror = process_xcvlocal_command(p->mem_ctx,
10303 p->session_info->security_token,
10304 r->in.function_name,
10305 &r->in.in_data, &out_data,
10309 werror = WERR_INVALID_PRINT_MONITOR;
10312 if (!W_ERROR_IS_OK(werror)) {
10316 *r->out.status_code = 0;
10318 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10319 memcpy(r->out.out_data, out_data.data,
10320 MIN(r->in.out_data_size, out_data.length));
10326 /****************************************************************
10327 _spoolss_AddPrintProcessor
10328 ****************************************************************/
10330 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10331 struct spoolss_AddPrintProcessor *r)
10333 /* for now, just indicate success and ignore the add. We'll
10334 automatically set the winprint processor for printer
10335 entries later. Used to debug the LexMark Optra S 1855 PCL
10341 /****************************************************************
10343 ****************************************************************/
10345 WERROR _spoolss_AddPort(struct pipes_struct *p,
10346 struct spoolss_AddPort *r)
10348 /* do what w2k3 does */
10350 return WERR_NOT_SUPPORTED;
10353 /****************************************************************
10354 _spoolss_GetPrinterDriver
10355 ****************************************************************/
10357 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10358 struct spoolss_GetPrinterDriver *r)
10360 p->rng_fault_state = true;
10361 return WERR_NOT_SUPPORTED;
10364 /****************************************************************
10365 _spoolss_ReadPrinter
10366 ****************************************************************/
10368 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10369 struct spoolss_ReadPrinter *r)
10371 p->rng_fault_state = true;
10372 return WERR_NOT_SUPPORTED;
10375 /****************************************************************
10376 _spoolss_WaitForPrinterChange
10377 ****************************************************************/
10379 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10380 struct spoolss_WaitForPrinterChange *r)
10382 p->rng_fault_state = true;
10383 return WERR_NOT_SUPPORTED;
10386 /****************************************************************
10387 _spoolss_ConfigurePort
10388 ****************************************************************/
10390 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10391 struct spoolss_ConfigurePort *r)
10393 p->rng_fault_state = true;
10394 return WERR_NOT_SUPPORTED;
10397 /****************************************************************
10398 _spoolss_DeletePort
10399 ****************************************************************/
10401 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10402 struct spoolss_DeletePort *r)
10404 p->rng_fault_state = true;
10405 return WERR_NOT_SUPPORTED;
10408 /****************************************************************
10409 _spoolss_CreatePrinterIC
10410 ****************************************************************/
10412 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10413 struct spoolss_CreatePrinterIC *r)
10415 p->rng_fault_state = true;
10416 return WERR_NOT_SUPPORTED;
10419 /****************************************************************
10420 _spoolss_PlayGDIScriptOnPrinterIC
10421 ****************************************************************/
10423 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10424 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10426 p->rng_fault_state = true;
10427 return WERR_NOT_SUPPORTED;
10430 /****************************************************************
10431 _spoolss_DeletePrinterIC
10432 ****************************************************************/
10434 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10435 struct spoolss_DeletePrinterIC *r)
10437 p->rng_fault_state = true;
10438 return WERR_NOT_SUPPORTED;
10441 /****************************************************************
10442 _spoolss_AddPrinterConnection
10443 ****************************************************************/
10445 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10446 struct spoolss_AddPrinterConnection *r)
10448 p->rng_fault_state = true;
10449 return WERR_NOT_SUPPORTED;
10452 /****************************************************************
10453 _spoolss_DeletePrinterConnection
10454 ****************************************************************/
10456 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10457 struct spoolss_DeletePrinterConnection *r)
10459 p->rng_fault_state = true;
10460 return WERR_NOT_SUPPORTED;
10463 /****************************************************************
10464 _spoolss_PrinterMessageBox
10465 ****************************************************************/
10467 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10468 struct spoolss_PrinterMessageBox *r)
10470 p->rng_fault_state = true;
10471 return WERR_NOT_SUPPORTED;
10474 /****************************************************************
10475 _spoolss_AddMonitor
10476 ****************************************************************/
10478 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10479 struct spoolss_AddMonitor *r)
10481 p->rng_fault_state = true;
10482 return WERR_NOT_SUPPORTED;
10485 /****************************************************************
10486 _spoolss_DeleteMonitor
10487 ****************************************************************/
10489 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10490 struct spoolss_DeleteMonitor *r)
10492 p->rng_fault_state = true;
10493 return WERR_NOT_SUPPORTED;
10496 /****************************************************************
10497 _spoolss_DeletePrintProcessor
10498 ****************************************************************/
10500 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10501 struct spoolss_DeletePrintProcessor *r)
10503 p->rng_fault_state = true;
10504 return WERR_NOT_SUPPORTED;
10507 /****************************************************************
10508 _spoolss_AddPrintProvidor
10509 ****************************************************************/
10511 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10512 struct spoolss_AddPrintProvidor *r)
10514 p->rng_fault_state = true;
10515 return WERR_NOT_SUPPORTED;
10518 /****************************************************************
10519 _spoolss_DeletePrintProvidor
10520 ****************************************************************/
10522 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10523 struct spoolss_DeletePrintProvidor *r)
10525 p->rng_fault_state = true;
10526 return WERR_NOT_SUPPORTED;
10529 /****************************************************************
10530 _spoolss_FindFirstPrinterChangeNotification
10531 ****************************************************************/
10533 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10534 struct spoolss_FindFirstPrinterChangeNotification *r)
10536 p->rng_fault_state = true;
10537 return WERR_NOT_SUPPORTED;
10540 /****************************************************************
10541 _spoolss_FindNextPrinterChangeNotification
10542 ****************************************************************/
10544 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10545 struct spoolss_FindNextPrinterChangeNotification *r)
10547 p->rng_fault_state = true;
10548 return WERR_NOT_SUPPORTED;
10551 /****************************************************************
10552 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10553 ****************************************************************/
10555 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10556 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10558 p->rng_fault_state = true;
10559 return WERR_NOT_SUPPORTED;
10562 /****************************************************************
10563 _spoolss_ReplyOpenPrinter
10564 ****************************************************************/
10566 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10567 struct spoolss_ReplyOpenPrinter *r)
10569 p->rng_fault_state = true;
10570 return WERR_NOT_SUPPORTED;
10573 /****************************************************************
10574 _spoolss_RouterReplyPrinter
10575 ****************************************************************/
10577 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10578 struct spoolss_RouterReplyPrinter *r)
10580 p->rng_fault_state = true;
10581 return WERR_NOT_SUPPORTED;
10584 /****************************************************************
10585 _spoolss_ReplyClosePrinter
10586 ****************************************************************/
10588 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10589 struct spoolss_ReplyClosePrinter *r)
10591 p->rng_fault_state = true;
10592 return WERR_NOT_SUPPORTED;
10595 /****************************************************************
10597 ****************************************************************/
10599 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10600 struct spoolss_AddPortEx *r)
10602 p->rng_fault_state = true;
10603 return WERR_NOT_SUPPORTED;
10606 /****************************************************************
10607 _spoolss_RouterFindFirstPrinterChangeNotification
10608 ****************************************************************/
10610 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10611 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10613 p->rng_fault_state = true;
10614 return WERR_NOT_SUPPORTED;
10617 /****************************************************************
10618 _spoolss_SpoolerInit
10619 ****************************************************************/
10621 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10622 struct spoolss_SpoolerInit *r)
10624 p->rng_fault_state = true;
10625 return WERR_NOT_SUPPORTED;
10628 /****************************************************************
10629 _spoolss_ResetPrinterEx
10630 ****************************************************************/
10632 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10633 struct spoolss_ResetPrinterEx *r)
10635 p->rng_fault_state = true;
10636 return WERR_NOT_SUPPORTED;
10639 /****************************************************************
10640 _spoolss_RouterReplyPrinterEx
10641 ****************************************************************/
10643 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10644 struct spoolss_RouterReplyPrinterEx *r)
10646 p->rng_fault_state = true;
10647 return WERR_NOT_SUPPORTED;
10650 /****************************************************************
10652 ****************************************************************/
10654 WERROR _spoolss_44(struct pipes_struct *p,
10655 struct spoolss_44 *r)
10657 p->rng_fault_state = true;
10658 return WERR_NOT_SUPPORTED;
10661 /****************************************************************
10663 ****************************************************************/
10665 WERROR _spoolss_SetPort(struct pipes_struct *p,
10666 struct spoolss_SetPort *r)
10668 p->rng_fault_state = true;
10669 return WERR_NOT_SUPPORTED;
10672 /****************************************************************
10674 ****************************************************************/
10676 WERROR _spoolss_4a(struct pipes_struct *p,
10677 struct spoolss_4a *r)
10679 p->rng_fault_state = true;
10680 return WERR_NOT_SUPPORTED;
10683 /****************************************************************
10685 ****************************************************************/
10687 WERROR _spoolss_4b(struct pipes_struct *p,
10688 struct spoolss_4b *r)
10690 p->rng_fault_state = true;
10691 return WERR_NOT_SUPPORTED;
10694 /****************************************************************
10696 ****************************************************************/
10698 WERROR _spoolss_4c(struct pipes_struct *p,
10699 struct spoolss_4c *r)
10701 p->rng_fault_state = true;
10702 return WERR_NOT_SUPPORTED;
10705 /****************************************************************
10707 ****************************************************************/
10709 WERROR _spoolss_53(struct pipes_struct *p,
10710 struct spoolss_53 *r)
10712 p->rng_fault_state = true;
10713 return WERR_NOT_SUPPORTED;
10716 /****************************************************************
10717 _spoolss_AddPerMachineConnection
10718 ****************************************************************/
10720 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10721 struct spoolss_AddPerMachineConnection *r)
10723 p->rng_fault_state = true;
10724 return WERR_NOT_SUPPORTED;
10727 /****************************************************************
10728 _spoolss_DeletePerMachineConnection
10729 ****************************************************************/
10731 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10732 struct spoolss_DeletePerMachineConnection *r)
10734 p->rng_fault_state = true;
10735 return WERR_NOT_SUPPORTED;
10738 /****************************************************************
10739 _spoolss_EnumPerMachineConnections
10740 ****************************************************************/
10742 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10743 struct spoolss_EnumPerMachineConnections *r)
10745 p->rng_fault_state = true;
10746 return WERR_NOT_SUPPORTED;
10749 /****************************************************************
10751 ****************************************************************/
10753 WERROR _spoolss_5a(struct pipes_struct *p,
10754 struct spoolss_5a *r)
10756 p->rng_fault_state = true;
10757 return WERR_NOT_SUPPORTED;
10760 /****************************************************************
10762 ****************************************************************/
10764 WERROR _spoolss_5b(struct pipes_struct *p,
10765 struct spoolss_5b *r)
10767 p->rng_fault_state = true;
10768 return WERR_NOT_SUPPORTED;
10771 /****************************************************************
10773 ****************************************************************/
10775 WERROR _spoolss_5c(struct pipes_struct *p,
10776 struct spoolss_5c *r)
10778 p->rng_fault_state = true;
10779 return WERR_NOT_SUPPORTED;
10782 /****************************************************************
10784 ****************************************************************/
10786 WERROR _spoolss_5d(struct pipes_struct *p,
10787 struct spoolss_5d *r)
10789 p->rng_fault_state = true;
10790 return WERR_NOT_SUPPORTED;
10793 /****************************************************************
10795 ****************************************************************/
10797 WERROR _spoolss_5e(struct pipes_struct *p,
10798 struct spoolss_5e *r)
10800 p->rng_fault_state = true;
10801 return WERR_NOT_SUPPORTED;
10804 /****************************************************************
10806 ****************************************************************/
10808 WERROR _spoolss_5f(struct pipes_struct *p,
10809 struct spoolss_5f *r)
10811 p->rng_fault_state = true;
10812 return WERR_NOT_SUPPORTED;
10815 /****************************************************************
10817 ****************************************************************/
10819 WERROR _spoolss_60(struct pipes_struct *p,
10820 struct spoolss_60 *r)
10822 p->rng_fault_state = true;
10823 return WERR_NOT_SUPPORTED;
10826 /****************************************************************
10828 ****************************************************************/
10830 WERROR _spoolss_61(struct pipes_struct *p,
10831 struct spoolss_61 *r)
10833 p->rng_fault_state = true;
10834 return WERR_NOT_SUPPORTED;
10837 /****************************************************************
10839 ****************************************************************/
10841 WERROR _spoolss_62(struct pipes_struct *p,
10842 struct spoolss_62 *r)
10844 p->rng_fault_state = true;
10845 return WERR_NOT_SUPPORTED;
10848 /****************************************************************
10850 ****************************************************************/
10852 WERROR _spoolss_63(struct pipes_struct *p,
10853 struct spoolss_63 *r)
10855 p->rng_fault_state = true;
10856 return WERR_NOT_SUPPORTED;
10859 /****************************************************************
10861 ****************************************************************/
10863 WERROR _spoolss_64(struct pipes_struct *p,
10864 struct spoolss_64 *r)
10866 p->rng_fault_state = true;
10867 return WERR_NOT_SUPPORTED;
10870 /****************************************************************
10872 ****************************************************************/
10874 WERROR _spoolss_65(struct pipes_struct *p,
10875 struct spoolss_65 *r)
10877 p->rng_fault_state = true;
10878 return WERR_NOT_SUPPORTED;
10881 /****************************************************************
10882 _spoolss_GetCorePrinterDrivers
10883 ****************************************************************/
10885 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10886 struct spoolss_GetCorePrinterDrivers *r)
10888 p->rng_fault_state = true;
10889 return WERR_NOT_SUPPORTED;
10892 /****************************************************************
10894 ****************************************************************/
10896 WERROR _spoolss_67(struct pipes_struct *p,
10897 struct spoolss_67 *r)
10899 p->rng_fault_state = true;
10900 return WERR_NOT_SUPPORTED;
10903 /****************************************************************
10904 _spoolss_GetPrinterDriverPackagePath
10905 ****************************************************************/
10907 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10908 struct spoolss_GetPrinterDriverPackagePath *r)
10910 p->rng_fault_state = true;
10911 return WERR_NOT_SUPPORTED;
10914 /****************************************************************
10916 ****************************************************************/
10918 WERROR _spoolss_69(struct pipes_struct *p,
10919 struct spoolss_69 *r)
10921 p->rng_fault_state = true;
10922 return WERR_NOT_SUPPORTED;
10925 /****************************************************************
10927 ****************************************************************/
10929 WERROR _spoolss_6a(struct pipes_struct *p,
10930 struct spoolss_6a *r)
10932 p->rng_fault_state = true;
10933 return WERR_NOT_SUPPORTED;
10936 /****************************************************************
10938 ****************************************************************/
10940 WERROR _spoolss_6b(struct pipes_struct *p,
10941 struct spoolss_6b *r)
10943 p->rng_fault_state = true;
10944 return WERR_NOT_SUPPORTED;
10947 /****************************************************************
10949 ****************************************************************/
10951 WERROR _spoolss_6c(struct pipes_struct *p,
10952 struct spoolss_6c *r)
10954 p->rng_fault_state = true;
10955 return WERR_NOT_SUPPORTED;
10958 /****************************************************************
10960 ****************************************************************/
10962 WERROR _spoolss_6d(struct pipes_struct *p,
10963 struct spoolss_6d *r)
10965 p->rng_fault_state = true;
10966 return WERR_NOT_SUPPORTED;