2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
10 * Copyright (C) Guenther Deschner 2009-2010.
11 * Copyright (C) Andreas Schneider 2010.
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, see <http://www.gnu.org/licenses/>.
27 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
28 up, all the errors returned are DOS errors, not NT status codes. */
32 #include "nt_printing.h"
33 #include "srv_spoolss_util.h"
34 #include "../librpc/gen_ndr/srv_spoolss.h"
35 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
36 #include "rpc_client/init_spoolss.h"
37 #include "rpc_client/cli_pipe.h"
38 #include "../libcli/security/security.h"
39 #include "librpc/gen_ndr/ndr_security.h"
41 #include "include/printing.h"
43 #include "../librpc/gen_ndr/netlogon.h"
45 #include "printing/notify.h"
47 #include "../libcli/registry/util_reg.h"
48 #include "smbd/smbd.h"
49 #include "smbd/globals.h"
52 #include "rpc_server/spoolss/srv_spoolss_nt.h"
54 #include "libsmb/libsmb.h"
55 #include "printing/printer_list.h"
56 #include "../lib/tsocket/tsocket.h"
57 #include "rpc_client/cli_winreg_spoolss.h"
58 #include "../libcli/smb/smbXcli_base.h"
60 /* macros stolen from s4 spoolss server */
61 #define SPOOLSS_BUFFER_UNION(fn,info,level) \
62 ((info)?ndr_size_##fn(info, level, 0):0)
64 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,info,level,count) \
65 ((info)?ndr_size_##fn##_info(mem_ctx, level, count, info):0)
67 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,info,count) \
68 ((info)?ndr_size_##fn##_info(mem_ctx, count, info):0)
70 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
73 #define DBGC_CLASS DBGC_RPC_SRV
75 #ifndef MAX_OPEN_PRINTER_EXS
76 #define MAX_OPEN_PRINTER_EXS 50
79 struct notify_back_channel;
81 /* structure to store the printer handles */
82 /* and a reference to what it's pointing to */
83 /* and the notify info asked about */
84 /* that's the central struct */
85 struct printer_handle {
86 struct printer_handle *prev, *next;
87 bool document_started;
89 uint32 jobid; /* jobid in printing backend */
91 const char *servername;
94 uint32 access_granted;
100 struct spoolss_NotifyOption *option;
101 struct policy_handle cli_hnd;
102 struct notify_back_channel *cli_chan;
104 /* are we in a FindNextPrinterChangeNotify() call? */
106 struct messaging_context *msg_ctx;
113 /* devmode sent in the OpenPrinter() call */
114 struct spoolss_DeviceMode *devmode;
116 /* TODO cache the printer info2 structure */
117 struct spoolss_PrinterInfo2 *info2;
121 static struct printer_handle *printers_list;
123 struct printer_session_counter {
124 struct printer_session_counter *next;
125 struct printer_session_counter *prev;
131 static struct printer_session_counter *counter_list;
133 struct notify_back_channel {
134 struct notify_back_channel *prev, *next;
136 /* associated client */
137 struct sockaddr_storage client_address;
139 /* print notify back-channel pipe handle*/
140 struct rpc_pipe_client *cli_pipe;
141 uint32_t active_connections;
144 static struct notify_back_channel *back_channels;
146 /* Map generic permissions to printer object specific permissions */
148 const struct standard_mapping printer_std_mapping = {
155 /* Map generic permissions to print server object specific permissions */
157 const struct standard_mapping printserver_std_mapping = {
164 /* API table for Xcv Monitor functions */
166 struct xcv_api_table {
168 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
171 static void prune_printername_cache(void);
173 /********************************************************************
174 * Canonicalize servername.
175 ********************************************************************/
177 static const char *canon_servername(const char *servername)
179 const char *pservername = servername;
180 while (*pservername == '\\') {
186 /* translate between internal status numbers and NT status numbers */
187 static int nt_printj_status(int v)
193 return JOB_STATUS_PAUSED;
195 return JOB_STATUS_SPOOLING;
197 return JOB_STATUS_PRINTING;
199 return JOB_STATUS_ERROR;
201 return JOB_STATUS_DELETING;
203 return JOB_STATUS_OFFLINE;
205 return JOB_STATUS_PAPEROUT;
207 return JOB_STATUS_PRINTED;
209 return JOB_STATUS_DELETED;
211 return JOB_STATUS_BLOCKED_DEVQ;
212 case LPQ_USER_INTERVENTION:
213 return JOB_STATUS_USER_INTERVENTION;
218 static int nt_printq_status(int v)
222 return PRINTER_STATUS_PAUSED;
231 /***************************************************************************
232 Disconnect from the client
233 ****************************************************************************/
235 static void srv_spoolss_replycloseprinter(int snum,
236 struct printer_handle *prn_hnd)
242 * Tell the specific printing tdb we no longer want messages for this printer
243 * by deregistering our PID.
246 if (!print_notify_deregister_pid(snum)) {
247 DEBUG(0, ("Failed to register our pid for printer %s\n",
248 lp_const_servicename(snum)));
251 /* weird if the test succeeds !!! */
252 if (prn_hnd->notify.cli_chan == NULL ||
253 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
254 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
255 prn_hnd->notify.cli_chan->active_connections == 0) {
256 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
257 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
258 TALLOC_FREE(prn_hnd->notify.cli_chan);
262 status = dcerpc_spoolss_ReplyClosePrinter(
263 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
265 &prn_hnd->notify.cli_hnd,
267 if (!NT_STATUS_IS_OK(status)) {
268 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
270 result = ntstatus_to_werror(status);
271 } else if (!W_ERROR_IS_OK(result)) {
272 DEBUG(0, ("reply_close_printer failed [%s].\n",
273 win_errstr(result)));
276 /* if it's the last connection, deconnect the IPC$ share */
277 if (prn_hnd->notify.cli_chan->active_connections == 1) {
279 cli_shutdown(rpc_pipe_np_smb_conn(prn_hnd->notify.cli_chan->cli_pipe));
280 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
281 TALLOC_FREE(prn_hnd->notify.cli_chan);
283 if (prn_hnd->notify.msg_ctx != NULL) {
284 messaging_deregister(prn_hnd->notify.msg_ctx,
285 MSG_PRINTER_NOTIFY2, NULL);
289 if (prn_hnd->notify.cli_chan) {
290 prn_hnd->notify.cli_chan->active_connections--;
291 prn_hnd->notify.cli_chan = NULL;
295 /****************************************************************************
296 Functions to free a printer entry datastruct.
297 ****************************************************************************/
299 static int printer_entry_destructor(struct printer_handle *Printer)
301 if (Printer->notify.cli_chan != NULL &&
302 Printer->notify.cli_chan->active_connections > 0) {
305 switch(Printer->printer_type) {
307 srv_spoolss_replycloseprinter(snum, Printer);
311 snum = print_queue_snum(Printer->sharename);
313 srv_spoolss_replycloseprinter(snum, Printer);
321 Printer->notify.flags=0;
322 Printer->notify.options=0;
323 Printer->notify.localmachine[0]='\0';
324 Printer->notify.printerlocal=0;
325 TALLOC_FREE(Printer->notify.option);
326 TALLOC_FREE(Printer->devmode);
328 /* Remove from the internal list. */
329 DLIST_REMOVE(printers_list, Printer);
333 /****************************************************************************
334 find printer index by handle
335 ****************************************************************************/
337 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
338 struct policy_handle *hnd)
340 struct printer_handle *find_printer = NULL;
342 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
343 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
350 /****************************************************************************
351 Close printer index by handle.
352 ****************************************************************************/
354 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
356 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
359 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
364 close_policy_hnd(p, hnd);
369 /****************************************************************************
370 Delete a printer given a handle.
371 ****************************************************************************/
373 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
374 const char *sharename,
375 struct messaging_context *msg_ctx)
377 char *cmd = lp_deleteprinter_cmd();
378 char *command = NULL;
380 bool is_print_op = false;
382 /* can't fail if we don't try */
387 command = talloc_asprintf(ctx,
394 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
396 DEBUG(10,("Running [%s]\n", command));
398 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
403 if ( (ret = smbrun(command, NULL)) == 0 ) {
404 /* Tell everyone we updated smb.conf. */
405 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
411 /********** END SePrintOperatorPrivlege BLOCK **********/
413 DEBUGADD(10,("returned [%d]\n", ret));
415 TALLOC_FREE(command);
418 return WERR_BADFID; /* What to return here? */
423 /****************************************************************************
424 Delete a printer given a handle.
425 ****************************************************************************/
427 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
429 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
433 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
439 * It turns out that Windows allows delete printer on a handle
440 * opened by an admin user, then used on a pipe handle created
441 * by an anonymous user..... but they're working on security.... riiight !
445 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
446 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
447 return WERR_ACCESS_DENIED;
450 /* this does not need a become root since the access check has been
451 done on the handle already */
453 result = winreg_delete_printer_key_internal(p->mem_ctx,
454 get_session_info_system(),
458 if (!W_ERROR_IS_OK(result)) {
459 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
463 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
464 Printer->sharename, p->msg_ctx);
465 if (!W_ERROR_IS_OK(result)) {
468 prune_printername_cache();
472 /****************************************************************************
473 Return the snum of a printer corresponding to an handle.
474 ****************************************************************************/
476 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
477 int *number, struct share_params **params)
479 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
482 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
487 switch (Printer->printer_type) {
489 DEBUG(4,("short name:%s\n", Printer->sharename));
490 *number = print_queue_snum(Printer->sharename);
491 return (*number != -1);
499 /****************************************************************************
500 Set printer handle type.
501 Check if it's \\server or \\server\printer
502 ****************************************************************************/
504 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
506 DEBUG(3,("Setting printer type=%s\n", handlename));
508 /* it's a print server */
509 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
510 DEBUGADD(4,("Printer is a print server\n"));
511 Printer->printer_type = SPLHND_SERVER;
513 /* it's a printer (set_printer_hnd_name() will handle port monitors */
515 DEBUGADD(4,("Printer is a printer\n"));
516 Printer->printer_type = SPLHND_PRINTER;
522 static void prune_printername_cache_fn(const char *key, const char *value,
523 time_t timeout, void *private_data)
528 static void prune_printername_cache(void)
530 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
533 /****************************************************************************
534 Set printer handle name.. Accept names like \\server, \\server\printer,
535 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
536 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
537 XcvDataPort() interface.
538 ****************************************************************************/
540 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
541 const struct auth_session_info *session_info,
542 struct messaging_context *msg_ctx,
543 struct printer_handle *Printer,
544 const char *handlename)
547 int n_services=lp_numservices();
549 const char *printername;
550 const char *servername = NULL;
553 struct spoolss_PrinterInfo2 *info2 = NULL;
558 * Hopefully nobody names his printers like this. Maybe \ or ,
559 * are illegal in printer names even?
561 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
565 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
566 (unsigned long)strlen(handlename)));
568 aprinter = discard_const_p(char, handlename);
569 if ( *handlename == '\\' ) {
570 servername = canon_servername(handlename);
571 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
575 if (!is_myname_or_ipaddr(servername)) {
576 return WERR_INVALID_PRINTER_NAME;
578 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
579 if (Printer->servername == NULL) {
584 if (Printer->printer_type == SPLHND_SERVER) {
588 if (Printer->printer_type != SPLHND_PRINTER) {
589 return WERR_INVALID_HANDLE;
592 DEBUGADD(5, ("searching for [%s]\n", aprinter));
594 p = strchr(aprinter, ',');
601 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
603 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
609 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
612 /* check for the Port Monitor Interface */
613 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
614 Printer->printer_type = SPLHND_PORTMON_TCP;
615 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
618 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
619 Printer->printer_type = SPLHND_PORTMON_LOCAL;
620 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
625 * With hundreds of printers, the "for" loop iterating all
626 * shares can be quite expensive, as it is done on every
627 * OpenPrinter. The loop maps "aprinter" to "sname", the
628 * result of which we cache in gencache.
631 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
633 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
635 found = (strcmp(tmp, printer_not_found) != 0);
637 DEBUG(4, ("Printer %s not found\n", aprinter));
639 return WERR_INVALID_PRINTER_NAME;
645 /* Search all sharenames first as this is easier than pulling
646 the printer_info_2 off of disk. Don't use find_service() since
647 that calls out to map_username() */
649 /* do another loop to look for printernames */
650 for (snum = 0; !found && snum < n_services; snum++) {
651 const char *printer = lp_const_servicename(snum);
653 /* no point going on if this is not a printer */
654 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
658 /* ignore [printers] share */
659 if (strequal(printer, "printers")) {
663 fstrcpy(sname, printer);
664 if (strequal(aprinter, printer)) {
669 /* no point looking up the printer object if
670 we aren't allowing printername != sharename */
671 if (lp_force_printername(snum)) {
675 result = winreg_get_printer_internal(mem_ctx,
680 if ( !W_ERROR_IS_OK(result) ) {
681 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
682 sname, win_errstr(result)));
686 printername = strrchr(info2->printername, '\\');
687 if (printername == NULL) {
688 printername = info2->printername;
693 if (strequal(printername, aprinter)) {
698 DEBUGADD(10, ("printername: %s\n", printername));
704 if (cache_key != NULL) {
705 gencache_set(cache_key, printer_not_found,
707 TALLOC_FREE(cache_key);
709 DEBUGADD(4,("Printer not found\n"));
710 return WERR_INVALID_PRINTER_NAME;
713 if (cache_key != NULL) {
714 gencache_set(cache_key, sname, time(NULL)+300);
715 TALLOC_FREE(cache_key);
718 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
720 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
725 /****************************************************************************
726 Find first available printer slot. creates a printer handle for you.
727 ****************************************************************************/
729 static WERROR open_printer_hnd(struct pipes_struct *p,
730 struct policy_handle *hnd,
732 uint32_t access_granted)
734 struct printer_handle *new_printer;
737 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
739 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
740 if (new_printer == NULL) {
743 talloc_set_destructor(new_printer, printer_entry_destructor);
745 /* This also steals the printer_handle on the policy_handle */
746 if (!create_policy_hnd(p, hnd, new_printer)) {
747 TALLOC_FREE(new_printer);
748 return WERR_INVALID_HANDLE;
751 /* Add to the internal list. */
752 DLIST_ADD(printers_list, new_printer);
754 new_printer->notify.option=NULL;
756 if (!set_printer_hnd_printertype(new_printer, name)) {
757 close_printer_handle(p, hnd);
758 return WERR_INVALID_HANDLE;
761 result = set_printer_hnd_name(p->mem_ctx,
762 get_session_info_system(),
765 if (!W_ERROR_IS_OK(result)) {
766 close_printer_handle(p, hnd);
770 new_printer->access_granted = access_granted;
772 DEBUG(5, ("%d printer handles active\n",
773 (int)num_pipe_handles(p)));
778 /***************************************************************************
779 check to see if the client motify handle is monitoring the notification
780 given by (notify_type, notify_field).
781 **************************************************************************/
783 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
784 uint16_t notify_field)
789 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
790 uint16_t notify_field)
792 struct spoolss_NotifyOption *option = p->notify.option;
796 * Flags should always be zero when the change notify
797 * is registered by the client's spooler. A user Win32 app
798 * might use the flags though instead of the NOTIFY_OPTION_INFO
807 return is_monitoring_event_flags(
808 p->notify.flags, notify_type, notify_field);
810 for (i = 0; i < option->count; i++) {
812 /* Check match for notify_type */
814 if (option->types[i].type != notify_type)
817 /* Check match for field */
819 for (j = 0; j < option->types[i].count; j++) {
820 if (option->types[i].fields[j].field == notify_field) {
826 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
827 p->servername, p->sharename, notify_type, notify_field));
832 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
833 _data->data.integer[0] = _integer; \
834 _data->data.integer[1] = 0;
837 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
838 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
839 if (!_data->data.string.string) {\
840 _data->data.string.size = 0; \
842 _data->data.string.size = strlen_m_term(_p) * 2;
844 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
845 _data->data.devmode.devmode = _devmode;
847 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
848 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
849 if (!_data->data.sd.sd) { \
850 _data->data.sd.sd_size = 0; \
852 _data->data.sd.sd_size = \
853 ndr_size_security_descriptor(_data->data.sd.sd, 0);
855 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
860 struct spoolss_Time st;
864 if (!init_systemtime(&st, t)) {
868 p = talloc_array(mem_ctx, char, len);
874 * Systemtime must be linearized as a set of UINT16's.
875 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
878 SSVAL(p, 0, st.year);
879 SSVAL(p, 2, st.month);
880 SSVAL(p, 4, st.day_of_week);
882 SSVAL(p, 8, st.hour);
883 SSVAL(p, 10, st.minute);
884 SSVAL(p, 12, st.second);
885 SSVAL(p, 14, st.millisecond);
891 /* Convert a notification message to a struct spoolss_Notify */
893 static void notify_one_value(struct spoolss_notify_msg *msg,
894 struct spoolss_Notify *data,
897 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
900 static void notify_string(struct spoolss_notify_msg *msg,
901 struct spoolss_Notify *data,
904 /* The length of the message includes the trailing \0 */
906 data->data.string.size = msg->len * 2;
907 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
908 if (!data->data.string.string) {
909 data->data.string.size = 0;
914 static void notify_system_time(struct spoolss_notify_msg *msg,
915 struct spoolss_Notify *data,
918 data->data.string.string = NULL;
919 data->data.string.size = 0;
921 if (msg->len != sizeof(time_t)) {
922 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
927 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
928 &data->data.string.string,
929 &data->data.string.size);
932 struct notify2_message_table {
934 void (*fn)(struct spoolss_notify_msg *msg,
935 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
938 static struct notify2_message_table printer_notify_table[] = {
939 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
940 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
941 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
942 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
943 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
944 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
945 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
946 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
947 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
948 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
949 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
950 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
951 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
952 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
953 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
954 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
955 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
956 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
957 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
960 static struct notify2_message_table job_notify_table[] = {
961 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
962 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
963 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
964 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
965 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
966 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
967 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
968 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
969 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
970 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
971 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
972 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
973 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
974 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
975 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
976 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
977 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
978 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
979 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
980 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
981 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
982 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
983 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
984 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
988 /***********************************************************************
989 Allocate talloc context for container object
990 **********************************************************************/
992 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
997 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1002 /***********************************************************************
1003 release all allocated memory and zero out structure
1004 **********************************************************************/
1006 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1012 talloc_destroy(ctr->ctx);
1019 /***********************************************************************
1020 **********************************************************************/
1022 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1030 /***********************************************************************
1031 **********************************************************************/
1033 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1035 if ( !ctr || !ctr->msg_groups )
1038 if ( idx >= ctr->num_groups )
1041 return &ctr->msg_groups[idx];
1045 /***********************************************************************
1046 How many groups of change messages do we have ?
1047 **********************************************************************/
1049 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1054 return ctr->num_groups;
1057 /***********************************************************************
1058 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1059 **********************************************************************/
1061 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1063 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1064 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1065 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1071 /* loop over all groups looking for a matching printer name */
1073 for ( i=0; i<ctr->num_groups; i++ ) {
1074 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1078 /* add a new group? */
1080 if ( i == ctr->num_groups ) {
1083 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1084 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1087 ctr->msg_groups = groups;
1089 /* clear the new entry and set the printer name */
1091 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1092 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1095 /* add the change messages; 'i' is the correct index now regardless */
1097 msg_grp = &ctr->msg_groups[i];
1099 msg_grp->num_msgs++;
1101 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1102 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1105 msg_grp->msgs = msg_list;
1107 new_slot = msg_grp->num_msgs-1;
1108 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1110 /* need to allocate own copy of data */
1112 if ( msg->len != 0 )
1113 msg_grp->msgs[new_slot].notify.data = (char *)
1114 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1116 return ctr->num_groups;
1119 static void construct_info_data(struct spoolss_Notify *info_data,
1120 enum spoolss_NotifyType type,
1121 uint16_t field, int id);
1123 /***********************************************************************
1124 Send a change notication message on all handles which have a call
1126 **********************************************************************/
1128 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1129 struct printer_handle *prn_hnd,
1130 SPOOLSS_NOTIFY_MSG *messages,
1132 struct spoolss_Notify **_notifies,
1135 struct spoolss_Notify *notifies;
1136 SPOOLSS_NOTIFY_MSG *msg;
1141 notifies = talloc_zero_array(mem_ctx,
1142 struct spoolss_Notify, num_msgs);
1147 for (i = 0; i < num_msgs; i++) {
1151 /* Are we monitoring this event? */
1153 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1157 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1158 "for printer [%s]\n",
1159 msg->type, msg->field, prn_hnd->sharename));
1162 * if the is a printer notification handle and not a job
1163 * notification type, then set the id to 0.
1164 * Otherwise just use what was specified in the message.
1166 * When registering change notification on a print server
1167 * handle we always need to send back the id (snum) matching
1168 * the printer for which the change took place.
1169 * For change notify registered on a printer handle,
1170 * this does not matter and the id should be 0.
1175 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1176 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1182 /* Convert unix jobid to smb jobid */
1184 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1185 id = sysjob_to_jobid(msg->id);
1188 DEBUG(3, ("no such unix jobid %d\n",
1194 construct_info_data(¬ifies[count],
1195 msg->type, msg->field, id);
1198 case PRINTER_NOTIFY_TYPE:
1199 if (printer_notify_table[msg->field].fn) {
1200 printer_notify_table[msg->field].fn(msg,
1201 ¬ifies[count], mem_ctx);
1205 case JOB_NOTIFY_TYPE:
1206 if (job_notify_table[msg->field].fn) {
1207 job_notify_table[msg->field].fn(msg,
1208 ¬ifies[count], mem_ctx);
1213 DEBUG(5, ("Unknown notification type %d\n",
1221 *_notifies = notifies;
1227 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1228 struct printer_handle *prn_hnd,
1229 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1231 struct spoolss_Notify *notifies;
1233 union spoolss_ReplyPrinterInfo info;
1234 struct spoolss_NotifyInfo info0;
1235 uint32_t reply_result;
1240 /* Is there notification on this handle? */
1241 if (prn_hnd->notify.cli_chan == NULL ||
1242 prn_hnd->notify.cli_chan->cli_pipe == NULL ||
1243 prn_hnd->notify.cli_chan->cli_pipe->binding_handle == NULL ||
1244 prn_hnd->notify.cli_chan->active_connections == 0) {
1248 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1249 prn_hnd->servername, prn_hnd->sharename));
1251 /* For this printer? Print servers always receive notifications. */
1252 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1253 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1257 DEBUG(10,("Our printer\n"));
1259 /* build the array of change notifications */
1260 ret = build_notify2_messages(mem_ctx, prn_hnd,
1262 msg_group->num_msgs,
1268 info0.version = 0x2;
1269 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1270 info0.count = count;
1271 info0.notifies = notifies;
1273 info.info0 = &info0;
1275 status = dcerpc_spoolss_RouterReplyPrinterEx(
1276 prn_hnd->notify.cli_chan->cli_pipe->binding_handle,
1278 &prn_hnd->notify.cli_hnd,
1279 prn_hnd->notify.change, /* color */
1280 prn_hnd->notify.flags,
1282 0, /* reply_type, must be 0 */
1284 if (!NT_STATUS_IS_OK(status)) {
1285 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1287 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1288 nt_errstr(status)));
1289 werr = ntstatus_to_werror(status);
1290 } else if (!W_ERROR_IS_OK(werr)) {
1291 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1293 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1296 switch (reply_result) {
1299 case PRINTER_NOTIFY_INFO_DISCARDED:
1300 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1301 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1310 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1312 struct printer_handle *p;
1313 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1314 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1318 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1322 if (!msg_group->msgs) {
1323 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1327 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1329 /* loop over all printers */
1331 for (p = printers_list; p; p = p->next) {
1332 ret = send_notify2_printer(mem_ctx, p, msg_group);
1339 DEBUG(8,("send_notify2_changes: Exit...\n"));
1343 /***********************************************************************
1344 **********************************************************************/
1346 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1349 uint32_t tv_sec, tv_usec;
1352 /* Unpack message */
1354 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1357 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1359 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1362 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1363 &msg->notify.value[0], &msg->notify.value[1]);
1365 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1366 &msg->len, &msg->notify.data);
1368 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1369 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1371 tv->tv_sec = tv_sec;
1372 tv->tv_usec = tv_usec;
1375 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1376 msg->notify.value[1]));
1378 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1383 /********************************************************************
1384 Receive a notify2 message list
1385 ********************************************************************/
1387 static void receive_notify2_message_list(struct messaging_context *msg,
1390 struct server_id server_id,
1393 size_t msg_count, i;
1394 char *buf = (char *)data->data;
1397 SPOOLSS_NOTIFY_MSG notify;
1398 SPOOLSS_NOTIFY_MSG_CTR messages;
1401 if (data->length < 4) {
1402 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1406 msg_count = IVAL(buf, 0);
1409 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1411 if (msg_count == 0) {
1412 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1416 /* initialize the container */
1418 ZERO_STRUCT( messages );
1419 notify_msg_ctr_init( &messages );
1422 * build message groups for each printer identified
1423 * in a change_notify msg. Remember that a PCN message
1424 * includes the handle returned for the srv_spoolss_replyopenprinter()
1425 * call. Therefore messages are grouped according to printer handle.
1428 for ( i=0; i<msg_count; i++ ) {
1429 struct timeval msg_tv;
1431 if (msg_ptr + 4 - buf > data->length) {
1432 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1436 msg_len = IVAL(msg_ptr,0);
1439 if (msg_ptr + msg_len - buf > data->length) {
1440 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1444 /* unpack messages */
1446 ZERO_STRUCT( notify );
1447 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1450 /* add to correct list in container */
1452 notify_msg_ctr_addmsg( &messages, ¬ify );
1454 /* free memory that might have been allocated by notify2_unpack_msg() */
1456 if ( notify.len != 0 )
1457 SAFE_FREE( notify.notify.data );
1460 /* process each group of messages */
1462 num_groups = notify_msg_ctr_numgroups( &messages );
1463 for ( i=0; i<num_groups; i++ )
1464 send_notify2_changes( &messages, i );
1469 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1470 (uint32_t)msg_count ));
1472 notify_msg_ctr_destroy( &messages );
1477 /********************************************************************
1478 Send a message to ourself about new driver being installed
1479 so we can upgrade the information for each printer bound to this
1481 ********************************************************************/
1483 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1484 struct messaging_context *msg_ctx)
1486 int len = strlen(drivername);
1491 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1494 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1495 MSG_PRINTER_DRVUPGRADE,
1496 (const uint8_t *)drivername, len+1);
1501 void srv_spoolss_cleanup(void)
1503 struct printer_session_counter *session_counter;
1505 for (session_counter = counter_list;
1506 session_counter != NULL;
1507 session_counter = counter_list) {
1508 DLIST_REMOVE(counter_list, session_counter);
1509 TALLOC_FREE(session_counter);
1513 /**********************************************************************
1514 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1515 over all printers, upgrading ones as necessary
1516 **********************************************************************/
1518 void do_drv_upgrade_printer(struct messaging_context *msg,
1521 struct server_id server_id,
1524 TALLOC_CTX *tmp_ctx;
1525 const struct auth_session_info *session_info = get_session_info_system();
1526 struct spoolss_PrinterInfo2 *pinfo2;
1528 const char *drivername;
1530 int n_services = lp_numservices();
1531 struct dcerpc_binding_handle *b = NULL;
1533 tmp_ctx = talloc_new(NULL);
1534 if (!tmp_ctx) return;
1536 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1538 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1542 DEBUG(10, ("do_drv_upgrade_printer: "
1543 "Got message for new driver [%s]\n", drivername));
1545 /* Iterate the printer list */
1547 for (snum = 0; snum < n_services; snum++) {
1548 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1552 /* ignore [printers] share */
1553 if (strequal(lp_const_servicename(snum), "printers")) {
1558 result = winreg_printer_binding_handle(tmp_ctx,
1562 if (!W_ERROR_IS_OK(result)) {
1567 result = winreg_get_printer(tmp_ctx, b,
1568 lp_const_servicename(snum),
1571 if (!W_ERROR_IS_OK(result)) {
1575 if (!pinfo2->drivername) {
1579 if (strcmp(drivername, pinfo2->drivername) != 0) {
1583 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1585 /* all we care about currently is the change_id */
1586 result = winreg_printer_update_changeid(tmp_ctx, b,
1587 pinfo2->printername);
1589 if (!W_ERROR_IS_OK(result)) {
1590 DEBUG(3, ("do_drv_upgrade_printer: "
1591 "Failed to update changeid [%s]\n",
1592 win_errstr(result)));
1598 talloc_free(tmp_ctx);
1601 /********************************************************************
1602 Update the cache for all printq's with a registered client
1604 ********************************************************************/
1606 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1608 struct printer_handle *printer = printers_list;
1611 /* loop through all printers and update the cache where
1612 a client is connected */
1614 if ((printer->printer_type == SPLHND_PRINTER) &&
1615 ((printer->notify.cli_chan != NULL) &&
1616 (printer->notify.cli_chan->active_connections > 0))) {
1617 snum = print_queue_snum(printer->sharename);
1618 print_queue_status(msg_ctx, snum, NULL, NULL);
1621 printer = printer->next;
1627 /****************************************************************
1628 _spoolss_OpenPrinter
1629 ****************************************************************/
1631 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1632 struct spoolss_OpenPrinter *r)
1634 struct spoolss_OpenPrinterEx e;
1637 ZERO_STRUCT(e.in.userlevel);
1639 e.in.printername = r->in.printername;
1640 e.in.datatype = r->in.datatype;
1641 e.in.devmode_ctr = r->in.devmode_ctr;
1642 e.in.access_mask = r->in.access_mask;
1645 e.out.handle = r->out.handle;
1647 werr = _spoolss_OpenPrinterEx(p, &e);
1649 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1650 /* OpenPrinterEx returns this for a bad
1651 * printer name. We must return WERR_INVALID_PRINTER_NAME
1654 werr = WERR_INVALID_PRINTER_NAME;
1660 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1661 struct spoolss_DeviceMode *orig,
1662 struct spoolss_DeviceMode **dest)
1664 struct spoolss_DeviceMode *dm;
1666 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1671 /* copy all values, then duplicate strings and structs */
1674 dm->devicename = talloc_strdup(dm, orig->devicename);
1675 if (!dm->devicename) {
1678 dm->formname = talloc_strdup(dm, orig->formname);
1679 if (!dm->formname) {
1682 if (orig->driverextra_data.data) {
1683 dm->driverextra_data.data =
1684 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1685 orig->driverextra_data.length);
1686 if (!dm->driverextra_data.data) {
1695 /****************************************************************
1696 _spoolss_OpenPrinterEx
1697 ****************************************************************/
1699 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1700 struct spoolss_OpenPrinterEx *r)
1705 struct printer_handle *Printer=NULL;
1709 if (!r->in.printername) {
1710 return WERR_INVALID_PARAM;
1713 if (!*r->in.printername) {
1714 return WERR_INVALID_PARAM;
1717 if (r->in.level > 3) {
1718 return WERR_INVALID_PARAM;
1720 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1721 (r->in.level == 2 && !r->in.userlevel.level2) ||
1722 (r->in.level == 3 && !r->in.userlevel.level3)) {
1723 return WERR_INVALID_PARAM;
1726 /* some sanity check because you can open a printer or a print server */
1727 /* aka: \\server\printer or \\server */
1729 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1731 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1732 if (!W_ERROR_IS_OK(result)) {
1733 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1734 "for printer %s\n", r->in.printername));
1735 ZERO_STRUCTP(r->out.handle);
1739 Printer = find_printer_index_by_hnd(p, r->out.handle);
1741 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1742 "handle we created for printer %s\n", r->in.printername));
1743 close_printer_handle(p, r->out.handle);
1744 ZERO_STRUCTP(r->out.handle);
1745 return WERR_INVALID_PARAM;
1749 * First case: the user is opening the print server:
1751 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1752 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1754 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1755 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1756 * or if the user is listed in the smb.conf printer admin parameter.
1758 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1759 * client view printer folder, but does not show the MSAPW.
1761 * Note: this test needs code to check access rights here too. Jeremy
1762 * could you look at this?
1764 * Second case: the user is opening a printer:
1765 * NT doesn't let us connect to a printer if the connecting user
1766 * doesn't have print permission.
1768 * Third case: user is opening a Port Monitor
1769 * access checks same as opening a handle to the print server.
1772 switch (Printer->printer_type )
1775 case SPLHND_PORTMON_TCP:
1776 case SPLHND_PORTMON_LOCAL:
1777 /* Printserver handles use global struct... */
1781 /* Map standard access rights to object specific access rights */
1783 se_map_standard(&r->in.access_mask,
1784 &printserver_std_mapping);
1786 /* Deny any object specific bits that don't apply to print
1787 servers (i.e printer and job specific bits) */
1789 r->in.access_mask &= SEC_MASK_SPECIFIC;
1791 if (r->in.access_mask &
1792 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1793 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1794 close_printer_handle(p, r->out.handle);
1795 ZERO_STRUCTP(r->out.handle);
1796 return WERR_ACCESS_DENIED;
1799 /* Allow admin access */
1801 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1803 if (!lp_ms_add_printer_wizard()) {
1804 close_printer_handle(p, r->out.handle);
1805 ZERO_STRUCTP(r->out.handle);
1806 return WERR_ACCESS_DENIED;
1809 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1810 and not a printer admin, then fail */
1812 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1813 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1814 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1815 p->session_info->security_token)) {
1816 close_printer_handle(p, r->out.handle);
1817 ZERO_STRUCTP(r->out.handle);
1818 DEBUG(3,("access DENIED as user is not root, "
1819 "has no printoperator privilege, "
1820 "not a member of the printoperator builtin group and "
1821 "is not in printer admin list"));
1822 return WERR_ACCESS_DENIED;
1825 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1829 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1832 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1833 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1835 /* We fall through to return WERR_OK */
1838 case SPLHND_PRINTER:
1839 /* NT doesn't let us connect to a printer if the connecting user
1840 doesn't have print permission. */
1842 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1843 close_printer_handle(p, r->out.handle);
1844 ZERO_STRUCTP(r->out.handle);
1848 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1849 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1852 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1854 /* map an empty access mask to the minimum access mask */
1855 if (r->in.access_mask == 0x0)
1856 r->in.access_mask = PRINTER_ACCESS_USE;
1859 * If we are not serving the printer driver for this printer,
1860 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1861 * will keep NT clients happy --jerry
1864 if (lp_use_client_driver(snum)
1865 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1867 r->in.access_mask = PRINTER_ACCESS_USE;
1870 /* check smb.conf parameters and the the sec_desc */
1871 raddr = tsocket_address_inet_addr_string(p->remote_address,
1873 if (raddr == NULL) {
1877 rc = get_remote_hostname(p->remote_address,
1883 if (strequal(rhost, "UNKNOWN")) {
1887 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1889 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1890 ZERO_STRUCTP(r->out.handle);
1891 return WERR_ACCESS_DENIED;
1894 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1895 p->session_info->security_token, snum) ||
1896 !print_access_check(p->session_info,
1899 r->in.access_mask)) {
1900 DEBUG(3, ("access DENIED for printer open\n"));
1901 close_printer_handle(p, r->out.handle);
1902 ZERO_STRUCTP(r->out.handle);
1903 return WERR_ACCESS_DENIED;
1906 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1907 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1908 close_printer_handle(p, r->out.handle);
1909 ZERO_STRUCTP(r->out.handle);
1910 return WERR_ACCESS_DENIED;
1913 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1914 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1916 r->in.access_mask = PRINTER_ACCESS_USE;
1918 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1919 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1921 winreg_create_printer_internal(p->mem_ctx,
1922 get_session_info_system(),
1924 lp_const_servicename(snum));
1929 /* sanity check to prevent programmer error */
1930 ZERO_STRUCTP(r->out.handle);
1934 Printer->access_granted = r->in.access_mask;
1937 * If the client sent a devmode in the OpenPrinter() call, then
1938 * save it here in case we get a job submission on this handle
1941 if ((Printer->printer_type != SPLHND_SERVER) &&
1942 r->in.devmode_ctr.devmode) {
1943 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1947 #if 0 /* JERRY -- I'm doubtful this is really effective */
1948 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1949 optimization in Windows 2000 clients --jerry */
1951 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1952 && (RA_WIN2K == get_remote_arch()) )
1954 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1962 /****************************************************************
1963 _spoolss_ClosePrinter
1964 ****************************************************************/
1966 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1967 struct spoolss_ClosePrinter *r)
1969 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1971 if (Printer && Printer->document_started) {
1972 struct spoolss_EndDocPrinter e;
1974 e.in.handle = r->in.handle;
1976 _spoolss_EndDocPrinter(p, &e);
1979 if (!close_printer_handle(p, r->in.handle))
1982 /* clear the returned printer handle. Observed behavior
1983 from Win2k server. Don't think this really matters.
1984 Previous code just copied the value of the closed
1987 ZERO_STRUCTP(r->out.handle);
1992 /****************************************************************
1993 _spoolss_DeletePrinter
1994 ****************************************************************/
1996 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1997 struct spoolss_DeletePrinter *r)
1999 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2003 if (Printer && Printer->document_started) {
2004 struct spoolss_EndDocPrinter e;
2006 e.in.handle = r->in.handle;
2008 _spoolss_EndDocPrinter(p, &e);
2011 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2012 winreg_delete_printer_key_internal(p->mem_ctx,
2013 get_session_info_system(),
2015 lp_const_servicename(snum),
2019 result = delete_printer_handle(p, r->in.handle);
2024 /*******************************************************************
2025 * static function to lookup the version id corresponding to an
2026 * long architecture string
2027 ******************************************************************/
2029 static const struct print_architecture_table_node archi_table[]= {
2031 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2032 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2033 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2034 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2035 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2036 {"Windows IA64", SPL_ARCH_IA64, 3 },
2037 {"Windows x64", SPL_ARCH_X64, 3 },
2041 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2042 SPOOLSS_DRIVER_VERSION_NT35,
2043 SPOOLSS_DRIVER_VERSION_NT4,
2044 SPOOLSS_DRIVER_VERSION_200X,
2047 static int get_version_id(const char *arch)
2051 for (i=0; archi_table[i].long_archi != NULL; i++)
2053 if (strcmp(arch, archi_table[i].long_archi) == 0)
2054 return (archi_table[i].version);
2060 /****************************************************************
2061 _spoolss_DeletePrinterDriver
2062 ****************************************************************/
2064 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2065 struct spoolss_DeletePrinterDriver *r)
2068 struct spoolss_DriverInfo8 *info = NULL;
2071 struct dcerpc_binding_handle *b;
2072 TALLOC_CTX *tmp_ctx = NULL;
2076 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2077 and not a printer admin, then fail */
2079 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2080 !security_token_has_privilege(p->session_info->security_token,
2081 SEC_PRIV_PRINT_OPERATOR)) {
2082 return WERR_ACCESS_DENIED;
2085 /* check that we have a valid driver name first */
2087 if ((version = get_version_id(r->in.architecture)) == -1) {
2088 return WERR_INVALID_ENVIRONMENT;
2091 tmp_ctx = talloc_new(p->mem_ctx);
2096 status = winreg_printer_binding_handle(tmp_ctx,
2097 get_session_info_system(),
2100 if (!W_ERROR_IS_OK(status)) {
2104 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2105 status = winreg_get_driver(tmp_ctx, b,
2106 r->in.architecture, r->in.driver,
2107 drv_cversion[i], &info);
2108 if (!W_ERROR_IS_OK(status)) {
2109 DEBUG(5, ("skipping del of driver with version %d\n",
2115 if (printer_driver_in_use(tmp_ctx, b, info)) {
2116 status = WERR_PRINTER_DRIVER_IN_USE;
2120 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2121 if (!W_ERROR_IS_OK(status)) {
2122 DEBUG(0, ("failed del of driver with version %d\n",
2127 if (found == false) {
2128 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2129 status = WERR_UNKNOWN_PRINTER_DRIVER;
2135 talloc_free(tmp_ctx);
2140 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2141 struct pipes_struct *p,
2142 struct spoolss_DeletePrinterDriverEx *r,
2143 struct dcerpc_binding_handle *b,
2144 struct spoolss_DriverInfo8 *info)
2149 if (printer_driver_in_use(mem_ctx, b, info)) {
2150 status = WERR_PRINTER_DRIVER_IN_USE;
2155 * we have a couple of cases to consider.
2156 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2157 * then the delete should fail if **any** files overlap with
2159 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2160 * non-overlapping files
2161 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2162 * are set, then do not delete any files
2163 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2166 delete_files = r->in.delete_flags
2167 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2171 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2172 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2173 status = WERR_PRINTER_DRIVER_IN_USE;
2177 * printer_driver_files_in_use() has trimmed overlapping files
2178 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2183 status = winreg_del_driver(mem_ctx, b, info, info->version);
2184 if (!W_ERROR_IS_OK(status)) {
2189 * now delete any associated files if delete_files is
2190 * true. Even if this part failes, we return succes
2191 * because the driver doesn not exist any more
2194 delete_driver_files(p->session_info, info);
2201 /****************************************************************
2202 _spoolss_DeletePrinterDriverEx
2203 ****************************************************************/
2205 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2206 struct spoolss_DeletePrinterDriverEx *r)
2208 struct spoolss_DriverInfo8 *info = NULL;
2210 struct dcerpc_binding_handle *b;
2211 TALLOC_CTX *tmp_ctx = NULL;
2215 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2216 and not a printer admin, then fail */
2218 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2219 !security_token_has_privilege(p->session_info->security_token,
2220 SEC_PRIV_PRINT_OPERATOR)) {
2221 return WERR_ACCESS_DENIED;
2224 /* check that we have a valid driver name first */
2225 if (get_version_id(r->in.architecture) == -1) {
2226 /* this is what NT returns */
2227 return WERR_INVALID_ENVIRONMENT;
2230 tmp_ctx = talloc_new(p->mem_ctx);
2235 status = winreg_printer_binding_handle(tmp_ctx,
2236 get_session_info_system(),
2239 if (!W_ERROR_IS_OK(status)) {
2243 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2244 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2245 && (drv_cversion[i] != r->in.version)) {
2249 /* check if a driver with this version exists before delete */
2250 status = winreg_get_driver(tmp_ctx, b,
2251 r->in.architecture, r->in.driver,
2252 drv_cversion[i], &info);
2253 if (!W_ERROR_IS_OK(status)) {
2254 DEBUG(5, ("skipping del of driver with version %d\n",
2260 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2261 if (!W_ERROR_IS_OK(status)) {
2262 DEBUG(0, ("failed to delete driver with version %d\n",
2267 if (found == false) {
2268 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2269 status = WERR_UNKNOWN_PRINTER_DRIVER;
2275 talloc_free(tmp_ctx);
2280 /********************************************************************
2281 GetPrinterData on a printer server Handle.
2282 ********************************************************************/
2284 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2286 enum winreg_Type *type,
2287 union spoolss_PrinterData *data)
2289 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2291 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2293 SIVAL(&data->value, 0, 0x00);
2297 if (!strcasecmp_m(value, "BeepEnabled")) {
2299 SIVAL(&data->value, 0, 0x00);
2303 if (!strcasecmp_m(value, "EventLog")) {
2305 /* formally was 0x1b */
2306 SIVAL(&data->value, 0, 0x00);
2310 if (!strcasecmp_m(value, "NetPopup")) {
2312 SIVAL(&data->value, 0, 0x00);
2316 if (!strcasecmp_m(value, "MajorVersion")) {
2319 /* Windows NT 4.0 seems to not allow uploading of drivers
2320 to a server that reports 0x3 as the MajorVersion.
2321 need to investigate more how Win2k gets around this .
2324 if (RA_WINNT == get_remote_arch()) {
2325 SIVAL(&data->value, 0, 0x02);
2327 SIVAL(&data->value, 0, 0x03);
2333 if (!strcasecmp_m(value, "MinorVersion")) {
2335 SIVAL(&data->value, 0, 0x00);
2340 * uint32_t size = 0x114
2341 * uint32_t major = 5
2342 * uint32_t minor = [0|1]
2343 * uint32_t build = [2195|2600]
2344 * extra unicode string = e.g. "Service Pack 3"
2346 if (!strcasecmp_m(value, "OSVersion")) {
2348 enum ndr_err_code ndr_err;
2349 struct spoolss_OSVersion os;
2351 os.major = 5; /* Windows 2000 == 5.0 */
2353 os.build = 2195; /* build */
2354 os.extra_string = ""; /* leave extra string empty */
2356 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2357 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2358 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2359 return WERR_GENERAL_FAILURE;
2363 data->binary = blob;
2369 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2372 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2373 W_ERROR_HAVE_NO_MEMORY(data->string);
2378 if (!strcasecmp_m(value, "Architecture")) {
2380 data->string = talloc_strdup(mem_ctx,
2381 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2382 W_ERROR_HAVE_NO_MEMORY(data->string);
2387 if (!strcasecmp_m(value, "DsPresent")) {
2390 /* only show the publish check box if we are a
2391 member of a AD domain */
2393 if (lp_security() == SEC_ADS) {
2394 SIVAL(&data->value, 0, 0x01);
2396 SIVAL(&data->value, 0, 0x00);
2401 if (!strcasecmp_m(value, "DNSMachineName")) {
2402 const char *hostname = get_mydnsfullname();
2405 return WERR_BADFILE;
2409 data->string = talloc_strdup(mem_ctx, hostname);
2410 W_ERROR_HAVE_NO_MEMORY(data->string);
2417 return WERR_INVALID_PARAM;
2420 /****************************************************************
2421 _spoolss_GetPrinterData
2422 ****************************************************************/
2424 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2425 struct spoolss_GetPrinterData *r)
2427 struct spoolss_GetPrinterDataEx r2;
2429 r2.in.handle = r->in.handle;
2430 r2.in.key_name = "PrinterDriverData";
2431 r2.in.value_name = r->in.value_name;
2432 r2.in.offered = r->in.offered;
2433 r2.out.type = r->out.type;
2434 r2.out.data = r->out.data;
2435 r2.out.needed = r->out.needed;
2437 return _spoolss_GetPrinterDataEx(p, &r2);
2440 /*********************************************************
2441 Connect to the client machine.
2442 **********************************************************/
2444 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2445 struct sockaddr_storage *client_ss, const char *remote_machine)
2448 struct cli_state *the_cli;
2449 struct sockaddr_storage rm_addr;
2450 char addr[INET6_ADDRSTRLEN];
2452 if ( is_zero_addr(client_ss) ) {
2453 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2455 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2456 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2459 print_sockaddr(addr, sizeof(addr), &rm_addr);
2461 rm_addr = *client_ss;
2462 print_sockaddr(addr, sizeof(addr), &rm_addr);
2463 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2467 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2468 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2473 /* setup the connection */
2474 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2475 &rm_addr, 0, "IPC$", "IPC",
2479 0, lp_client_signing());
2481 if ( !NT_STATUS_IS_OK( ret ) ) {
2482 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2487 if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2488 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2489 cli_shutdown(the_cli);
2494 * Ok - we have an anonymous connection to the IPC$ share.
2495 * Now start the NT Domain stuff :-).
2498 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2499 if (!NT_STATUS_IS_OK(ret)) {
2500 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2501 remote_machine, nt_errstr(ret)));
2502 cli_shutdown(the_cli);
2509 /***************************************************************************
2510 Connect to the client.
2511 ****************************************************************************/
2513 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2514 uint32_t localprinter,
2515 enum winreg_Type type,
2516 struct policy_handle *handle,
2517 struct notify_back_channel **_chan,
2518 struct sockaddr_storage *client_ss,
2519 struct messaging_context *msg_ctx)
2523 struct notify_back_channel *chan;
2525 for (chan = back_channels; chan; chan = chan->next) {
2526 if (memcmp(&chan->client_address, client_ss,
2527 sizeof(struct sockaddr_storage)) == 0) {
2533 * If it's the first connection, contact the client
2534 * and connect to the IPC$ share anonymously
2537 fstring unix_printer;
2539 /* the +2 is to strip the leading 2 backslashs */
2540 fstrcpy(unix_printer, printer + 2);
2542 chan = talloc_zero(NULL, struct notify_back_channel);
2546 chan->client_address = *client_ss;
2548 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2553 DLIST_ADD(back_channels, chan);
2555 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2556 receive_notify2_message_list);
2559 if (chan->cli_pipe == NULL ||
2560 chan->cli_pipe->binding_handle == NULL) {
2561 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2562 "NULL %s for printer %s\n",
2563 chan->cli_pipe == NULL ?
2564 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2570 * Tell the specific printing tdb we want messages for this printer
2571 * by registering our PID.
2574 if (!print_notify_register_pid(snum)) {
2575 DEBUG(0, ("Failed to register our pid for printer %s\n",
2579 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2588 if (!NT_STATUS_IS_OK(status)) {
2589 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2590 result = ntstatus_to_werror(status);
2591 } else if (!W_ERROR_IS_OK(result)) {
2592 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2595 chan->active_connections++;
2598 return (W_ERROR_IS_OK(result));
2601 /****************************************************************
2602 ****************************************************************/
2604 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2605 const struct spoolss_NotifyOption *r)
2607 struct spoolss_NotifyOption *option;
2614 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2621 if (!option->count) {
2625 option->types = talloc_zero_array(option,
2626 struct spoolss_NotifyOptionType, option->count);
2627 if (!option->types) {
2628 talloc_free(option);
2632 for (i=0; i < option->count; i++) {
2633 option->types[i] = r->types[i];
2635 if (option->types[i].count) {
2636 option->types[i].fields = talloc_zero_array(option,
2637 union spoolss_Field, option->types[i].count);
2638 if (!option->types[i].fields) {
2639 talloc_free(option);
2642 for (k=0; k<option->types[i].count; k++) {
2643 option->types[i].fields[k] =
2644 r->types[i].fields[k];
2652 /****************************************************************
2653 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2655 * before replying OK: status=0 a rpc call is made to the workstation
2656 * asking ReplyOpenPrinter
2658 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2659 * called from api_spoolss_rffpcnex
2660 ****************************************************************/
2662 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2663 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2666 struct spoolss_NotifyOption *option = r->in.notify_options;
2667 struct sockaddr_storage client_ss;
2670 /* store the notify value in the printer struct */
2672 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2675 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2676 "Invalid handle (%s:%u:%u).\n",
2677 OUR_HANDLE(r->in.handle)));
2681 Printer->notify.flags = r->in.flags;
2682 Printer->notify.options = r->in.options;
2683 Printer->notify.printerlocal = r->in.printer_local;
2684 Printer->notify.msg_ctx = p->msg_ctx;
2686 TALLOC_FREE(Printer->notify.option);
2687 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2689 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2691 /* Connect to the client machine and send a ReplyOpenPrinter */
2693 if ( Printer->printer_type == SPLHND_SERVER)
2695 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2696 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2699 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2700 "remote_address is %s\n",
2701 tsocket_address_string(p->remote_address, p->mem_ctx)));
2703 if (!lp_print_notify_backchannel(snum)) {
2704 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2705 "backchannel disabled\n"));
2706 return WERR_SERVER_UNAVAILABLE;
2709 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2710 (struct sockaddr *) &client_ss,
2711 sizeof(struct sockaddr_storage));
2712 if (client_len < 0) {
2716 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2717 Printer->notify.printerlocal, REG_SZ,
2718 &Printer->notify.cli_hnd,
2719 &Printer->notify.cli_chan,
2720 &client_ss, p->msg_ctx)) {
2721 return WERR_SERVER_UNAVAILABLE;
2727 /*******************************************************************
2728 * fill a notify_info_data with the servername
2729 ********************************************************************/
2731 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2733 struct spoolss_Notify *data,
2734 print_queue_struct *queue,
2735 struct spoolss_PrinterInfo2 *pinfo2,
2736 TALLOC_CTX *mem_ctx)
2738 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2741 /*******************************************************************
2742 * fill a notify_info_data with the printername (not including the servername).
2743 ********************************************************************/
2745 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2747 struct spoolss_Notify *data,
2748 print_queue_struct *queue,
2749 struct spoolss_PrinterInfo2 *pinfo2,
2750 TALLOC_CTX *mem_ctx)
2752 /* the notify name should not contain the \\server\ part */
2753 const char *p = strrchr(pinfo2->printername, '\\');
2756 p = pinfo2->printername;
2761 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2764 /*******************************************************************
2765 * fill a notify_info_data with the servicename
2766 ********************************************************************/
2768 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2770 struct spoolss_Notify *data,
2771 print_queue_struct *queue,
2772 struct spoolss_PrinterInfo2 *pinfo2,
2773 TALLOC_CTX *mem_ctx)
2775 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2778 /*******************************************************************
2779 * fill a notify_info_data with the port name
2780 ********************************************************************/
2782 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2784 struct spoolss_Notify *data,
2785 print_queue_struct *queue,
2786 struct spoolss_PrinterInfo2 *pinfo2,
2787 TALLOC_CTX *mem_ctx)
2789 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2792 /*******************************************************************
2793 * fill a notify_info_data with the printername
2794 * but it doesn't exist, have to see what to do
2795 ********************************************************************/
2797 static void spoolss_notify_driver_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->drivername);
2807 /*******************************************************************
2808 * fill a notify_info_data with the comment
2809 ********************************************************************/
2811 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2813 struct spoolss_Notify *data,
2814 print_queue_struct *queue,
2815 struct spoolss_PrinterInfo2 *pinfo2,
2816 TALLOC_CTX *mem_ctx)
2820 if (*pinfo2->comment == '\0') {
2821 p = lp_comment(snum);
2823 p = pinfo2->comment;
2826 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2829 /*******************************************************************
2830 * fill a notify_info_data with the comment
2831 * location = "Room 1, floor 2, building 3"
2832 ********************************************************************/
2834 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2836 struct spoolss_Notify *data,
2837 print_queue_struct *queue,
2838 struct spoolss_PrinterInfo2 *pinfo2,
2839 TALLOC_CTX *mem_ctx)
2841 const char *loc = pinfo2->location;
2844 status = printer_list_get_printer(mem_ctx,
2849 if (NT_STATUS_IS_OK(status)) {
2851 loc = pinfo2->location;
2855 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2858 /*******************************************************************
2859 * fill a notify_info_data with the device mode
2860 * jfm:xxxx don't to it for know but that's a real problem !!!
2861 ********************************************************************/
2863 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2865 struct spoolss_Notify *data,
2866 print_queue_struct *queue,
2867 struct spoolss_PrinterInfo2 *pinfo2,
2868 TALLOC_CTX *mem_ctx)
2870 /* for a dummy implementation we have to zero the fields */
2871 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2874 /*******************************************************************
2875 * fill a notify_info_data with the separator file name
2876 ********************************************************************/
2878 static void spoolss_notify_sepfile(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 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2888 /*******************************************************************
2889 * fill a notify_info_data with the print processor
2890 * jfm:xxxx return always winprint to indicate we don't do anything to it
2891 ********************************************************************/
2893 static void spoolss_notify_print_processor(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->printprocessor);
2903 /*******************************************************************
2904 * fill a notify_info_data with the print processor options
2905 * jfm:xxxx send an empty string
2906 ********************************************************************/
2908 static void spoolss_notify_parameters(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->parameters);
2918 /*******************************************************************
2919 * fill a notify_info_data with the data type
2920 * jfm:xxxx always send RAW as data type
2921 ********************************************************************/
2923 static void spoolss_notify_datatype(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->datatype);
2933 /*******************************************************************
2934 * fill a notify_info_data with the security descriptor
2935 * jfm:xxxx send an null pointer to say no security desc
2936 * have to implement security before !
2937 ********************************************************************/
2939 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2941 struct spoolss_Notify *data,
2942 print_queue_struct *queue,
2943 struct spoolss_PrinterInfo2 *pinfo2,
2944 TALLOC_CTX *mem_ctx)
2946 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2949 /*******************************************************************
2950 * fill a notify_info_data with the attributes
2951 * jfm:xxxx a samba printer is always shared
2952 ********************************************************************/
2954 static void spoolss_notify_attributes(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_INTEGER(data, pinfo2->attributes);
2964 /*******************************************************************
2965 * fill a notify_info_data with the priority
2966 ********************************************************************/
2968 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2970 struct spoolss_Notify *data,
2971 print_queue_struct *queue,
2972 struct spoolss_PrinterInfo2 *pinfo2,
2973 TALLOC_CTX *mem_ctx)
2975 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2978 /*******************************************************************
2979 * fill a notify_info_data with the default priority
2980 ********************************************************************/
2982 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2984 struct spoolss_Notify *data,
2985 print_queue_struct *queue,
2986 struct spoolss_PrinterInfo2 *pinfo2,
2987 TALLOC_CTX *mem_ctx)
2989 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2992 /*******************************************************************
2993 * fill a notify_info_data with the start time
2994 ********************************************************************/
2996 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2998 struct spoolss_Notify *data,
2999 print_queue_struct *queue,
3000 struct spoolss_PrinterInfo2 *pinfo2,
3001 TALLOC_CTX *mem_ctx)
3003 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3006 /*******************************************************************
3007 * fill a notify_info_data with the until time
3008 ********************************************************************/
3010 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3012 struct spoolss_Notify *data,
3013 print_queue_struct *queue,
3014 struct spoolss_PrinterInfo2 *pinfo2,
3015 TALLOC_CTX *mem_ctx)
3017 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3020 /*******************************************************************
3021 * fill a notify_info_data with the status
3022 ********************************************************************/
3024 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3026 struct spoolss_Notify *data,
3027 print_queue_struct *queue,
3028 struct spoolss_PrinterInfo2 *pinfo2,
3029 TALLOC_CTX *mem_ctx)
3031 print_status_struct status;
3033 print_queue_length(msg_ctx, snum, &status);
3034 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3037 /*******************************************************************
3038 * fill a notify_info_data with the number of jobs queued
3039 ********************************************************************/
3041 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3043 struct spoolss_Notify *data,
3044 print_queue_struct *queue,
3045 struct spoolss_PrinterInfo2 *pinfo2,
3046 TALLOC_CTX *mem_ctx)
3048 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3049 data, print_queue_length(msg_ctx, snum, NULL));
3052 /*******************************************************************
3053 * fill a notify_info_data with the average ppm
3054 ********************************************************************/
3056 static void spoolss_notify_average_ppm(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 /* always respond 8 pages per minutes */
3064 /* a little hard ! */
3065 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3068 /*******************************************************************
3069 * fill a notify_info_data with username
3070 ********************************************************************/
3072 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3074 struct spoolss_Notify *data,
3075 print_queue_struct *queue,
3076 struct spoolss_PrinterInfo2 *pinfo2,
3077 TALLOC_CTX *mem_ctx)
3079 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3082 /*******************************************************************
3083 * fill a notify_info_data with job status
3084 ********************************************************************/
3086 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3088 struct spoolss_Notify *data,
3089 print_queue_struct *queue,
3090 struct spoolss_PrinterInfo2 *pinfo2,
3091 TALLOC_CTX *mem_ctx)
3093 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3096 /*******************************************************************
3097 * fill a notify_info_data with job name
3098 ********************************************************************/
3100 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3102 struct spoolss_Notify *data,
3103 print_queue_struct *queue,
3104 struct spoolss_PrinterInfo2 *pinfo2,
3105 TALLOC_CTX *mem_ctx)
3107 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3110 /*******************************************************************
3111 * fill a notify_info_data with job status
3112 ********************************************************************/
3114 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3116 struct spoolss_Notify *data,
3117 print_queue_struct *queue,
3118 struct spoolss_PrinterInfo2 *pinfo2,
3119 TALLOC_CTX *mem_ctx)
3122 * Now we're returning job status codes we just return a "" here. JRA.
3127 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3130 switch (queue->status) {
3135 p = ""; /* NT provides the paused string */
3144 #endif /* NO LONGER NEEDED. */
3146 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3149 /*******************************************************************
3150 * fill a notify_info_data with job time
3151 ********************************************************************/
3153 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3155 struct spoolss_Notify *data,
3156 print_queue_struct *queue,
3157 struct spoolss_PrinterInfo2 *pinfo2,
3158 TALLOC_CTX *mem_ctx)
3160 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3163 /*******************************************************************
3164 * fill a notify_info_data with job size
3165 ********************************************************************/
3167 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3169 struct spoolss_Notify *data,
3170 print_queue_struct *queue,
3171 struct spoolss_PrinterInfo2 *pinfo2,
3172 TALLOC_CTX *mem_ctx)
3174 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3177 /*******************************************************************
3178 * fill a notify_info_data with page info
3179 ********************************************************************/
3180 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3182 struct spoolss_Notify *data,
3183 print_queue_struct *queue,
3184 struct spoolss_PrinterInfo2 *pinfo2,
3185 TALLOC_CTX *mem_ctx)
3187 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3190 /*******************************************************************
3191 * fill a notify_info_data with pages printed info.
3192 ********************************************************************/
3193 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3195 struct spoolss_Notify *data,
3196 print_queue_struct *queue,
3197 struct spoolss_PrinterInfo2 *pinfo2,
3198 TALLOC_CTX *mem_ctx)
3200 /* Add code when back-end tracks this */
3201 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3204 /*******************************************************************
3205 Fill a notify_info_data with job position.
3206 ********************************************************************/
3208 static void spoolss_notify_job_position(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 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3218 /*******************************************************************
3219 Fill a notify_info_data with submitted time.
3220 ********************************************************************/
3222 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3224 struct spoolss_Notify *data,
3225 print_queue_struct *queue,
3226 struct spoolss_PrinterInfo2 *pinfo2,
3227 TALLOC_CTX *mem_ctx)
3229 data->data.string.string = NULL;
3230 data->data.string.size = 0;
3232 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3233 &data->data.string.string,
3234 &data->data.string.size);
3238 struct s_notify_info_data_table
3240 enum spoolss_NotifyType type;
3243 enum spoolss_NotifyTable variable_type;
3244 void (*fn) (struct messaging_context *msg_ctx,
3245 int snum, struct spoolss_Notify *data,
3246 print_queue_struct *queue,
3247 struct spoolss_PrinterInfo2 *pinfo2,
3248 TALLOC_CTX *mem_ctx);
3251 /* A table describing the various print notification constants and
3252 whether the notification data is a pointer to a variable sized
3253 buffer, a one value uint32_t or a two value uint32_t. */
3255 static const struct s_notify_info_data_table notify_info_data_table[] =
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3273 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3274 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3275 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3276 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3277 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3278 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3279 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3280 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3281 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3282 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3296 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3297 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3298 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3299 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3300 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3301 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3302 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3303 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3304 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3305 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3308 /*******************************************************************
3309 Return the variable_type of info_data structure.
3310 ********************************************************************/
3312 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3317 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3318 if ( (notify_info_data_table[i].type == type) &&
3319 (notify_info_data_table[i].field == field) ) {
3320 return notify_info_data_table[i].variable_type;
3324 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3326 return (enum spoolss_NotifyTable) 0;
3329 /****************************************************************************
3330 ****************************************************************************/
3332 static bool search_notify(enum spoolss_NotifyType type,
3338 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3339 if (notify_info_data_table[i].type == type &&
3340 notify_info_data_table[i].field == field &&
3341 notify_info_data_table[i].fn != NULL) {
3350 /****************************************************************************
3351 ****************************************************************************/
3353 static void construct_info_data(struct spoolss_Notify *info_data,
3354 enum spoolss_NotifyType type,
3355 uint16_t field, int id)
3357 info_data->type = type;
3358 info_data->field.field = field;
3359 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3360 info_data->job_id = id;
3363 /*******************************************************************
3365 * fill a notify_info struct with info asked
3367 ********************************************************************/
3369 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3370 struct printer_handle *print_hnd,
3371 struct spoolss_NotifyInfo *info,
3372 struct spoolss_PrinterInfo2 *pinfo2,
3374 const struct spoolss_NotifyOptionType *option_type,
3376 TALLOC_CTX *mem_ctx)
3379 enum spoolss_NotifyType type;
3382 struct spoolss_Notify *current_data;
3384 type = option_type->type;
3386 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3387 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3388 option_type->count, lp_servicename(snum)));
3390 for(field_num=0; field_num < option_type->count; field_num++) {
3391 field = option_type->fields[field_num].field;
3393 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3395 if (!search_notify(type, field, &j) )
3398 info->notifies = talloc_realloc(info, info->notifies,
3399 struct spoolss_Notify,
3401 if (info->notifies == NULL) {
3402 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3406 current_data = &info->notifies[info->count];
3408 construct_info_data(current_data, type, field, id);
3410 DEBUG(10, ("construct_notify_printer_info: "
3411 "calling [%s] snum=%d printername=[%s])\n",
3412 notify_info_data_table[j].name, snum,
3413 pinfo2->printername));
3415 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3416 NULL, pinfo2, mem_ctx);
3424 /*******************************************************************
3426 * fill a notify_info struct with info asked
3428 ********************************************************************/
3430 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3431 print_queue_struct *queue,
3432 struct spoolss_NotifyInfo *info,
3433 struct spoolss_PrinterInfo2 *pinfo2,
3435 const struct spoolss_NotifyOptionType *option_type,
3437 TALLOC_CTX *mem_ctx)
3440 enum spoolss_NotifyType type;
3442 struct spoolss_Notify *current_data;
3444 DEBUG(4,("construct_notify_jobs_info\n"));
3446 type = option_type->type;
3448 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3449 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3450 option_type->count));
3452 for(field_num=0; field_num<option_type->count; field_num++) {
3453 field = option_type->fields[field_num].field;
3455 if (!search_notify(type, field, &j) )
3458 info->notifies = talloc_realloc(info, info->notifies,
3459 struct spoolss_Notify,
3461 if (info->notifies == NULL) {
3462 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3466 current_data=&(info->notifies[info->count]);
3468 construct_info_data(current_data, type, field, id);
3469 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3470 queue, pinfo2, mem_ctx);
3478 * JFM: The enumeration is not that simple, it's even non obvious.
3480 * let's take an example: I want to monitor the PRINTER SERVER for
3481 * the printer's name and the number of jobs currently queued.
3482 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3483 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3485 * I have 3 printers on the back of my server.
3487 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3490 * 1 printer 1 name 1
3491 * 2 printer 1 cjob 1
3492 * 3 printer 2 name 2
3493 * 4 printer 2 cjob 2
3494 * 5 printer 3 name 3
3495 * 6 printer 3 name 3
3497 * that's the print server case, the printer case is even worse.
3500 /*******************************************************************
3502 * enumerate all printers on the printserver
3503 * fill a notify_info struct with info asked
3505 ********************************************************************/
3507 static WERROR printserver_notify_info(struct pipes_struct *p,
3508 struct policy_handle *hnd,
3509 struct spoolss_NotifyInfo *info,
3510 TALLOC_CTX *mem_ctx)
3513 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3514 int n_services=lp_numservices();
3516 struct spoolss_NotifyOption *option;
3517 struct spoolss_NotifyOptionType option_type;
3518 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3521 DEBUG(4,("printserver_notify_info\n"));
3526 option = Printer->notify.option;
3529 info->notifies = NULL;
3532 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3533 sending a ffpcn() request first */
3538 for (i=0; i<option->count; i++) {
3539 option_type = option->types[i];
3541 if (option_type.type != PRINTER_NOTIFY_TYPE)
3544 for (snum = 0; snum < n_services; snum++) {
3545 if (!lp_browseable(snum) ||
3546 !lp_snum_ok(snum) ||
3547 !lp_print_ok(snum)) {
3548 continue; /* skip */
3551 /* Maybe we should use the SYSTEM session_info here... */
3552 result = winreg_get_printer_internal(mem_ctx,
3553 get_session_info_system(),
3555 lp_servicename(snum),
3557 if (!W_ERROR_IS_OK(result)) {
3558 DEBUG(4, ("printserver_notify_info: "
3559 "Failed to get printer [%s]\n",
3560 lp_servicename(snum)));
3565 construct_notify_printer_info(p->msg_ctx,
3571 TALLOC_FREE(pinfo2);
3577 * Debugging information, don't delete.
3580 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3581 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3582 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3584 for (i=0; i<info->count; i++) {
3585 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3586 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3587 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3594 /*******************************************************************
3596 * fill a notify_info struct with info asked
3598 ********************************************************************/
3600 static WERROR printer_notify_info(struct pipes_struct *p,
3601 struct policy_handle *hnd,
3602 struct spoolss_NotifyInfo *info,
3603 TALLOC_CTX *mem_ctx)
3606 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3609 struct spoolss_NotifyOption *option;
3610 struct spoolss_NotifyOptionType option_type;
3612 print_queue_struct *queue=NULL;
3613 print_status_struct status;
3614 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3617 DEBUG(4,("printer_notify_info\n"));
3622 option = Printer->notify.option;
3626 info->notifies = NULL;
3629 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3630 sending a ffpcn() request first */
3635 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3639 /* Maybe we should use the SYSTEM session_info here... */
3640 result = winreg_get_printer_internal(mem_ctx,
3641 get_session_info_system(),
3643 lp_servicename(snum), &pinfo2);
3644 if (!W_ERROR_IS_OK(result)) {
3649 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3650 * correct servername.
3652 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3653 if (pinfo2->servername == NULL) {
3657 for (i=0; i<option->count; i++) {
3658 option_type = option->types[i];
3660 switch (option_type.type) {
3661 case PRINTER_NOTIFY_TYPE:
3662 if (construct_notify_printer_info(p->msg_ctx,
3671 case JOB_NOTIFY_TYPE:
3673 count = print_queue_status(p->msg_ctx, snum, &queue,
3676 for (j=0; j<count; j++) {
3677 construct_notify_jobs_info(p->msg_ctx,
3691 * Debugging information, don't delete.
3694 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3695 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3696 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3698 for (i=0; i<info->count; i++) {
3699 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3700 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3701 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3705 talloc_free(pinfo2);
3709 /****************************************************************
3710 _spoolss_RouterRefreshPrinterChangeNotify
3711 ****************************************************************/
3713 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3714 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3716 struct spoolss_NotifyInfo *info;
3718 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3719 WERROR result = WERR_BADFID;
3721 /* we always have a spoolss_NotifyInfo struct */
3722 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3724 result = WERR_NOMEM;
3728 *r->out.info = info;
3731 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3732 "Invalid handle (%s:%u:%u).\n",
3733 OUR_HANDLE(r->in.handle)));
3737 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3740 * We are now using the change value, and
3741 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3742 * I don't have a global notification system, I'm sending back all the
3743 * information even when _NOTHING_ has changed.
3746 /* We need to keep track of the change value to send back in
3747 RRPCN replies otherwise our updates are ignored. */
3749 Printer->notify.fnpcn = true;
3751 if (Printer->notify.cli_chan != NULL &&
3752 Printer->notify.cli_chan->active_connections > 0) {
3753 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3754 "Saving change value in request [%x]\n",
3756 Printer->notify.change = r->in.change_low;
3759 /* just ignore the spoolss_NotifyOption */
3761 switch (Printer->printer_type) {
3763 result = printserver_notify_info(p, r->in.handle,
3767 case SPLHND_PRINTER:
3768 result = printer_notify_info(p, r->in.handle,
3773 Printer->notify.fnpcn = false;
3779 /********************************************************************
3780 ********************************************************************/
3782 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3783 const char *servername,
3784 const char *printername,
3785 const char **printername_p)
3787 /* FIXME: add lp_force_printername() */
3789 if (servername == NULL) {
3790 *printername_p = talloc_strdup(mem_ctx, printername);
3791 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3795 if (servername[0] == '\\' && servername[1] == '\\') {
3799 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3800 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3805 /********************************************************************
3806 ********************************************************************/
3808 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3809 const char *printername)
3815 dm->devicename = talloc_strndup(dm, printername,
3816 MIN(strlen(printername), 31));
3819 /********************************************************************
3820 * construct_printer_info_0
3821 * fill a printer_info_0 struct
3822 ********************************************************************/
3824 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3825 const struct auth_session_info *session_info,
3826 struct messaging_context *msg_ctx,
3827 struct spoolss_PrinterInfo2 *info2,
3828 const char *servername,
3829 struct spoolss_PrinterInfo0 *r,
3833 struct printer_session_counter *session_counter;
3834 struct timeval setuptime;
3835 print_status_struct status;
3838 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3839 if (!W_ERROR_IS_OK(result)) {
3844 r->servername = talloc_strdup(mem_ctx, servername);
3845 W_ERROR_HAVE_NO_MEMORY(r->servername);
3847 r->servername = NULL;
3850 count = print_queue_length(msg_ctx, snum, &status);
3852 /* check if we already have a counter for this printer */
3853 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3854 if (session_counter->snum == snum)
3858 /* it's the first time, add it to the list */
3859 if (session_counter == NULL) {
3860 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3861 W_ERROR_HAVE_NO_MEMORY(session_counter);
3862 session_counter->snum = snum;
3863 session_counter->counter = 0;
3864 DLIST_ADD(counter_list, session_counter);
3868 session_counter->counter++;
3874 get_startup_time(&setuptime);
3875 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3878 * the global_counter should be stored in a TDB as it's common to all the clients
3879 * and should be zeroed on samba startup
3881 r->global_counter = session_counter->counter;
3883 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3884 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3885 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3886 r->free_build = SPOOLSS_RELEASE_BUILD;
3888 r->max_spooling = 0;
3889 r->session_counter = session_counter->counter;
3890 r->num_error_out_of_paper = 0x0;
3891 r->num_error_not_ready = 0x0; /* number of print failure */
3893 r->number_of_processors = 0x1;
3894 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3895 r->high_part_total_bytes = 0x0;
3897 /* ChangeID in milliseconds*/
3898 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3899 info2->sharename, &r->change_id);
3901 r->last_error = WERR_OK;
3902 r->status = nt_printq_status(status.status);
3903 r->enumerate_network_printers = 0x0;
3904 r->c_setprinter = 0x0;
3905 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3906 r->processor_level = 0x6; /* 6 ???*/
3915 /********************************************************************
3916 * construct_printer_info1
3917 * fill a spoolss_PrinterInfo1 struct
3918 ********************************************************************/
3920 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3921 const struct spoolss_PrinterInfo2 *info2,
3923 const char *servername,
3924 struct spoolss_PrinterInfo1 *r,
3931 if (info2->comment == NULL || info2->comment[0] == '\0') {
3932 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3934 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3936 W_ERROR_HAVE_NO_MEMORY(r->comment);
3938 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3939 if (!W_ERROR_IS_OK(result)) {
3943 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3947 W_ERROR_HAVE_NO_MEMORY(r->description);
3952 /********************************************************************
3953 * construct_printer_info2
3954 * fill a spoolss_PrinterInfo2 struct
3955 ********************************************************************/
3957 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3958 struct messaging_context *msg_ctx,
3959 const struct spoolss_PrinterInfo2 *info2,
3960 const char *servername,
3961 struct spoolss_PrinterInfo2 *r,
3965 print_status_struct status;
3968 count = print_queue_length(msg_ctx, snum, &status);
3971 r->servername = talloc_strdup(mem_ctx, servername);
3972 W_ERROR_HAVE_NO_MEMORY(r->servername);
3974 r->servername = NULL;
3977 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3978 if (!W_ERROR_IS_OK(result)) {
3982 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
3983 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3984 r->portname = talloc_strdup(mem_ctx, info2->portname);
3985 W_ERROR_HAVE_NO_MEMORY(r->portname);
3986 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3987 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3989 if (info2->comment[0] == '\0') {
3990 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
3992 r->comment = talloc_strdup(mem_ctx, info2->comment);
3994 W_ERROR_HAVE_NO_MEMORY(r->comment);
3996 r->location = talloc_strdup(mem_ctx, info2->location);
3997 if (info2->location[0] == '\0') {
3998 const char *loc = NULL;
4001 nt_status = printer_list_get_printer(mem_ctx,
4006 if (NT_STATUS_IS_OK(nt_status)) {
4008 r->location = talloc_strdup(mem_ctx, loc);
4012 W_ERROR_HAVE_NO_MEMORY(r->location);
4014 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4015 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4016 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4017 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4018 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4019 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4020 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4021 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4023 r->attributes = info2->attributes;
4025 r->priority = info2->priority;
4026 r->defaultpriority = info2->defaultpriority;
4027 r->starttime = info2->starttime;
4028 r->untiltime = info2->untiltime;
4029 r->status = nt_printq_status(status.status);
4031 r->averageppm = info2->averageppm;
4033 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4035 DEBUG(8,("Returning NULL Devicemode!\n"));
4038 compose_devicemode_devicename(r->devmode, r->printername);
4042 if (info2->secdesc != NULL) {
4043 /* don't use talloc_steal() here unless you do a deep steal of all
4044 the SEC_DESC members */
4046 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4052 /********************************************************************
4053 * construct_printer_info3
4054 * fill a spoolss_PrinterInfo3 struct
4055 ********************************************************************/
4057 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4058 const struct spoolss_PrinterInfo2 *info2,
4059 const char *servername,
4060 struct spoolss_PrinterInfo3 *r,
4063 /* These are the components of the SD we are returning. */
4065 if (info2->secdesc != NULL) {
4066 /* don't use talloc_steal() here unless you do a deep steal of all
4067 the SEC_DESC members */
4069 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4070 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4076 /********************************************************************
4077 * construct_printer_info4
4078 * fill a spoolss_PrinterInfo4 struct
4079 ********************************************************************/
4081 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4082 const struct spoolss_PrinterInfo2 *info2,
4083 const char *servername,
4084 struct spoolss_PrinterInfo4 *r,
4089 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4090 if (!W_ERROR_IS_OK(result)) {
4095 r->servername = talloc_strdup(mem_ctx, servername);
4096 W_ERROR_HAVE_NO_MEMORY(r->servername);
4098 r->servername = NULL;
4101 r->attributes = info2->attributes;
4106 /********************************************************************
4107 * construct_printer_info5
4108 * fill a spoolss_PrinterInfo5 struct
4109 ********************************************************************/
4111 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4112 const struct spoolss_PrinterInfo2 *info2,
4113 const char *servername,
4114 struct spoolss_PrinterInfo5 *r,
4119 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4120 if (!W_ERROR_IS_OK(result)) {
4124 r->portname = talloc_strdup(mem_ctx, info2->portname);
4125 W_ERROR_HAVE_NO_MEMORY(r->portname);
4127 r->attributes = info2->attributes;
4129 /* these two are not used by NT+ according to MSDN */
4130 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4131 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4136 /********************************************************************
4137 * construct_printer_info_6
4138 * fill a spoolss_PrinterInfo6 struct
4139 ********************************************************************/
4141 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4142 struct messaging_context *msg_ctx,
4143 const struct spoolss_PrinterInfo2 *info2,
4144 const char *servername,
4145 struct spoolss_PrinterInfo6 *r,
4148 print_status_struct status;
4150 print_queue_length(msg_ctx, snum, &status);
4152 r->status = nt_printq_status(status.status);
4157 /********************************************************************
4158 * construct_printer_info7
4159 * fill a spoolss_PrinterInfo7 struct
4160 ********************************************************************/
4162 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4163 struct messaging_context *msg_ctx,
4164 const char *servername,
4165 struct spoolss_PrinterInfo7 *r,
4168 const struct auth_session_info *session_info = get_session_info_system();
4171 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4173 lp_servicename(snum), &guid, NULL)) {
4174 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4175 r->action = DSPRINT_PUBLISH;
4177 r->guid = talloc_strdup(mem_ctx, "");
4178 r->action = DSPRINT_UNPUBLISH;
4180 W_ERROR_HAVE_NO_MEMORY(r->guid);
4185 /********************************************************************
4186 * construct_printer_info8
4187 * fill a spoolss_PrinterInfo8 struct
4188 ********************************************************************/
4190 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4191 const struct spoolss_PrinterInfo2 *info2,
4192 const char *servername,
4193 struct spoolss_DeviceModeInfo *r,
4197 const char *printername;
4199 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4200 if (!W_ERROR_IS_OK(result)) {
4204 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4206 DEBUG(8,("Returning NULL Devicemode!\n"));
4209 compose_devicemode_devicename(r->devmode, printername);
4215 /********************************************************************
4216 ********************************************************************/
4218 static bool snum_is_shared_printer(int snum)
4220 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4223 /********************************************************************
4224 Spoolss_enumprinters.
4225 ********************************************************************/
4227 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4228 const struct auth_session_info *session_info,
4229 struct messaging_context *msg_ctx,
4230 const char *servername,
4233 union spoolss_PrinterInfo **info_p,
4237 int n_services = lp_numservices();
4238 union spoolss_PrinterInfo *info = NULL;
4240 WERROR result = WERR_OK;
4241 struct dcerpc_binding_handle *b = NULL;
4242 TALLOC_CTX *tmp_ctx = NULL;
4244 tmp_ctx = talloc_new(mem_ctx);
4252 for (snum = 0; snum < n_services; snum++) {
4254 const char *printer;
4255 struct spoolss_PrinterInfo2 *info2;
4257 if (!snum_is_shared_printer(snum)) {
4261 printer = lp_const_servicename(snum);
4263 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4267 result = winreg_printer_binding_handle(tmp_ctx,
4271 if (!W_ERROR_IS_OK(result)) {
4276 result = winreg_create_printer(tmp_ctx, b,
4278 if (!W_ERROR_IS_OK(result)) {
4282 info = talloc_realloc(tmp_ctx, info,
4283 union spoolss_PrinterInfo,
4286 result = WERR_NOMEM;
4290 result = winreg_get_printer(tmp_ctx, b,
4292 if (!W_ERROR_IS_OK(result)) {
4298 result = construct_printer_info0(info, session_info,
4301 &info[count].info0, snum);
4304 result = construct_printer_info1(info, info2, flags,
4306 &info[count].info1, snum);
4309 result = construct_printer_info2(info, msg_ctx, info2,
4311 &info[count].info2, snum);
4314 result = construct_printer_info4(info, info2,
4316 &info[count].info4, snum);
4319 result = construct_printer_info5(info, info2,
4321 &info[count].info5, snum);
4325 result = WERR_UNKNOWN_LEVEL;
4329 if (!W_ERROR_IS_OK(result)) {
4337 if (W_ERROR_IS_OK(result)) {
4338 *info_p = talloc_move(mem_ctx, &info);
4342 talloc_free(tmp_ctx);
4347 /********************************************************************
4348 * handle enumeration of printers at level 0
4349 ********************************************************************/
4351 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4352 const struct auth_session_info *session_info,
4353 struct messaging_context *msg_ctx,
4355 const char *servername,
4356 union spoolss_PrinterInfo **info,
4359 DEBUG(4,("enum_all_printers_info_0\n"));
4361 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4362 servername, 0, flags, info, count);
4366 /********************************************************************
4367 ********************************************************************/
4369 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4370 const struct auth_session_info *session_info,
4371 struct messaging_context *msg_ctx,
4372 const char *servername,
4374 union spoolss_PrinterInfo **info,
4377 DEBUG(4,("enum_all_printers_info_1\n"));
4379 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4380 servername, 1, flags, info, count);
4383 /********************************************************************
4384 enum_all_printers_info_1_local.
4385 *********************************************************************/
4387 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4388 const struct auth_session_info *session_info,
4389 struct messaging_context *msg_ctx,
4390 const char *servername,
4391 union spoolss_PrinterInfo **info,
4394 DEBUG(4,("enum_all_printers_info_1_local\n"));
4396 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4397 servername, PRINTER_ENUM_ICON8, info, count);
4400 /********************************************************************
4401 enum_all_printers_info_1_name.
4402 *********************************************************************/
4404 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4405 const struct auth_session_info *session_info,
4406 struct messaging_context *msg_ctx,
4407 const char *servername,
4408 union spoolss_PrinterInfo **info,
4411 const char *s = servername;
4413 DEBUG(4,("enum_all_printers_info_1_name\n"));
4415 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4419 if (!is_myname_or_ipaddr(s)) {
4420 return WERR_INVALID_NAME;
4423 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4424 servername, PRINTER_ENUM_ICON8, info, count);
4427 /********************************************************************
4428 enum_all_printers_info_1_network.
4429 *********************************************************************/
4431 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4432 const struct auth_session_info *session_info,
4433 struct messaging_context *msg_ctx,
4434 const char *servername,
4435 union spoolss_PrinterInfo **info,
4438 const char *s = servername;
4440 DEBUG(4,("enum_all_printers_info_1_network\n"));
4442 /* If we respond to a enum_printers level 1 on our name with flags
4443 set to PRINTER_ENUM_REMOTE with a list of printers then these
4444 printers incorrectly appear in the APW browse list.
4445 Specifically the printers for the server appear at the workgroup
4446 level where all the other servers in the domain are
4447 listed. Windows responds to this call with a
4448 WERR_CAN_NOT_COMPLETE so we should do the same. */
4450 if (servername[0] == '\\' && servername[1] == '\\') {
4454 if (is_myname_or_ipaddr(s)) {
4455 return WERR_CAN_NOT_COMPLETE;
4458 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4459 servername, PRINTER_ENUM_NAME, info, count);
4462 /********************************************************************
4463 * api_spoolss_enumprinters
4465 * called from api_spoolss_enumprinters (see this to understand)
4466 ********************************************************************/
4468 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4469 const struct auth_session_info *session_info,
4470 struct messaging_context *msg_ctx,
4471 const char *servername,
4472 union spoolss_PrinterInfo **info,
4475 DEBUG(4,("enum_all_printers_info_2\n"));
4477 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4478 servername, 2, 0, info, count);
4481 /********************************************************************
4482 * handle enumeration of printers at level 1
4483 ********************************************************************/
4485 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4486 const struct auth_session_info *session_info,
4487 struct messaging_context *msg_ctx,
4489 const char *servername,
4490 union spoolss_PrinterInfo **info,
4493 /* Not all the flags are equals */
4495 if (flags & PRINTER_ENUM_LOCAL) {
4496 return enum_all_printers_info_1_local(mem_ctx, session_info,
4497 msg_ctx, servername, info, count);
4500 if (flags & PRINTER_ENUM_NAME) {
4501 return enum_all_printers_info_1_name(mem_ctx, session_info,
4502 msg_ctx, servername, info,
4506 if (flags & PRINTER_ENUM_NETWORK) {
4507 return enum_all_printers_info_1_network(mem_ctx, session_info,
4508 msg_ctx, servername, info,
4512 return WERR_OK; /* NT4sp5 does that */
4515 /********************************************************************
4516 * handle enumeration of printers at level 2
4517 ********************************************************************/
4519 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4520 const struct auth_session_info *session_info,
4521 struct messaging_context *msg_ctx,
4523 const char *servername,
4524 union spoolss_PrinterInfo **info,
4527 if (flags & PRINTER_ENUM_LOCAL) {
4529 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4534 if (flags & PRINTER_ENUM_NAME) {
4535 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4536 return WERR_INVALID_NAME;
4539 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4544 if (flags & PRINTER_ENUM_REMOTE) {
4545 return WERR_UNKNOWN_LEVEL;
4551 /********************************************************************
4552 * handle enumeration of printers at level 4
4553 ********************************************************************/
4555 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4556 const struct auth_session_info *session_info,
4557 struct messaging_context *msg_ctx,
4559 const char *servername,
4560 union spoolss_PrinterInfo **info,
4563 DEBUG(4,("enum_all_printers_info_4\n"));
4565 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4566 servername, 4, flags, info, count);
4570 /********************************************************************
4571 * handle enumeration of printers at level 5
4572 ********************************************************************/
4574 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4575 const struct auth_session_info *session_info,
4576 struct messaging_context *msg_ctx,
4578 const char *servername,
4579 union spoolss_PrinterInfo **info,
4582 DEBUG(4,("enum_all_printers_info_5\n"));
4584 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4585 servername, 5, flags, info, count);
4588 /****************************************************************
4589 _spoolss_EnumPrinters
4590 ****************************************************************/
4592 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4593 struct spoolss_EnumPrinters *r)
4595 const struct auth_session_info *session_info = get_session_info_system();
4598 /* that's an [in out] buffer */
4600 if (!r->in.buffer && (r->in.offered != 0)) {
4601 return WERR_INVALID_PARAM;
4604 DEBUG(4,("_spoolss_EnumPrinters\n"));
4608 *r->out.info = NULL;
4612 * flags==PRINTER_ENUM_NAME
4613 * if name=="" then enumerates all printers
4614 * if name!="" then enumerate the printer
4615 * flags==PRINTER_ENUM_REMOTE
4616 * name is NULL, enumerate printers
4617 * Level 2: name!="" enumerates printers, name can't be NULL
4618 * Level 3: doesn't exist
4619 * Level 4: does a local registry lookup
4620 * Level 5: same as Level 2
4623 if (r->in.server && r->in.server[0] == '\0') {
4624 r->in.server = NULL;
4627 switch (r->in.level) {
4629 result = enumprinters_level0(p->mem_ctx, session_info,
4630 p->msg_ctx, r->in.flags,
4632 r->out.info, r->out.count);
4635 result = enumprinters_level1(p->mem_ctx, session_info,
4636 p->msg_ctx, r->in.flags,
4638 r->out.info, r->out.count);
4641 result = enumprinters_level2(p->mem_ctx, session_info,
4642 p->msg_ctx, r->in.flags,
4644 r->out.info, r->out.count);
4647 result = enumprinters_level4(p->mem_ctx, session_info,
4648 p->msg_ctx, r->in.flags,
4650 r->out.info, r->out.count);
4653 result = enumprinters_level5(p->mem_ctx, session_info,
4654 p->msg_ctx, r->in.flags,
4656 r->out.info, r->out.count);
4659 return WERR_UNKNOWN_LEVEL;
4662 if (!W_ERROR_IS_OK(result)) {
4666 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4667 spoolss_EnumPrinters,
4668 *r->out.info, r->in.level,
4670 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4671 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4673 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4676 /****************************************************************
4678 ****************************************************************/
4680 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4681 struct spoolss_GetPrinter *r)
4683 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4684 struct spoolss_PrinterInfo2 *info2 = NULL;
4685 WERROR result = WERR_OK;
4688 /* that's an [in out] buffer */
4690 if (!r->in.buffer && (r->in.offered != 0)) {
4691 return WERR_INVALID_PARAM;
4696 if (Printer == NULL) {
4700 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4704 result = winreg_get_printer_internal(p->mem_ctx,
4705 get_session_info_system(),
4707 lp_const_servicename(snum),
4709 if (!W_ERROR_IS_OK(result)) {
4713 switch (r->in.level) {
4715 result = construct_printer_info0(p->mem_ctx,
4716 get_session_info_system(),
4719 Printer->servername,
4720 &r->out.info->info0,
4724 result = construct_printer_info1(p->mem_ctx, info2,
4726 Printer->servername,
4727 &r->out.info->info1, snum);
4730 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4731 Printer->servername,
4732 &r->out.info->info2, snum);
4735 result = construct_printer_info3(p->mem_ctx, info2,
4736 Printer->servername,
4737 &r->out.info->info3, snum);
4740 result = construct_printer_info4(p->mem_ctx, info2,
4741 Printer->servername,
4742 &r->out.info->info4, snum);
4745 result = construct_printer_info5(p->mem_ctx, info2,
4746 Printer->servername,
4747 &r->out.info->info5, snum);
4750 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4751 Printer->servername,
4752 &r->out.info->info6, snum);
4755 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4756 Printer->servername,
4757 &r->out.info->info7, snum);
4760 result = construct_printer_info8(p->mem_ctx, info2,
4761 Printer->servername,
4762 &r->out.info->info8, snum);
4765 result = WERR_UNKNOWN_LEVEL;
4771 if (!W_ERROR_IS_OK(result)) {
4772 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4773 r->in.level, win_errstr(result)));
4774 TALLOC_FREE(r->out.info);
4778 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4779 r->out.info, r->in.level);
4780 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4782 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4785 /********************************************************************
4786 ********************************************************************/
4788 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4790 if (in && strlen(in)) { \
4791 out = talloc_strdup(mem_ctx, in); \
4793 out = talloc_strdup(mem_ctx, ""); \
4795 W_ERROR_HAVE_NO_MEMORY(out); \
4798 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4800 if (in && strlen(in)) { \
4801 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4803 out = talloc_strdup(mem_ctx, ""); \
4805 W_ERROR_HAVE_NO_MEMORY(out); \
4808 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4809 const char **string_array,
4810 const char ***presult,
4811 const char *cservername,
4815 int i, num_strings = 0;
4816 const char **array = NULL;
4818 if (string_array == NULL) {
4819 return WERR_INVALID_PARAMETER;
4822 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4823 const char *str = NULL;
4825 if (cservername == NULL || arch == NULL) {
4826 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4828 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4831 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4838 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4839 &array, &num_strings);
4849 /********************************************************************
4850 * fill a spoolss_DriverInfo1 struct
4851 ********************************************************************/
4853 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4854 struct spoolss_DriverInfo1 *r,
4855 const struct spoolss_DriverInfo8 *driver,
4856 const char *servername)
4858 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4859 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4864 /********************************************************************
4865 * fill a spoolss_DriverInfo2 struct
4866 ********************************************************************/
4868 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4869 struct spoolss_DriverInfo2 *r,
4870 const struct spoolss_DriverInfo8 *driver,
4871 const char *servername)
4874 const char *cservername = canon_servername(servername);
4876 r->version = driver->version;
4878 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4879 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4880 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4881 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4883 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4884 driver->architecture,
4886 driver->driver_path,
4889 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4890 driver->architecture,
4895 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4896 driver->architecture,
4898 driver->config_file,
4904 /********************************************************************
4905 * fill a spoolss_DriverInfo3 struct
4906 ********************************************************************/
4908 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4909 struct spoolss_DriverInfo3 *r,
4910 const struct spoolss_DriverInfo8 *driver,
4911 const char *servername)
4913 const char *cservername = canon_servername(servername);
4915 r->version = driver->version;
4917 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4918 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4919 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4920 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4922 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4923 driver->architecture,
4925 driver->driver_path,
4928 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4929 driver->architecture,
4934 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4935 driver->architecture,
4937 driver->config_file,
4940 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4941 driver->architecture,
4946 FILL_DRIVER_STRING(mem_ctx,
4947 driver->monitor_name,
4950 FILL_DRIVER_STRING(mem_ctx,
4951 driver->default_datatype,
4952 r->default_datatype);
4954 return string_array_from_driver_info(mem_ctx,
4955 driver->dependent_files,
4956 &r->dependent_files,
4958 driver->architecture,
4962 /********************************************************************
4963 * fill a spoolss_DriverInfo4 struct
4964 ********************************************************************/
4966 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4967 struct spoolss_DriverInfo4 *r,
4968 const struct spoolss_DriverInfo8 *driver,
4969 const char *servername)
4971 const char *cservername = canon_servername(servername);
4974 r->version = driver->version;
4976 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4977 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4978 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4979 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4981 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4982 driver->architecture,
4984 driver->driver_path,
4987 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4988 driver->architecture,
4993 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4994 driver->architecture,
4996 driver->config_file,
4999 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5000 driver->architecture,
5005 result = string_array_from_driver_info(mem_ctx,
5006 driver->dependent_files,
5007 &r->dependent_files,
5009 driver->architecture,
5011 if (!W_ERROR_IS_OK(result)) {
5015 FILL_DRIVER_STRING(mem_ctx,
5016 driver->monitor_name,
5019 FILL_DRIVER_STRING(mem_ctx,
5020 driver->default_datatype,
5021 r->default_datatype);
5024 result = string_array_from_driver_info(mem_ctx,
5025 driver->previous_names,
5032 /********************************************************************
5033 * fill a spoolss_DriverInfo5 struct
5034 ********************************************************************/
5036 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5037 struct spoolss_DriverInfo5 *r,
5038 const struct spoolss_DriverInfo8 *driver,
5039 const char *servername)
5041 const char *cservername = canon_servername(servername);
5043 r->version = driver->version;
5045 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5046 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5047 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5048 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5050 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5051 driver->architecture,
5053 driver->driver_path,
5056 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5057 driver->architecture,
5062 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5063 driver->architecture,
5065 driver->config_file,
5068 r->driver_attributes = 0;
5069 r->config_version = 0;
5070 r->driver_version = 0;
5074 /********************************************************************
5075 * fill a spoolss_DriverInfo6 struct
5076 ********************************************************************/
5078 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5079 struct spoolss_DriverInfo6 *r,
5080 const struct spoolss_DriverInfo8 *driver,
5081 const char *servername)
5083 const char *cservername = canon_servername(servername);
5086 r->version = driver->version;
5088 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5089 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5090 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5091 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5093 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5094 driver->architecture,
5096 driver->driver_path,
5099 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5100 driver->architecture,
5105 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5106 driver->architecture,
5108 driver->config_file,
5111 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5112 driver->architecture,
5117 FILL_DRIVER_STRING(mem_ctx,
5118 driver->monitor_name,
5121 FILL_DRIVER_STRING(mem_ctx,
5122 driver->default_datatype,
5123 r->default_datatype);
5125 result = string_array_from_driver_info(mem_ctx,
5126 driver->dependent_files,
5127 &r->dependent_files,
5129 driver->architecture,
5131 if (!W_ERROR_IS_OK(result)) {
5135 result = string_array_from_driver_info(mem_ctx,
5136 driver->previous_names,
5139 if (!W_ERROR_IS_OK(result)) {
5143 r->driver_date = driver->driver_date;
5144 r->driver_version = driver->driver_version;
5146 FILL_DRIVER_STRING(mem_ctx,
5147 driver->manufacturer_name,
5148 r->manufacturer_name);
5149 FILL_DRIVER_STRING(mem_ctx,
5150 driver->manufacturer_url,
5151 r->manufacturer_url);
5152 FILL_DRIVER_STRING(mem_ctx,
5153 driver->hardware_id,
5155 FILL_DRIVER_STRING(mem_ctx,
5162 /********************************************************************
5163 * fill a spoolss_DriverInfo8 struct
5164 ********************************************************************/
5166 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5167 struct spoolss_DriverInfo8 *r,
5168 const struct spoolss_DriverInfo8 *driver,
5169 const char *servername)
5171 const char *cservername = canon_servername(servername);
5174 r->version = driver->version;
5176 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5177 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5178 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5179 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5181 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5182 driver->architecture,
5184 driver->driver_path,
5187 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5188 driver->architecture,
5193 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5194 driver->architecture,
5196 driver->config_file,
5199 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5200 driver->architecture,
5205 FILL_DRIVER_STRING(mem_ctx,
5206 driver->monitor_name,
5209 FILL_DRIVER_STRING(mem_ctx,
5210 driver->default_datatype,
5211 r->default_datatype);
5213 result = string_array_from_driver_info(mem_ctx,
5214 driver->dependent_files,
5215 &r->dependent_files,
5217 driver->architecture,
5219 if (!W_ERROR_IS_OK(result)) {
5223 result = string_array_from_driver_info(mem_ctx,
5224 driver->previous_names,
5227 if (!W_ERROR_IS_OK(result)) {
5231 r->driver_date = driver->driver_date;
5232 r->driver_version = driver->driver_version;
5234 FILL_DRIVER_STRING(mem_ctx,
5235 driver->manufacturer_name,
5236 r->manufacturer_name);
5237 FILL_DRIVER_STRING(mem_ctx,
5238 driver->manufacturer_url,
5239 r->manufacturer_url);
5240 FILL_DRIVER_STRING(mem_ctx,
5241 driver->hardware_id,
5243 FILL_DRIVER_STRING(mem_ctx,
5247 FILL_DRIVER_STRING(mem_ctx,
5248 driver->print_processor,
5249 r->print_processor);
5250 FILL_DRIVER_STRING(mem_ctx,
5251 driver->vendor_setup,
5254 result = string_array_from_driver_info(mem_ctx,
5255 driver->color_profiles,
5258 if (!W_ERROR_IS_OK(result)) {
5262 FILL_DRIVER_STRING(mem_ctx,
5266 r->printer_driver_attributes = driver->printer_driver_attributes;
5268 result = string_array_from_driver_info(mem_ctx,
5269 driver->core_driver_dependencies,
5270 &r->core_driver_dependencies,
5272 if (!W_ERROR_IS_OK(result)) {
5276 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5277 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5282 #if 0 /* disabled until marshalling issues are resolved - gd */
5283 /********************************************************************
5284 ********************************************************************/
5286 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5287 struct spoolss_DriverFileInfo *r,
5288 const char *cservername,
5289 const char *file_name,
5290 enum spoolss_DriverFileType file_type,
5291 uint32_t file_version)
5293 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5294 cservername, file_name);
5295 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5296 r->file_type = file_type;
5297 r->file_version = file_version;
5302 /********************************************************************
5303 ********************************************************************/
5305 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5306 const struct spoolss_DriverInfo8 *driver,
5307 const char *cservername,
5308 struct spoolss_DriverFileInfo **info_p,
5311 struct spoolss_DriverFileInfo *info = NULL;
5319 if (strlen(driver->driver_path)) {
5320 info = talloc_realloc(mem_ctx, info,
5321 struct spoolss_DriverFileInfo,
5323 W_ERROR_HAVE_NO_MEMORY(info);
5324 result = fill_spoolss_DriverFileInfo(info,
5327 driver->driver_path,
5328 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5330 W_ERROR_NOT_OK_RETURN(result);
5334 if (strlen(driver->config_file)) {
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->config_file,
5343 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5345 W_ERROR_NOT_OK_RETURN(result);
5349 if (strlen(driver->data_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,
5358 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5360 W_ERROR_NOT_OK_RETURN(result);
5364 if (strlen(driver->help_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_HELP,
5375 W_ERROR_NOT_OK_RETURN(result);
5379 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5380 info = talloc_realloc(mem_ctx, info,
5381 struct spoolss_DriverFileInfo,
5383 W_ERROR_HAVE_NO_MEMORY(info);
5384 result = fill_spoolss_DriverFileInfo(info,
5387 driver->dependent_files[i],
5388 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5390 W_ERROR_NOT_OK_RETURN(result);
5400 /********************************************************************
5401 * fill a spoolss_DriverInfo101 struct
5402 ********************************************************************/
5404 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5405 struct spoolss_DriverInfo101 *r,
5406 const struct spoolss_DriverInfo8 *driver,
5407 const char *servername)
5409 const char *cservername = canon_servername(servername);
5412 r->version = driver->version;
5414 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5415 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5416 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5417 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5419 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5423 if (!W_ERROR_IS_OK(result)) {
5427 FILL_DRIVER_STRING(mem_ctx,
5428 driver->monitor_name,
5431 FILL_DRIVER_STRING(mem_ctx,
5432 driver->default_datatype,
5433 r->default_datatype);
5435 result = string_array_from_driver_info(mem_ctx,
5436 driver->previous_names,
5439 if (!W_ERROR_IS_OK(result)) {
5443 r->driver_date = driver->driver_date;
5444 r->driver_version = driver->driver_version;
5446 FILL_DRIVER_STRING(mem_ctx,
5447 driver->manufacturer_name,
5448 r->manufacturer_name);
5449 FILL_DRIVER_STRING(mem_ctx,
5450 driver->manufacturer_url,
5451 r->manufacturer_url);
5452 FILL_DRIVER_STRING(mem_ctx,
5453 driver->hardware_id,
5455 FILL_DRIVER_STRING(mem_ctx,
5462 /********************************************************************
5463 ********************************************************************/
5465 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5466 const struct auth_session_info *session_info,
5467 struct messaging_context *msg_ctx,
5469 union spoolss_DriverInfo *r,
5471 const char *servername,
5472 const char *architecture,
5475 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5476 struct spoolss_DriverInfo8 *driver;
5478 struct dcerpc_binding_handle *b;
5479 TALLOC_CTX *tmp_ctx = NULL;
5482 return WERR_UNKNOWN_LEVEL;
5485 tmp_ctx = talloc_new(mem_ctx);
5490 result = winreg_printer_binding_handle(tmp_ctx,
5494 if (!W_ERROR_IS_OK(result)) {
5498 result = winreg_get_printer(tmp_ctx, b,
5499 lp_const_servicename(snum),
5502 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5503 win_errstr(result)));
5505 if (!W_ERROR_IS_OK(result)) {
5506 result = WERR_INVALID_PRINTER_NAME;
5510 result = winreg_get_driver(tmp_ctx, b,
5512 pinfo2->drivername, version, &driver);
5514 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5515 win_errstr(result)));
5517 if (!W_ERROR_IS_OK(result)) {
5519 * Is this a W2k client ?
5523 result = WERR_UNKNOWN_PRINTER_DRIVER;
5527 /* Yes - try again with a WinNT driver. */
5529 result = winreg_get_driver(tmp_ctx, b,
5533 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5534 win_errstr(result)));
5535 if (!W_ERROR_IS_OK(result)) {
5536 result = WERR_UNKNOWN_PRINTER_DRIVER;
5541 /* these are allocated on mem_ctx and not tmp_ctx because they are
5542 * the 'return value' and need to utlive this call */
5545 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5548 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5551 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5554 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5557 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5560 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5563 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5565 #if 0 /* disabled until marshalling issues are resolved - gd */
5567 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5571 result = WERR_UNKNOWN_LEVEL;
5576 talloc_free(tmp_ctx);
5580 /****************************************************************
5581 _spoolss_GetPrinterDriver2
5582 ****************************************************************/
5584 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5585 struct spoolss_GetPrinterDriver2 *r)
5587 struct printer_handle *printer;
5592 /* that's an [in out] buffer */
5594 if (!r->in.buffer && (r->in.offered != 0)) {
5595 return WERR_INVALID_PARAM;
5598 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5600 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5601 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5602 return WERR_INVALID_PRINTER_NAME;
5606 *r->out.server_major_version = 0;
5607 *r->out.server_minor_version = 0;
5609 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5613 result = construct_printer_driver_info_level(p->mem_ctx,
5614 get_session_info_system(),
5616 r->in.level, r->out.info,
5617 snum, printer->servername,
5619 r->in.client_major_version);
5620 if (!W_ERROR_IS_OK(result)) {
5621 TALLOC_FREE(r->out.info);
5625 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5626 r->out.info, r->in.level);
5627 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5629 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5633 /****************************************************************
5634 _spoolss_StartPagePrinter
5635 ****************************************************************/
5637 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5638 struct spoolss_StartPagePrinter *r)
5640 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5643 DEBUG(3,("_spoolss_StartPagePrinter: "
5644 "Error in startpageprinter printer handle\n"));
5648 Printer->page_started = true;
5652 /****************************************************************
5653 _spoolss_EndPagePrinter
5654 ****************************************************************/
5656 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5657 struct spoolss_EndPagePrinter *r)
5661 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5664 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5665 OUR_HANDLE(r->in.handle)));
5669 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5672 Printer->page_started = false;
5673 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5678 /****************************************************************
5679 _spoolss_StartDocPrinter
5680 ****************************************************************/
5682 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5683 struct spoolss_StartDocPrinter *r)
5685 struct spoolss_DocumentInfo1 *info_1;
5687 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5693 DEBUG(2,("_spoolss_StartDocPrinter: "
5694 "Invalid handle (%s:%u:%u)\n",
5695 OUR_HANDLE(r->in.handle)));
5699 if (Printer->jobid) {
5700 DEBUG(2, ("_spoolss_StartDocPrinter: "
5701 "StartDocPrinter called twice! "
5702 "(existing jobid = %d)\n", Printer->jobid));
5703 return WERR_INVALID_HANDLE;
5706 if (r->in.level != 1) {
5707 return WERR_UNKNOWN_LEVEL;
5710 info_1 = r->in.info.info1;
5713 * a nice thing with NT is it doesn't listen to what you tell it.
5714 * when asked to send _only_ RAW datas, it tries to send datas
5717 * So I add checks like in NT Server ...
5720 if (info_1->datatype) {
5721 if (strcmp(info_1->datatype, "RAW") != 0) {
5723 return WERR_INVALID_DATATYPE;
5727 /* get the share number of the printer */
5728 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5732 rc = get_remote_hostname(p->remote_address,
5738 if (strequal(rhost,"UNKNOWN")) {
5739 rhost = tsocket_address_inet_addr_string(p->remote_address,
5741 if (rhost == NULL) {
5746 werr = print_job_start(p->session_info,
5750 info_1->document_name,
5751 info_1->output_file,
5755 /* An error occured in print_job_start() so return an appropriate
5758 if (!W_ERROR_IS_OK(werr)) {
5762 Printer->document_started = true;
5763 *r->out.job_id = Printer->jobid;
5768 /****************************************************************
5769 _spoolss_EndDocPrinter
5770 ****************************************************************/
5772 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5773 struct spoolss_EndDocPrinter *r)
5775 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5780 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5781 OUR_HANDLE(r->in.handle)));
5785 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5789 Printer->document_started = false;
5790 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5791 if (!NT_STATUS_IS_OK(status)) {
5792 DEBUG(2, ("_spoolss_EndDocPrinter: "
5793 "print_job_end failed [%s]\n",
5794 nt_errstr(status)));
5798 return ntstatus_to_werror(status);
5801 /****************************************************************
5802 _spoolss_WritePrinter
5803 ****************************************************************/
5805 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5806 struct spoolss_WritePrinter *r)
5808 ssize_t buffer_written;
5810 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5813 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5814 OUR_HANDLE(r->in.handle)));
5815 *r->out.num_written = r->in._data_size;
5819 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5822 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5823 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5824 snum, Printer->jobid,
5825 (const char *)r->in.data.data,
5826 (size_t)r->in._data_size);
5827 if (buffer_written == (ssize_t)-1) {
5828 *r->out.num_written = 0;
5829 if (errno == ENOSPC)
5830 return WERR_NO_SPOOL_SPACE;
5832 return WERR_ACCESS_DENIED;
5835 *r->out.num_written = r->in._data_size;
5840 /********************************************************************
5841 * api_spoolss_getprinter
5842 * called from the spoolss dispatcher
5844 ********************************************************************/
5846 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5847 struct pipes_struct *p)
5849 const struct auth_session_info *session_info = p->session_info;
5851 WERROR errcode = WERR_BADFUNC;
5852 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5855 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5856 OUR_HANDLE(handle)));
5860 if (!get_printer_snum(p, handle, &snum, NULL))
5864 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5865 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5867 case SPOOLSS_PRINTER_CONTROL_RESUME:
5868 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5869 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5871 case SPOOLSS_PRINTER_CONTROL_PURGE:
5872 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5875 return WERR_UNKNOWN_LEVEL;
5882 /****************************************************************
5883 _spoolss_AbortPrinter
5884 * From MSDN: "Deletes printer's spool file if printer is configured
5886 ****************************************************************/
5888 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5889 struct spoolss_AbortPrinter *r)
5891 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5893 WERROR errcode = WERR_OK;
5896 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5897 OUR_HANDLE(r->in.handle)));
5901 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5904 if (!Printer->document_started) {
5905 return WERR_SPL_NO_STARTDOC;
5908 errcode = print_job_delete(p->session_info,
5916 /********************************************************************
5917 * called by spoolss_api_setprinter
5918 * when updating a printer description
5919 ********************************************************************/
5921 static WERROR update_printer_sec(struct policy_handle *handle,
5922 struct pipes_struct *p,
5923 struct sec_desc_buf *secdesc_ctr)
5925 struct spoolss_security_descriptor *new_secdesc = NULL;
5926 struct spoolss_security_descriptor *old_secdesc = NULL;
5927 const char *printer;
5930 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5931 struct dcerpc_binding_handle *b;
5932 TALLOC_CTX *tmp_ctx = NULL;
5934 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5935 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5936 OUR_HANDLE(handle)));
5938 result = WERR_BADFID;
5942 if (secdesc_ctr == NULL) {
5943 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5944 result = WERR_INVALID_PARAM;
5947 printer = lp_const_servicename(snum);
5949 /* Check the user has permissions to change the security
5950 descriptor. By experimentation with two NT machines, the user
5951 requires Full Access to the printer to change security
5954 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5955 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5956 result = WERR_ACCESS_DENIED;
5960 tmp_ctx = talloc_new(p->mem_ctx);
5965 result = winreg_printer_binding_handle(tmp_ctx,
5966 get_session_info_system(),
5969 if (!W_ERROR_IS_OK(result)) {
5973 /* NT seems to like setting the security descriptor even though
5974 nothing may have actually changed. */
5975 result = winreg_get_printer_secdesc(tmp_ctx, b,
5978 if (!W_ERROR_IS_OK(result)) {
5979 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5980 result = WERR_BADFID;
5984 if (DEBUGLEVEL >= 10) {
5985 struct security_acl *the_acl;
5988 the_acl = old_secdesc->dacl;
5989 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
5990 printer, the_acl->num_aces));
5992 for (i = 0; i < the_acl->num_aces; i++) {
5993 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
5994 &the_acl->aces[i].trustee),
5995 the_acl->aces[i].access_mask));
5998 the_acl = secdesc_ctr->sd->dacl;
6001 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6002 printer, the_acl->num_aces));
6004 for (i = 0; i < the_acl->num_aces; i++) {
6005 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6006 &the_acl->aces[i].trustee),
6007 the_acl->aces[i].access_mask));
6010 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6014 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6015 if (new_secdesc == NULL) {
6016 result = WERR_NOMEM;
6020 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6025 result = winreg_set_printer_secdesc(tmp_ctx, b,
6030 talloc_free(tmp_ctx);
6034 /********************************************************************
6035 Canonicalize printer info from a client
6036 ********************************************************************/
6038 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6039 struct spoolss_SetPrinterInfo2 *info2,
6042 fstring printername;
6045 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6046 "portname=%s drivername=%s comment=%s location=%s\n",
6047 info2->servername, info2->printername, info2->sharename,
6048 info2->portname, info2->drivername, info2->comment,
6051 /* we force some elements to "correct" values */
6052 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6053 if (info2->servername == NULL) {
6056 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6057 if (info2->sharename == NULL) {
6061 /* check to see if we allow printername != sharename */
6062 if (lp_force_printername(snum)) {
6063 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6064 lp_netbios_name(), info2->sharename);
6066 /* make sure printername is in \\server\printername format */
6067 fstrcpy(printername, info2->printername);
6069 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6070 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6074 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6075 lp_netbios_name(), p);
6077 if (info2->printername == NULL) {
6081 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6082 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6087 /****************************************************************************
6088 ****************************************************************************/
6090 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6092 char *cmd = lp_addport_cmd();
6093 char *command = NULL;
6095 bool is_print_op = false;
6098 return WERR_ACCESS_DENIED;
6101 command = talloc_asprintf(ctx,
6102 "%s \"%s\" \"%s\"", cmd, portname, uri );
6108 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6110 DEBUG(10,("Running [%s]\n", command));
6112 /********* BEGIN SePrintOperatorPrivilege **********/
6117 ret = smbrun(command, NULL);
6122 /********* END SePrintOperatorPrivilege **********/
6124 DEBUGADD(10,("returned [%d]\n", ret));
6126 TALLOC_FREE(command);
6129 return WERR_ACCESS_DENIED;
6135 /****************************************************************************
6136 ****************************************************************************/
6138 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6142 * As we do not know if we are embedded in the file server process
6143 * or not, we have to pretend that all shares are in use.
6148 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6149 struct spoolss_SetPrinterInfo2 *info2,
6150 const char *remote_machine,
6151 struct messaging_context *msg_ctx)
6153 char *cmd = lp_addprinter_cmd();
6155 char *command = NULL;
6159 bool is_print_op = false;
6161 if (!remote_machine) {
6165 command = talloc_asprintf(ctx,
6166 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6167 cmd, info2->printername, info2->sharename,
6168 info2->portname, info2->drivername,
6169 info2->location, info2->comment, remote_machine);
6175 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6177 DEBUG(10,("Running [%s]\n", command));
6179 /********* BEGIN SePrintOperatorPrivilege **********/
6184 if ( (ret = smbrun(command, &fd)) == 0 ) {
6185 /* Tell everyone we updated smb.conf. */
6186 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6192 /********* END SePrintOperatorPrivilege **********/
6194 DEBUGADD(10,("returned [%d]\n", ret));
6196 TALLOC_FREE(command);
6204 /* reload our services immediately */
6206 reload_services(NULL, spoolss_conn_snum_used, false);
6210 /* Get lines and convert them back to dos-codepage */
6211 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6212 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6215 /* Set the portname to what the script says the portname should be. */
6216 /* but don't require anything to be return from the script exit a good error code */
6219 /* Set the portname to what the script says the portname should be. */
6220 info2->portname = talloc_strdup(ctx, qlines[0]);
6221 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6224 TALLOC_FREE(qlines);
6228 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6229 const struct auth_session_info *session_info,
6230 struct messaging_context *msg_ctx,
6232 struct spoolss_SetPrinterInfo2 *printer,
6233 struct spoolss_PrinterInfo2 *old_printer)
6235 bool force_update = (old_printer == NULL);
6236 const char *dnsdomname;
6237 const char *longname;
6238 const char *uncname;
6239 const char *spooling;
6241 WERROR result = WERR_OK;
6242 struct dcerpc_binding_handle *b;
6243 TALLOC_CTX *tmp_ctx;
6246 tmp_ctx = talloc_new(mem_ctx);
6251 result = winreg_printer_binding_handle(tmp_ctx,
6255 if (!W_ERROR_IS_OK(result)) {
6259 if (printer->drivername != NULL &&
6261 !strequal(printer->drivername, old_printer->drivername))) {
6262 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6264 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6265 result = WERR_INVALID_DATA;
6268 result = winreg_set_printer_dataex(tmp_ctx, b,
6270 SPOOL_DSSPOOLER_KEY,
6271 SPOOL_REG_DRIVERNAME,
6275 if (!W_ERROR_IS_OK(result)) {
6276 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6280 if (!force_update) {
6281 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6282 printer->drivername));
6284 notify_printer_driver(server_event_context(), msg_ctx,
6285 snum, printer->drivername ?
6286 printer->drivername : "");
6290 if (printer->comment != NULL &&
6292 !strequal(printer->comment, old_printer->comment))) {
6293 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6295 DEBUG(0, ("comment data corrupted\n"));
6296 result = WERR_INVALID_DATA;
6299 result = winreg_set_printer_dataex(tmp_ctx, b,
6301 SPOOL_DSSPOOLER_KEY,
6302 SPOOL_REG_DESCRIPTION,
6306 if (!W_ERROR_IS_OK(result)) {
6307 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6311 if (!force_update) {
6312 notify_printer_comment(server_event_context(), msg_ctx,
6313 snum, printer->comment ?
6314 printer->comment : "");
6318 if (printer->sharename != NULL &&
6320 !strequal(printer->sharename, old_printer->sharename))) {
6321 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6323 DEBUG(0, ("sharename data corrupted\n"));
6324 result = WERR_INVALID_DATA;
6327 result = winreg_set_printer_dataex(tmp_ctx, b,
6329 SPOOL_DSSPOOLER_KEY,
6330 SPOOL_REG_PRINTSHARENAME,
6334 if (!W_ERROR_IS_OK(result)) {
6335 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6339 if (!force_update) {
6340 notify_printer_sharename(server_event_context(),
6342 snum, printer->sharename ?
6343 printer->sharename : "");
6347 if (printer->printername != NULL &&
6349 !strequal(printer->printername, old_printer->printername))) {
6352 p = strrchr(printer->printername, '\\' );
6356 p = printer->printername;
6359 ok = push_reg_sz(tmp_ctx, &buffer, p);
6361 DEBUG(0, ("printername data corrupted\n"));
6362 result = WERR_INVALID_DATA;
6365 result = winreg_set_printer_dataex(tmp_ctx, b,
6367 SPOOL_DSSPOOLER_KEY,
6368 SPOOL_REG_PRINTERNAME,
6372 if (!W_ERROR_IS_OK(result)) {
6373 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6377 if (!force_update) {
6378 notify_printer_printername(server_event_context(),
6379 msg_ctx, snum, p ? p : "");
6383 if (printer->portname != NULL &&
6385 !strequal(printer->portname, old_printer->portname))) {
6386 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6388 DEBUG(0, ("portname data corrupted\n"));
6389 result = WERR_INVALID_DATA;
6392 result = winreg_set_printer_dataex(tmp_ctx, b,
6394 SPOOL_DSSPOOLER_KEY,
6399 if (!W_ERROR_IS_OK(result)) {
6400 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6404 if (!force_update) {
6405 notify_printer_port(server_event_context(),
6406 msg_ctx, snum, printer->portname ?
6407 printer->portname : "");
6411 if (printer->location != NULL &&
6413 !strequal(printer->location, old_printer->location))) {
6414 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6416 DEBUG(0, ("location data corrupted\n"));
6417 result = WERR_INVALID_DATA;
6420 result = winreg_set_printer_dataex(tmp_ctx, b,
6422 SPOOL_DSSPOOLER_KEY,
6427 if (!W_ERROR_IS_OK(result)) {
6428 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6432 if (!force_update) {
6433 notify_printer_location(server_event_context(),
6436 printer->location : "");
6440 if (printer->sepfile != NULL &&
6442 !strequal(printer->sepfile, old_printer->sepfile))) {
6443 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6445 DEBUG(0, ("sepfile data corrupted\n"));
6446 result = WERR_INVALID_DATA;
6449 result = winreg_set_printer_dataex(tmp_ctx, b,
6451 SPOOL_DSSPOOLER_KEY,
6452 SPOOL_REG_PRINTSEPARATORFILE,
6456 if (!W_ERROR_IS_OK(result)) {
6457 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6461 if (!force_update) {
6462 notify_printer_sepfile(server_event_context(),
6465 printer->sepfile : "");
6469 if (printer->starttime != 0 &&
6471 printer->starttime != old_printer->starttime)) {
6472 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6473 SIVAL(buffer.data, 0, printer->starttime);
6474 result = winreg_set_printer_dataex(tmp_ctx, b,
6476 SPOOL_DSSPOOLER_KEY,
6477 SPOOL_REG_PRINTSTARTTIME,
6481 if (!W_ERROR_IS_OK(result)) {
6482 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6487 if (printer->untiltime != 0 &&
6489 printer->untiltime != old_printer->untiltime)) {
6490 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6491 SIVAL(buffer.data, 0, printer->untiltime);
6492 result = winreg_set_printer_dataex(tmp_ctx, b,
6494 SPOOL_DSSPOOLER_KEY,
6495 SPOOL_REG_PRINTENDTIME,
6499 if (!W_ERROR_IS_OK(result)) {
6500 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6505 if (force_update || printer->priority != old_printer->priority) {
6506 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6507 SIVAL(buffer.data, 0, printer->priority);
6508 result = winreg_set_printer_dataex(tmp_ctx, b,
6510 SPOOL_DSSPOOLER_KEY,
6515 if (!W_ERROR_IS_OK(result)) {
6516 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6521 if (force_update || printer->attributes != old_printer->attributes) {
6522 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6523 SIVAL(buffer.data, 0, (printer->attributes &
6524 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6525 result = winreg_set_printer_dataex(tmp_ctx, b,
6527 SPOOL_DSSPOOLER_KEY,
6528 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6532 if (!W_ERROR_IS_OK(result)) {
6533 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6537 switch (printer->attributes & 0x3) {
6539 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6542 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6545 spooling = SPOOL_REGVAL_PRINTDIRECT;
6548 spooling = "unknown";
6550 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6552 DEBUG(0, ("printSpooling data corrupted\n"));
6553 result = WERR_INVALID_DATA;
6556 winreg_set_printer_dataex(tmp_ctx, b,
6558 SPOOL_DSSPOOLER_KEY,
6559 SPOOL_REG_PRINTSPOOLING,
6565 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6567 DEBUG(0, ("shortServerName data corrupted\n"));
6568 result = WERR_INVALID_DATA;
6571 result = winreg_set_printer_dataex(tmp_ctx, b,
6573 SPOOL_DSSPOOLER_KEY,
6574 SPOOL_REG_SHORTSERVERNAME,
6578 if (!W_ERROR_IS_OK(result)) {
6579 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6583 dnsdomname = get_mydnsfullname();
6584 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6585 longname = talloc_strdup(tmp_ctx, dnsdomname);
6587 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6589 if (longname == NULL) {
6590 result = WERR_NOMEM;
6594 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6596 DEBUG(0, ("longname data corrupted\n"));
6597 result = WERR_INVALID_DATA;
6600 result = winreg_set_printer_dataex(tmp_ctx, b,
6602 SPOOL_DSSPOOLER_KEY,
6603 SPOOL_REG_SERVERNAME,
6607 if (!W_ERROR_IS_OK(result)) {
6608 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6612 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6613 lp_netbios_name(), printer->sharename);
6614 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6616 DEBUG(0, ("uncName data corrupted\n"));
6617 result = WERR_INVALID_DATA;
6620 result = winreg_set_printer_dataex(tmp_ctx, b,
6622 SPOOL_DSSPOOLER_KEY,
6627 if (!W_ERROR_IS_OK(result)) {
6628 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6633 talloc_free(tmp_ctx);
6637 /********************************************************************
6638 * Called by spoolss_api_setprinter
6639 * when updating a printer description.
6640 ********************************************************************/
6642 static WERROR update_printer(struct pipes_struct *p,
6643 struct policy_handle *handle,
6644 struct spoolss_SetPrinterInfoCtr *info_ctr,
6645 struct spoolss_DeviceMode *devmode)
6647 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6648 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6649 struct spoolss_PrinterInfo2 *old_printer;
6650 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6652 WERROR result = WERR_OK;
6653 TALLOC_CTX *tmp_ctx;
6654 struct dcerpc_binding_handle *b;
6656 DEBUG(8,("update_printer\n"));
6658 tmp_ctx = talloc_new(p->mem_ctx);
6659 if (tmp_ctx == NULL) {
6664 result = WERR_BADFID;
6668 if (!get_printer_snum(p, handle, &snum, NULL)) {
6669 result = WERR_BADFID;
6673 result = winreg_printer_binding_handle(tmp_ctx,
6674 get_session_info_system(),
6677 if (!W_ERROR_IS_OK(result)) {
6681 result = winreg_get_printer(tmp_ctx, b,
6682 lp_const_servicename(snum),
6684 if (!W_ERROR_IS_OK(result)) {
6685 result = WERR_BADFID;
6689 /* Do sanity check on the requested changes for Samba */
6690 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6691 result = WERR_INVALID_PARAM;
6695 /* FIXME!!! If the driver has changed we really should verify that
6696 it is installed before doing much else --jerry */
6698 /* Check calling user has permission to update printer description */
6699 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6700 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6701 result = WERR_ACCESS_DENIED;
6705 /* Call addprinter hook */
6706 /* Check changes to see if this is really needed */
6708 if (*lp_addprinter_cmd() &&
6709 (!strequal(printer->drivername, old_printer->drivername) ||
6710 !strequal(printer->comment, old_printer->comment) ||
6711 !strequal(printer->portname, old_printer->portname) ||
6712 !strequal(printer->location, old_printer->location)) )
6716 raddr = tsocket_address_inet_addr_string(p->remote_address,
6718 if (raddr == NULL) {
6722 /* add_printer_hook() will call reload_services() */
6723 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6726 result = WERR_ACCESS_DENIED;
6731 result = update_dsspooler(tmp_ctx,
6732 get_session_info_system(),
6737 if (!W_ERROR_IS_OK(result)) {
6741 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6743 if (devmode == NULL) {
6744 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6746 result = winreg_update_printer(tmp_ctx, b,
6754 talloc_free(tmp_ctx);
6759 /****************************************************************************
6760 ****************************************************************************/
6761 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6762 struct policy_handle *handle,
6763 struct spoolss_SetPrinterInfo7 *info7)
6766 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6769 struct printer_handle *Printer;
6771 if ( lp_security() != SEC_ADS ) {
6772 return WERR_UNKNOWN_LEVEL;
6775 Printer = find_printer_index_by_hnd(p, handle);
6777 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6782 if (!get_printer_snum(p, handle, &snum, NULL))
6785 result = winreg_get_printer_internal(p->mem_ctx,
6786 get_session_info_system(),
6788 lp_servicename(snum),
6790 if (!W_ERROR_IS_OK(result)) {
6794 nt_printer_publish(pinfo2,
6795 get_session_info_system(),
6800 TALLOC_FREE(pinfo2);
6803 return WERR_UNKNOWN_LEVEL;
6807 /********************************************************************
6808 ********************************************************************/
6810 static WERROR update_printer_devmode(struct pipes_struct *p,
6811 struct policy_handle *handle,
6812 struct spoolss_DeviceMode *devmode)
6815 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6816 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6818 DEBUG(8,("update_printer_devmode\n"));
6824 if (!get_printer_snum(p, handle, &snum, NULL)) {
6828 /* Check calling user has permission to update printer description */
6829 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6830 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6831 return WERR_ACCESS_DENIED;
6834 return winreg_update_printer_internal(p->mem_ctx,
6835 get_session_info_system(),
6837 lp_const_servicename(snum),
6845 /****************************************************************
6847 ****************************************************************/
6849 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6850 struct spoolss_SetPrinter *r)
6854 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6857 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6858 OUR_HANDLE(r->in.handle)));
6862 /* check the level */
6863 switch (r->in.info_ctr->level) {
6865 return control_printer(r->in.handle, r->in.command, p);
6867 result = update_printer(p, r->in.handle,
6869 r->in.devmode_ctr->devmode);
6870 if (!W_ERROR_IS_OK(result))
6872 if (r->in.secdesc_ctr->sd)
6873 result = update_printer_sec(r->in.handle, p,
6877 return update_printer_sec(r->in.handle, p,
6880 return publish_or_unpublish_printer(p, r->in.handle,
6881 r->in.info_ctr->info.info7);
6883 return update_printer_devmode(p, r->in.handle,
6884 r->in.devmode_ctr->devmode);
6886 return WERR_UNKNOWN_LEVEL;
6890 /****************************************************************
6891 _spoolss_FindClosePrinterNotify
6892 ****************************************************************/
6894 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6895 struct spoolss_FindClosePrinterNotify *r)
6897 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6900 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6901 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6905 if (Printer->notify.cli_chan != NULL &&
6906 Printer->notify.cli_chan->active_connections > 0) {
6909 if (Printer->printer_type == SPLHND_PRINTER) {
6910 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6915 srv_spoolss_replycloseprinter(snum, Printer);
6918 Printer->notify.flags=0;
6919 Printer->notify.options=0;
6920 Printer->notify.localmachine[0]='\0';
6921 Printer->notify.printerlocal=0;
6922 TALLOC_FREE(Printer->notify.option);
6927 /****************************************************************
6929 ****************************************************************/
6931 WERROR _spoolss_AddJob(struct pipes_struct *p,
6932 struct spoolss_AddJob *r)
6934 if (!r->in.buffer && (r->in.offered != 0)) {
6935 return WERR_INVALID_PARAM;
6938 /* this is what a NT server returns for AddJob. AddJob must fail on
6939 * non-local printers */
6941 if (r->in.level != 1) {
6942 return WERR_UNKNOWN_LEVEL;
6945 return WERR_INVALID_PARAM;
6948 /****************************************************************************
6950 ****************************************************************************/
6952 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6953 struct spoolss_JobInfo1 *r,
6954 const print_queue_struct *queue,
6955 int position, int snum,
6956 struct spoolss_PrinterInfo2 *pinfo2)
6960 t = gmtime(&queue->time);
6962 r->job_id = queue->sysjob;
6964 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6965 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6966 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6967 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6968 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6969 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6970 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6971 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6972 r->data_type = talloc_strdup(mem_ctx, "RAW");
6973 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6974 r->text_status = talloc_strdup(mem_ctx, "");
6975 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6977 r->status = nt_printj_status(queue->status);
6978 r->priority = queue->priority;
6979 r->position = position;
6980 r->total_pages = queue->page_count;
6981 r->pages_printed = 0; /* ??? */
6983 init_systemtime(&r->submitted, t);
6988 /****************************************************************************
6990 ****************************************************************************/
6992 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6993 struct spoolss_JobInfo2 *r,
6994 const print_queue_struct *queue,
6995 int position, int snum,
6996 struct spoolss_PrinterInfo2 *pinfo2,
6997 struct spoolss_DeviceMode *devmode)
7001 t = gmtime(&queue->time);
7003 r->job_id = queue->sysjob;
7005 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
7006 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7007 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7008 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7009 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7010 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7011 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7012 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7013 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7014 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7015 r->data_type = talloc_strdup(mem_ctx, "RAW");
7016 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7017 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7018 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7019 r->parameters = talloc_strdup(mem_ctx, "");
7020 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7021 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7022 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7024 r->devmode = devmode;
7026 r->text_status = talloc_strdup(mem_ctx, "");
7027 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7031 r->status = nt_printj_status(queue->status);
7032 r->priority = queue->priority;
7033 r->position = position;
7036 r->total_pages = queue->page_count;
7037 r->size = queue->size;
7038 init_systemtime(&r->submitted, t);
7040 r->pages_printed = 0; /* ??? */
7045 /****************************************************************************
7047 ****************************************************************************/
7049 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7050 struct spoolss_JobInfo3 *r,
7051 const print_queue_struct *queue,
7052 const print_queue_struct *next_queue,
7053 int position, int snum,
7054 struct spoolss_PrinterInfo2 *pinfo2)
7056 r->job_id = queue->sysjob;
7059 r->next_job_id = next_queue->sysjob;
7066 /****************************************************************************
7067 Enumjobs at level 1.
7068 ****************************************************************************/
7070 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7071 const print_queue_struct *queue,
7072 uint32_t num_queues, int snum,
7073 struct spoolss_PrinterInfo2 *pinfo2,
7074 union spoolss_JobInfo **info_p,
7077 union spoolss_JobInfo *info;
7079 WERROR result = WERR_OK;
7081 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7082 W_ERROR_HAVE_NO_MEMORY(info);
7084 *count = num_queues;
7086 for (i=0; i<*count; i++) {
7087 result = fill_job_info1(info,
7093 if (!W_ERROR_IS_OK(result)) {
7099 if (!W_ERROR_IS_OK(result)) {
7110 /****************************************************************************
7111 Enumjobs at level 2.
7112 ****************************************************************************/
7114 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7115 const print_queue_struct *queue,
7116 uint32_t num_queues, int snum,
7117 struct spoolss_PrinterInfo2 *pinfo2,
7118 union spoolss_JobInfo **info_p,
7121 union spoolss_JobInfo *info;
7123 WERROR result = WERR_OK;
7125 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7126 W_ERROR_HAVE_NO_MEMORY(info);
7128 *count = num_queues;
7130 for (i=0; i<*count; i++) {
7131 struct spoolss_DeviceMode *devmode;
7133 result = spoolss_create_default_devmode(info,
7134 pinfo2->printername,
7136 if (!W_ERROR_IS_OK(result)) {
7137 DEBUG(3, ("Can't proceed w/o a devmode!"));
7141 result = fill_job_info2(info,
7148 if (!W_ERROR_IS_OK(result)) {
7154 if (!W_ERROR_IS_OK(result)) {
7165 /****************************************************************************
7166 Enumjobs at level 3.
7167 ****************************************************************************/
7169 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7170 const print_queue_struct *queue,
7171 uint32_t num_queues, int snum,
7172 struct spoolss_PrinterInfo2 *pinfo2,
7173 union spoolss_JobInfo **info_p,
7176 union spoolss_JobInfo *info;
7178 WERROR result = WERR_OK;
7180 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7181 W_ERROR_HAVE_NO_MEMORY(info);
7183 *count = num_queues;
7185 for (i=0; i<*count; i++) {
7186 const print_queue_struct *next_queue = NULL;
7189 next_queue = &queue[i+1];
7192 result = fill_job_info3(info,
7199 if (!W_ERROR_IS_OK(result)) {
7205 if (!W_ERROR_IS_OK(result)) {
7216 /****************************************************************
7218 ****************************************************************/
7220 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7221 struct spoolss_EnumJobs *r)
7224 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7226 print_status_struct prt_status;
7227 print_queue_struct *queue = NULL;
7230 /* that's an [in out] buffer */
7232 if (!r->in.buffer && (r->in.offered != 0)) {
7233 return WERR_INVALID_PARAM;
7236 DEBUG(4,("_spoolss_EnumJobs\n"));
7240 *r->out.info = NULL;
7242 /* lookup the printer snum and tdb entry */
7244 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7248 result = winreg_get_printer_internal(p->mem_ctx,
7249 get_session_info_system(),
7251 lp_const_servicename(snum),
7253 if (!W_ERROR_IS_OK(result)) {
7257 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7258 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7259 count, prt_status.status, prt_status.message));
7263 TALLOC_FREE(pinfo2);
7267 switch (r->in.level) {
7269 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7270 pinfo2, r->out.info, r->out.count);
7273 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7274 pinfo2, r->out.info, r->out.count);
7277 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7278 pinfo2, r->out.info, r->out.count);
7281 result = WERR_UNKNOWN_LEVEL;
7286 TALLOC_FREE(pinfo2);
7288 if (!W_ERROR_IS_OK(result)) {
7292 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7294 *r->out.info, r->in.level,
7296 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7297 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7299 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7302 /****************************************************************
7303 _spoolss_ScheduleJob
7304 ****************************************************************/
7306 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7307 struct spoolss_ScheduleJob *r)
7312 /****************************************************************
7313 ****************************************************************/
7315 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7316 struct messaging_context *msg_ctx,
7317 const char *printer_name,
7319 struct spoolss_SetJobInfo1 *r)
7323 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7327 if (strequal(old_doc_name, r->document_name)) {
7331 if (!print_job_set_name(server_event_context(), msg_ctx,
7332 printer_name, job_id, r->document_name)) {
7339 /****************************************************************
7341 ****************************************************************/
7343 WERROR _spoolss_SetJob(struct pipes_struct *p,
7344 struct spoolss_SetJob *r)
7346 const struct auth_session_info *session_info = p->session_info;
7348 WERROR errcode = WERR_BADFUNC;
7350 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7354 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7355 return WERR_INVALID_PRINTER_NAME;
7358 switch (r->in.command) {
7359 case SPOOLSS_JOB_CONTROL_CANCEL:
7360 case SPOOLSS_JOB_CONTROL_DELETE:
7361 errcode = print_job_delete(session_info, p->msg_ctx,
7362 snum, r->in.job_id);
7363 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7367 case SPOOLSS_JOB_CONTROL_PAUSE:
7368 errcode = print_job_pause(session_info, p->msg_ctx,
7369 snum, r->in.job_id);
7371 case SPOOLSS_JOB_CONTROL_RESTART:
7372 case SPOOLSS_JOB_CONTROL_RESUME:
7373 errcode = print_job_resume(session_info, p->msg_ctx,
7374 snum, r->in.job_id);
7380 return WERR_UNKNOWN_LEVEL;
7383 if (!W_ERROR_IS_OK(errcode)) {
7387 if (r->in.ctr == NULL) {
7391 switch (r->in.ctr->level) {
7393 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7394 lp_const_servicename(snum),
7396 r->in.ctr->info.info1);
7402 return WERR_UNKNOWN_LEVEL;
7408 /****************************************************************************
7409 Enumerates all printer drivers by level and architecture.
7410 ****************************************************************************/
7412 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7413 const struct auth_session_info *session_info,
7414 struct messaging_context *msg_ctx,
7415 const char *servername,
7416 const char *architecture,
7418 union spoolss_DriverInfo **info_p,
7423 struct spoolss_DriverInfo8 *driver;
7424 union spoolss_DriverInfo *info = NULL;
7426 WERROR result = WERR_OK;
7427 uint32_t num_drivers;
7428 const char **drivers;
7429 struct dcerpc_binding_handle *b;
7430 TALLOC_CTX *tmp_ctx = NULL;
7435 tmp_ctx = talloc_new(mem_ctx);
7440 result = winreg_printer_binding_handle(tmp_ctx,
7444 if (!W_ERROR_IS_OK(result)) {
7448 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7449 result = winreg_get_driver_list(tmp_ctx, b,
7450 architecture, version,
7451 &num_drivers, &drivers);
7452 if (!W_ERROR_IS_OK(result)) {
7455 DEBUG(4, ("we have:[%d] drivers in environment"
7456 " [%s] and version [%d]\n",
7457 num_drivers, architecture, version));
7459 if (num_drivers != 0) {
7460 info = talloc_realloc(tmp_ctx, info,
7461 union spoolss_DriverInfo,
7462 count + num_drivers);
7464 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7465 "failed to enlarge driver info buffer!\n"));
7466 result = WERR_NOMEM;
7471 for (i = 0; i < num_drivers; i++) {
7472 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7474 result = winreg_get_driver(tmp_ctx, b,
7475 architecture, drivers[i],
7477 if (!W_ERROR_IS_OK(result)) {
7483 result = fill_printer_driver_info1(info, &info[count+i].info1,
7484 driver, servername);
7487 result = fill_printer_driver_info2(info, &info[count+i].info2,
7488 driver, servername);
7491 result = fill_printer_driver_info3(info, &info[count+i].info3,
7492 driver, servername);
7495 result = fill_printer_driver_info4(info, &info[count+i].info4,
7496 driver, servername);
7499 result = fill_printer_driver_info5(info, &info[count+i].info5,
7500 driver, servername);
7503 result = fill_printer_driver_info6(info, &info[count+i].info6,
7504 driver, servername);
7507 result = fill_printer_driver_info8(info, &info[count+i].info8,
7508 driver, servername);
7511 result = WERR_UNKNOWN_LEVEL;
7515 TALLOC_FREE(driver);
7517 if (!W_ERROR_IS_OK(result)) {
7522 count += num_drivers;
7523 TALLOC_FREE(drivers);
7527 if (W_ERROR_IS_OK(result)) {
7528 *info_p = talloc_move(mem_ctx, &info);
7532 talloc_free(tmp_ctx);
7536 /****************************************************************************
7537 Enumerates all printer drivers by level.
7538 ****************************************************************************/
7540 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7541 const struct auth_session_info *session_info,
7542 struct messaging_context *msg_ctx,
7543 const char *servername,
7544 const char *architecture,
7546 union spoolss_DriverInfo **info_p,
7550 WERROR result = WERR_OK;
7552 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7554 for (a=0; archi_table[a].long_archi != NULL; a++) {
7556 union spoolss_DriverInfo *info = NULL;
7559 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7563 archi_table[a].long_archi,
7567 if (!W_ERROR_IS_OK(result)) {
7571 for (i=0; i < count; i++) {
7572 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7573 info[i], info_p, count_p);
7580 return enumprinterdrivers_level_by_architecture(mem_ctx,
7590 /****************************************************************
7591 _spoolss_EnumPrinterDrivers
7592 ****************************************************************/
7594 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7595 struct spoolss_EnumPrinterDrivers *r)
7597 const char *cservername;
7600 /* that's an [in out] buffer */
7602 if (!r->in.buffer && (r->in.offered != 0)) {
7603 return WERR_INVALID_PARAM;
7606 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7610 *r->out.info = NULL;
7612 cservername = canon_servername(r->in.server);
7614 if (!is_myname_or_ipaddr(cservername)) {
7615 return WERR_UNKNOWN_PRINTER_DRIVER;
7618 result = enumprinterdrivers_level(p->mem_ctx,
7619 get_session_info_system(),
7626 if (!W_ERROR_IS_OK(result)) {
7630 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7631 spoolss_EnumPrinterDrivers,
7632 *r->out.info, r->in.level,
7634 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7635 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7637 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7640 /****************************************************************
7642 ****************************************************************/
7644 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7645 struct spoolss_EnumForms *r)
7651 *r->out.info = NULL;
7653 /* that's an [in out] buffer */
7655 if (!r->in.buffer && (r->in.offered != 0) ) {
7656 return WERR_INVALID_PARAM;
7659 DEBUG(4,("_spoolss_EnumForms\n"));
7660 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7661 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7663 switch (r->in.level) {
7665 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7666 get_session_info_system(),
7672 result = WERR_UNKNOWN_LEVEL;
7676 if (!W_ERROR_IS_OK(result)) {
7680 if (*r->out.count == 0) {
7681 return WERR_NO_MORE_ITEMS;
7684 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7686 *r->out.info, r->in.level,
7688 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7689 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7691 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7694 /****************************************************************
7696 ****************************************************************/
7698 WERROR _spoolss_GetForm(struct pipes_struct *p,
7699 struct spoolss_GetForm *r)
7703 /* that's an [in out] buffer */
7705 if (!r->in.buffer && (r->in.offered != 0)) {
7706 return WERR_INVALID_PARAM;
7709 DEBUG(4,("_spoolss_GetForm\n"));
7710 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7711 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7713 switch (r->in.level) {
7715 result = winreg_printer_getform1_internal(p->mem_ctx,
7716 get_session_info_system(),
7719 &r->out.info->info1);
7722 result = WERR_UNKNOWN_LEVEL;
7726 if (!W_ERROR_IS_OK(result)) {
7727 TALLOC_FREE(r->out.info);
7731 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7732 r->out.info, r->in.level);
7733 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7735 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7738 /****************************************************************************
7739 ****************************************************************************/
7741 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7742 struct spoolss_PortInfo1 *r,
7745 r->port_name = talloc_strdup(mem_ctx, name);
7746 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7751 /****************************************************************************
7752 TODO: This probably needs distinguish between TCP/IP and Local ports
7754 ****************************************************************************/
7756 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7757 struct spoolss_PortInfo2 *r,
7760 r->port_name = talloc_strdup(mem_ctx, name);
7761 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7763 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7764 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7766 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7767 W_ERROR_HAVE_NO_MEMORY(r->description);
7769 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7776 /****************************************************************************
7777 wrapper around the enumer ports command
7778 ****************************************************************************/
7780 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7782 char *cmd = lp_enumports_cmd();
7783 char **qlines = NULL;
7784 char *command = NULL;
7792 /* if no hook then just fill in the default port */
7795 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7798 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7799 TALLOC_FREE(qlines);
7806 /* we have a valid enumport command */
7808 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7813 DEBUG(10,("Running [%s]\n", command));
7814 ret = smbrun(command, &fd);
7815 DEBUG(10,("Returned [%d]\n", ret));
7816 TALLOC_FREE(command);
7821 return WERR_ACCESS_DENIED;
7825 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7826 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7836 /****************************************************************************
7838 ****************************************************************************/
7840 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7841 union spoolss_PortInfo **info_p,
7844 union spoolss_PortInfo *info = NULL;
7846 WERROR result = WERR_OK;
7847 char **qlines = NULL;
7850 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7851 if (!W_ERROR_IS_OK(result)) {
7856 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7858 DEBUG(10,("Returning WERR_NOMEM\n"));
7859 result = WERR_NOMEM;
7863 for (i=0; i<numlines; i++) {
7864 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7865 result = fill_port_1(info, &info[i].info1, qlines[i]);
7866 if (!W_ERROR_IS_OK(result)) {
7871 TALLOC_FREE(qlines);
7874 if (!W_ERROR_IS_OK(result)) {
7876 TALLOC_FREE(qlines);
7888 /****************************************************************************
7890 ****************************************************************************/
7892 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7893 union spoolss_PortInfo **info_p,
7896 union spoolss_PortInfo *info = NULL;
7898 WERROR result = WERR_OK;
7899 char **qlines = NULL;
7902 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7903 if (!W_ERROR_IS_OK(result)) {
7908 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7910 DEBUG(10,("Returning WERR_NOMEM\n"));
7911 result = WERR_NOMEM;
7915 for (i=0; i<numlines; i++) {
7916 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7917 result = fill_port_2(info, &info[i].info2, qlines[i]);
7918 if (!W_ERROR_IS_OK(result)) {
7923 TALLOC_FREE(qlines);
7926 if (!W_ERROR_IS_OK(result)) {
7928 TALLOC_FREE(qlines);
7940 /****************************************************************
7942 ****************************************************************/
7944 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7945 struct spoolss_EnumPorts *r)
7949 /* that's an [in out] buffer */
7951 if (!r->in.buffer && (r->in.offered != 0)) {
7952 return WERR_INVALID_PARAM;
7955 DEBUG(4,("_spoolss_EnumPorts\n"));
7959 *r->out.info = NULL;
7961 switch (r->in.level) {
7963 result = enumports_level_1(p->mem_ctx, r->out.info,
7967 result = enumports_level_2(p->mem_ctx, r->out.info,
7971 return WERR_UNKNOWN_LEVEL;
7974 if (!W_ERROR_IS_OK(result)) {
7978 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7980 *r->out.info, r->in.level,
7982 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7983 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7985 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7988 /****************************************************************************
7989 ****************************************************************************/
7991 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7993 struct spoolss_SetPrinterInfoCtr *info_ctr,
7994 struct spoolss_DeviceMode *devmode,
7995 struct security_descriptor *secdesc,
7996 struct spoolss_UserLevelCtr *user_ctr,
7997 struct policy_handle *handle)
7999 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8000 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8002 WERROR err = WERR_OK;
8004 /* samba does not have a concept of local, non-shared printers yet, so
8005 * make sure we always setup sharename - gd */
8006 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8007 (info2->printername != NULL && info2->printername[0] != '\0')) {
8008 DEBUG(5, ("spoolss_addprinterex_level_2: "
8009 "no sharename has been set, setting printername %s as sharename\n",
8010 info2->printername));
8011 info2->sharename = info2->printername;
8014 /* check to see if the printer already exists */
8015 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8016 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8018 return WERR_PRINTER_ALREADY_EXISTS;
8021 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8022 if ((snum = print_queue_snum(info2->printername)) != -1) {
8023 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8024 info2->printername));
8025 return WERR_PRINTER_ALREADY_EXISTS;
8029 /* validate printer info struct */
8030 if (!info2->printername || strlen(info2->printername) == 0) {
8031 return WERR_INVALID_PRINTER_NAME;
8033 if (!info2->portname || strlen(info2->portname) == 0) {
8034 return WERR_UNKNOWN_PORT;
8036 if (!info2->drivername || strlen(info2->drivername) == 0) {
8037 return WERR_UNKNOWN_PRINTER_DRIVER;
8039 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8040 return WERR_UNKNOWN_PRINTPROCESSOR;
8043 /* FIXME!!! smbd should check to see if the driver is installed before
8044 trying to add a printer like this --jerry */
8046 if (*lp_addprinter_cmd() ) {
8049 raddr = tsocket_address_inet_addr_string(p->remote_address,
8051 if (raddr == NULL) {
8055 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8058 return WERR_ACCESS_DENIED;
8061 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8062 "smb.conf parameter \"addprinter command\" is defined. This "
8063 "parameter must exist for this call to succeed\n",
8064 info2->sharename ));
8067 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8068 return WERR_ACCESS_DENIED;
8071 /* you must be a printer admin to add a new printer */
8072 if (!print_access_check(p->session_info,
8075 PRINTER_ACCESS_ADMINISTER)) {
8076 return WERR_ACCESS_DENIED;
8080 * Do sanity check on the requested changes for Samba.
8083 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8084 return WERR_INVALID_PARAM;
8087 if (devmode == NULL) {
8088 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8091 err = update_dsspooler(p->mem_ctx,
8092 get_session_info_system(),
8097 if (!W_ERROR_IS_OK(err)) {
8101 err = winreg_update_printer_internal(p->mem_ctx,
8102 get_session_info_system(),
8109 if (!W_ERROR_IS_OK(err)) {
8113 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8114 if (!W_ERROR_IS_OK(err)) {
8115 /* Handle open failed - remove addition. */
8116 ZERO_STRUCTP(handle);
8123 /****************************************************************
8124 _spoolss_AddPrinterEx
8125 ****************************************************************/
8127 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8128 struct spoolss_AddPrinterEx *r)
8130 switch (r->in.info_ctr->level) {
8132 /* we don't handle yet */
8133 /* but I know what to do ... */
8134 return WERR_UNKNOWN_LEVEL;
8136 return spoolss_addprinterex_level_2(p, r->in.server,
8138 r->in.devmode_ctr->devmode,
8139 r->in.secdesc_ctr->sd,
8140 r->in.userlevel_ctr,
8143 return WERR_UNKNOWN_LEVEL;
8147 /****************************************************************
8149 ****************************************************************/
8151 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8152 struct spoolss_AddPrinter *r)
8154 struct spoolss_AddPrinterEx a;
8155 struct spoolss_UserLevelCtr userlevel_ctr;
8157 ZERO_STRUCT(userlevel_ctr);
8159 userlevel_ctr.level = 1;
8161 a.in.server = r->in.server;
8162 a.in.info_ctr = r->in.info_ctr;
8163 a.in.devmode_ctr = r->in.devmode_ctr;
8164 a.in.secdesc_ctr = r->in.secdesc_ctr;
8165 a.in.userlevel_ctr = &userlevel_ctr;
8166 a.out.handle = r->out.handle;
8168 return _spoolss_AddPrinterEx(p, &a);
8171 /****************************************************************
8172 _spoolss_AddPrinterDriverEx
8173 ****************************************************************/
8175 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8176 struct spoolss_AddPrinterDriverEx *r)
8178 WERROR err = WERR_OK;
8179 const char *driver_name = NULL;
8184 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8185 fn = "_spoolss_AddPrinterDriver";
8187 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8188 fn = "_spoolss_AddPrinterDriverEx";
8191 return WERR_INVALID_PARAM;
8195 * we only support the semantics of AddPrinterDriver()
8196 * i.e. only copy files that are newer than existing ones
8199 if (r->in.flags == 0) {
8200 return WERR_INVALID_PARAM;
8203 if (r->in.flags != APD_COPY_NEW_FILES) {
8204 return WERR_ACCESS_DENIED;
8208 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8209 /* Clever hack from Martin Zielinski <mz@seh.de>
8210 * to allow downgrade from level 8 (Vista).
8212 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8213 r->in.info_ctr->level));
8214 return WERR_UNKNOWN_LEVEL;
8217 DEBUG(5,("Cleaning driver's information\n"));
8218 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8219 if (!W_ERROR_IS_OK(err))
8222 DEBUG(5,("Moving driver to final destination\n"));
8223 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8224 if (!W_ERROR_IS_OK(err)) {
8228 err = winreg_add_driver_internal(p->mem_ctx,
8229 get_session_info_system(),
8234 if (!W_ERROR_IS_OK(err)) {
8239 * I think this is where he DrvUpgradePrinter() hook would be
8240 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8241 * server. Right now, we just need to send ourselves a message
8242 * to update each printer bound to this driver. --jerry
8245 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8246 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8254 /****************************************************************
8255 _spoolss_AddPrinterDriver
8256 ****************************************************************/
8258 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8259 struct spoolss_AddPrinterDriver *r)
8261 struct spoolss_AddPrinterDriverEx a;
8263 switch (r->in.info_ctr->level) {
8270 return WERR_UNKNOWN_LEVEL;
8273 a.in.servername = r->in.servername;
8274 a.in.info_ctr = r->in.info_ctr;
8275 a.in.flags = APD_COPY_NEW_FILES;
8277 return _spoolss_AddPrinterDriverEx(p, &a);
8280 /****************************************************************************
8281 ****************************************************************************/
8283 struct _spoolss_paths {
8289 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8291 static const struct _spoolss_paths spoolss_paths[]= {
8292 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8293 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8296 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8297 const char *servername,
8298 const char *environment,
8302 const char *pservername = NULL;
8303 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8304 const char *short_archi;
8308 /* environment may be empty */
8309 if (environment && strlen(environment)) {
8310 long_archi = environment;
8313 /* servername may be empty */
8314 if (servername && strlen(servername)) {
8315 pservername = canon_servername(servername);
8317 if (!is_myname_or_ipaddr(pservername)) {
8318 return WERR_INVALID_PARAM;
8322 if (!(short_archi = get_short_archi(long_archi))) {
8323 return WERR_INVALID_ENVIRONMENT;
8326 switch (component) {
8327 case SPOOLSS_PRTPROCS_PATH:
8328 case SPOOLSS_DRIVER_PATH:
8330 *path = talloc_asprintf(mem_ctx,
8333 spoolss_paths[component].share,
8336 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8337 SPOOLSS_DEFAULT_SERVER_PATH,
8338 spoolss_paths[component].dir,
8343 return WERR_INVALID_PARAM;
8353 /****************************************************************************
8354 ****************************************************************************/
8356 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8357 const char *servername,
8358 const char *environment,
8359 struct spoolss_DriverDirectoryInfo1 *r)
8364 werr = compose_spoolss_server_path(mem_ctx,
8367 SPOOLSS_DRIVER_PATH,
8369 if (!W_ERROR_IS_OK(werr)) {
8373 DEBUG(4,("printer driver directory: [%s]\n", path));
8375 r->directory_name = path;
8380 /****************************************************************
8381 _spoolss_GetPrinterDriverDirectory
8382 ****************************************************************/
8384 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8385 struct spoolss_GetPrinterDriverDirectory *r)
8389 /* that's an [in out] buffer */
8391 if (!r->in.buffer && (r->in.offered != 0)) {
8392 return WERR_INVALID_PARAM;
8395 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8400 /* r->in.level is ignored */
8402 werror = getprinterdriverdir_level_1(p->mem_ctx,
8405 &r->out.info->info1);
8406 if (!W_ERROR_IS_OK(werror)) {
8407 TALLOC_FREE(r->out.info);
8411 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8412 r->out.info, r->in.level);
8413 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8415 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8418 /****************************************************************
8419 _spoolss_EnumPrinterData
8420 ****************************************************************/
8422 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8423 struct spoolss_EnumPrinterData *r)
8426 struct spoolss_EnumPrinterDataEx r2;
8428 struct spoolss_PrinterEnumValues *info, *val = NULL;
8431 r2.in.handle = r->in.handle;
8432 r2.in.key_name = "PrinterDriverData";
8434 r2.out.count = &count;
8435 r2.out.info = &info;
8436 r2.out.needed = &needed;
8438 result = _spoolss_EnumPrinterDataEx(p, &r2);
8439 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8440 r2.in.offered = needed;
8441 result = _spoolss_EnumPrinterDataEx(p, &r2);
8443 if (!W_ERROR_IS_OK(result)) {
8448 * The NT machine wants to know the biggest size of value and data
8450 * cf: MSDN EnumPrinterData remark section
8453 if (!r->in.value_offered && !r->in.data_offered) {
8454 uint32_t biggest_valuesize = 0;
8455 uint32_t biggest_datasize = 0;
8458 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8460 for (i=0; i<count; i++) {
8462 name_length = strlen(info[i].value_name);
8463 if (strlen(info[i].value_name) > biggest_valuesize) {
8464 biggest_valuesize = name_length;
8467 if (info[i].data_length > biggest_datasize) {
8468 biggest_datasize = info[i].data_length;
8471 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8475 /* the value is an UNICODE string but real_value_size is the length
8476 in bytes including the trailing 0 */
8478 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8479 *r->out.data_needed = biggest_datasize;
8481 DEBUG(6,("final values: [%d], [%d]\n",
8482 *r->out.value_needed, *r->out.data_needed));
8487 if (r->in.enum_index < count) {
8488 val = &info[r->in.enum_index];
8492 /* out_value should default to "" or else NT4 has
8493 problems unmarshalling the response */
8495 if (r->in.value_offered) {
8496 *r->out.value_needed = 1;
8497 r->out.value_name = talloc_strdup(r, "");
8498 if (!r->out.value_name) {
8502 r->out.value_name = NULL;
8503 *r->out.value_needed = 0;
8506 /* the data is counted in bytes */
8508 *r->out.data_needed = r->in.data_offered;
8510 result = WERR_NO_MORE_ITEMS;
8514 * - counted in bytes in the request
8515 * - counted in UNICODE chars in the max reply
8516 * - counted in bytes in the real size
8518 * take a pause *before* coding not *during* coding
8522 if (r->in.value_offered) {
8523 r->out.value_name = talloc_strdup(r, val->value_name);
8524 if (!r->out.value_name) {
8527 *r->out.value_needed = val->value_name_len;
8529 r->out.value_name = NULL;
8530 *r->out.value_needed = 0;
8535 *r->out.type = val->type;
8537 /* data - counted in bytes */
8540 * See the section "Dynamically Typed Query Parameters"
8544 if (r->out.data && val->data && val->data->data &&
8545 val->data_length && r->in.data_offered) {
8546 memcpy(r->out.data, val->data->data,
8547 MIN(val->data_length,r->in.data_offered));
8550 *r->out.data_needed = val->data_length;
8558 /****************************************************************
8559 _spoolss_SetPrinterData
8560 ****************************************************************/
8562 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8563 struct spoolss_SetPrinterData *r)
8565 struct spoolss_SetPrinterDataEx r2;
8567 r2.in.handle = r->in.handle;
8568 r2.in.key_name = "PrinterDriverData";
8569 r2.in.value_name = r->in.value_name;
8570 r2.in.type = r->in.type;
8571 r2.in.data = r->in.data;
8572 r2.in.offered = r->in.offered;
8574 return _spoolss_SetPrinterDataEx(p, &r2);
8577 /****************************************************************
8578 _spoolss_ResetPrinter
8579 ****************************************************************/
8581 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8582 struct spoolss_ResetPrinter *r)
8584 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8587 DEBUG(5,("_spoolss_ResetPrinter\n"));
8590 * All we do is to check to see if the handle and queue is valid.
8591 * This call really doesn't mean anything to us because we only
8592 * support RAW printing. --jerry
8596 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8597 OUR_HANDLE(r->in.handle)));
8601 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8605 /* blindly return success */
8609 /****************************************************************
8610 _spoolss_DeletePrinterData
8611 ****************************************************************/
8613 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8614 struct spoolss_DeletePrinterData *r)
8616 struct spoolss_DeletePrinterDataEx r2;
8618 r2.in.handle = r->in.handle;
8619 r2.in.key_name = "PrinterDriverData";
8620 r2.in.value_name = r->in.value_name;
8622 return _spoolss_DeletePrinterDataEx(p, &r2);
8625 /****************************************************************
8627 ****************************************************************/
8629 WERROR _spoolss_AddForm(struct pipes_struct *p,
8630 struct spoolss_AddForm *r)
8632 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8634 WERROR status = WERR_OK;
8635 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8636 struct dcerpc_binding_handle *b;
8637 TALLOC_CTX *tmp_ctx = NULL;
8639 DEBUG(5,("_spoolss_AddForm\n"));
8642 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8643 OUR_HANDLE(r->in.handle)));
8647 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8648 and not a printer admin, then fail */
8650 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8651 !security_token_has_privilege(p->session_info->security_token,
8652 SEC_PRIV_PRINT_OPERATOR)) {
8653 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8654 return WERR_ACCESS_DENIED;
8657 switch (form->flags) {
8658 case SPOOLSS_FORM_USER:
8659 case SPOOLSS_FORM_BUILTIN:
8660 case SPOOLSS_FORM_PRINTER:
8663 return WERR_INVALID_PARAM;
8666 tmp_ctx = talloc_new(p->mem_ctx);
8671 status = winreg_printer_binding_handle(tmp_ctx,
8672 get_session_info_system(),
8675 if (!W_ERROR_IS_OK(status)) {
8679 status = winreg_printer_addform1(tmp_ctx, b, form);
8680 if (!W_ERROR_IS_OK(status)) {
8685 * ChangeID must always be set if this is a printer
8687 if (Printer->printer_type == SPLHND_PRINTER) {
8688 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8689 status = WERR_BADFID;
8693 status = winreg_printer_update_changeid(tmp_ctx, b,
8694 lp_const_servicename(snum));
8698 talloc_free(tmp_ctx);
8702 /****************************************************************
8704 ****************************************************************/
8706 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8707 struct spoolss_DeleteForm *r)
8709 const char *form_name = r->in.form_name;
8710 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8712 WERROR status = WERR_OK;
8713 struct dcerpc_binding_handle *b;
8714 TALLOC_CTX *tmp_ctx = NULL;
8716 DEBUG(5,("_spoolss_DeleteForm\n"));
8719 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8720 OUR_HANDLE(r->in.handle)));
8724 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8725 !security_token_has_privilege(p->session_info->security_token,
8726 SEC_PRIV_PRINT_OPERATOR)) {
8727 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8728 return WERR_ACCESS_DENIED;
8731 tmp_ctx = talloc_new(p->mem_ctx);
8736 status = winreg_printer_binding_handle(tmp_ctx,
8737 get_session_info_system(),
8740 if (!W_ERROR_IS_OK(status)) {
8744 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8745 if (!W_ERROR_IS_OK(status)) {
8750 * ChangeID must always be set if this is a printer
8752 if (Printer->printer_type == SPLHND_PRINTER) {
8753 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8754 status = WERR_BADFID;
8758 status = winreg_printer_update_changeid(tmp_ctx, b,
8759 lp_const_servicename(snum));
8763 talloc_free(tmp_ctx);
8767 /****************************************************************
8769 ****************************************************************/
8771 WERROR _spoolss_SetForm(struct pipes_struct *p,
8772 struct spoolss_SetForm *r)
8774 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8775 const char *form_name = r->in.form_name;
8777 WERROR status = WERR_OK;
8778 struct dcerpc_binding_handle *b;
8779 TALLOC_CTX *tmp_ctx = NULL;
8781 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8783 DEBUG(5,("_spoolss_SetForm\n"));
8786 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8787 OUR_HANDLE(r->in.handle)));
8791 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8792 and not a printer admin, then fail */
8794 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8795 !security_token_has_privilege(p->session_info->security_token,
8796 SEC_PRIV_PRINT_OPERATOR)) {
8797 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8798 return WERR_ACCESS_DENIED;
8801 tmp_ctx = talloc_new(p->mem_ctx);
8806 status = winreg_printer_binding_handle(tmp_ctx,
8807 get_session_info_system(),
8810 if (!W_ERROR_IS_OK(status)) {
8814 status = winreg_printer_setform1(tmp_ctx, b,
8817 if (!W_ERROR_IS_OK(status)) {
8822 * ChangeID must always be set if this is a printer
8824 if (Printer->printer_type == SPLHND_PRINTER) {
8825 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8826 status = WERR_BADFID;
8830 status = winreg_printer_update_changeid(tmp_ctx, b,
8831 lp_const_servicename(snum));
8835 talloc_free(tmp_ctx);
8839 /****************************************************************************
8840 fill_print_processor1
8841 ****************************************************************************/
8843 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8844 struct spoolss_PrintProcessorInfo1 *r,
8845 const char *print_processor_name)
8847 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8848 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8853 /****************************************************************************
8854 enumprintprocessors level 1.
8855 ****************************************************************************/
8857 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8858 union spoolss_PrintProcessorInfo **info_p,
8861 union spoolss_PrintProcessorInfo *info;
8864 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8865 W_ERROR_HAVE_NO_MEMORY(info);
8869 result = fill_print_processor1(info, &info[0].info1, "winprint");
8870 if (!W_ERROR_IS_OK(result)) {
8875 if (!W_ERROR_IS_OK(result)) {
8886 /****************************************************************
8887 _spoolss_EnumPrintProcessors
8888 ****************************************************************/
8890 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8891 struct spoolss_EnumPrintProcessors *r)
8895 /* that's an [in out] buffer */
8897 if (!r->in.buffer && (r->in.offered != 0)) {
8898 return WERR_INVALID_PARAM;
8901 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8904 * Enumerate the print processors ...
8906 * Just reply with "winprint", to keep NT happy
8907 * and I can use my nice printer checker.
8912 *r->out.info = NULL;
8914 if (!get_short_archi(r->in.environment)) {
8915 return WERR_INVALID_ENVIRONMENT;
8918 switch (r->in.level) {
8920 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8924 return WERR_UNKNOWN_LEVEL;
8927 if (!W_ERROR_IS_OK(result)) {
8931 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8932 spoolss_EnumPrintProcessors,
8933 *r->out.info, r->in.level,
8935 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8936 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8938 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8941 /****************************************************************************
8942 fill_printprocdatatype1
8943 ****************************************************************************/
8945 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8946 struct spoolss_PrintProcDataTypesInfo1 *r,
8947 const char *name_array)
8949 r->name_array = talloc_strdup(mem_ctx, name_array);
8950 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8955 /****************************************************************************
8956 enumprintprocdatatypes level 1.
8957 ****************************************************************************/
8959 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8960 union spoolss_PrintProcDataTypesInfo **info_p,
8964 union spoolss_PrintProcDataTypesInfo *info;
8966 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8967 W_ERROR_HAVE_NO_MEMORY(info);
8971 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8972 if (!W_ERROR_IS_OK(result)) {
8977 if (!W_ERROR_IS_OK(result)) {
8988 /****************************************************************
8989 _spoolss_EnumPrintProcDataTypes
8990 ****************************************************************/
8992 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8993 struct spoolss_EnumPrintProcDataTypes *r)
8997 /* that's an [in out] buffer */
8999 if (!r->in.buffer && (r->in.offered != 0)) {
9000 return WERR_INVALID_PARAM;
9003 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9007 *r->out.info = NULL;
9009 if (r->in.print_processor_name == NULL ||
9010 !strequal(r->in.print_processor_name, "winprint")) {
9011 return WERR_UNKNOWN_PRINTPROCESSOR;
9014 switch (r->in.level) {
9016 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9020 return WERR_UNKNOWN_LEVEL;
9023 if (!W_ERROR_IS_OK(result)) {
9027 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9028 spoolss_EnumPrintProcDataTypes,
9029 *r->out.info, r->in.level,
9031 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9032 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9034 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9037 /****************************************************************************
9039 ****************************************************************************/
9041 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9042 struct spoolss_MonitorInfo1 *r,
9043 const char *monitor_name)
9045 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9046 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9051 /****************************************************************************
9053 ****************************************************************************/
9055 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9056 struct spoolss_MonitorInfo2 *r,
9057 const char *monitor_name,
9058 const char *environment,
9059 const char *dll_name)
9061 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9062 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9063 r->environment = talloc_strdup(mem_ctx, environment);
9064 W_ERROR_HAVE_NO_MEMORY(r->environment);
9065 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9066 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9071 /****************************************************************************
9072 enumprintmonitors level 1.
9073 ****************************************************************************/
9075 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9076 union spoolss_MonitorInfo **info_p,
9079 union spoolss_MonitorInfo *info;
9080 WERROR result = WERR_OK;
9082 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9083 W_ERROR_HAVE_NO_MEMORY(info);
9087 result = fill_monitor_1(info, &info[0].info1,
9089 if (!W_ERROR_IS_OK(result)) {
9093 result = fill_monitor_1(info, &info[1].info1,
9095 if (!W_ERROR_IS_OK(result)) {
9100 if (!W_ERROR_IS_OK(result)) {
9111 /****************************************************************************
9112 enumprintmonitors level 2.
9113 ****************************************************************************/
9115 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9116 union spoolss_MonitorInfo **info_p,
9119 union spoolss_MonitorInfo *info;
9120 WERROR result = WERR_OK;
9122 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9123 W_ERROR_HAVE_NO_MEMORY(info);
9127 result = fill_monitor_2(info, &info[0].info2,
9129 "Windows NT X86", /* FIXME */
9131 if (!W_ERROR_IS_OK(result)) {
9135 result = fill_monitor_2(info, &info[1].info2,
9137 "Windows NT X86", /* FIXME */
9139 if (!W_ERROR_IS_OK(result)) {
9144 if (!W_ERROR_IS_OK(result)) {
9155 /****************************************************************
9156 _spoolss_EnumMonitors
9157 ****************************************************************/
9159 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9160 struct spoolss_EnumMonitors *r)
9164 /* that's an [in out] buffer */
9166 if (!r->in.buffer && (r->in.offered != 0)) {
9167 return WERR_INVALID_PARAM;
9170 DEBUG(5,("_spoolss_EnumMonitors\n"));
9173 * Enumerate the print monitors ...
9175 * Just reply with "Local Port", to keep NT happy
9176 * and I can use my nice printer checker.
9181 *r->out.info = NULL;
9183 switch (r->in.level) {
9185 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9189 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9193 return WERR_UNKNOWN_LEVEL;
9196 if (!W_ERROR_IS_OK(result)) {
9200 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9201 spoolss_EnumMonitors,
9202 *r->out.info, r->in.level,
9204 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9205 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9207 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9210 /****************************************************************************
9211 ****************************************************************************/
9213 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9214 const print_queue_struct *queue,
9215 int count, int snum,
9216 struct spoolss_PrinterInfo2 *pinfo2,
9218 struct spoolss_JobInfo1 *r)
9223 for (i=0; i<count; i++) {
9224 if (queue[i].sysjob == (int)jobid) {
9230 if (found == false) {
9231 /* NT treats not found as bad param... yet another bad choice */
9232 return WERR_INVALID_PARAM;
9235 return fill_job_info1(mem_ctx,
9243 /****************************************************************************
9244 ****************************************************************************/
9246 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9247 const print_queue_struct *queue,
9248 int count, int snum,
9249 struct spoolss_PrinterInfo2 *pinfo2,
9251 struct spoolss_JobInfo2 *r)
9255 struct spoolss_DeviceMode *devmode;
9258 for (i=0; i<count; i++) {
9259 if (queue[i].sysjob == (int)jobid) {
9265 if (found == false) {
9266 /* NT treats not found as bad param... yet another bad
9268 return WERR_INVALID_PARAM;
9272 * if the print job does not have a DEVMODE associated with it,
9273 * just use the one for the printer. A NULL devicemode is not
9274 * a failure condition
9277 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9279 result = spoolss_create_default_devmode(mem_ctx,
9280 pinfo2->printername,
9282 if (!W_ERROR_IS_OK(result)) {
9283 DEBUG(3, ("Can't proceed w/o a devmode!"));
9288 return fill_job_info2(mem_ctx,
9297 /****************************************************************
9299 ****************************************************************/
9301 WERROR _spoolss_GetJob(struct pipes_struct *p,
9302 struct spoolss_GetJob *r)
9304 WERROR result = WERR_OK;
9305 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9308 print_queue_struct *queue = NULL;
9309 print_status_struct prt_status;
9311 /* that's an [in out] buffer */
9313 if (!r->in.buffer && (r->in.offered != 0)) {
9314 return WERR_INVALID_PARAM;
9317 DEBUG(5,("_spoolss_GetJob\n"));
9321 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9325 result = winreg_get_printer_internal(p->mem_ctx,
9326 get_session_info_system(),
9328 lp_const_servicename(snum),
9330 if (!W_ERROR_IS_OK(result)) {
9334 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9336 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9337 count, prt_status.status, prt_status.message));
9339 switch (r->in.level) {
9341 result = getjob_level_1(p->mem_ctx,
9342 queue, count, snum, pinfo2,
9343 r->in.job_id, &r->out.info->info1);
9346 result = getjob_level_2(p->mem_ctx,
9347 queue, count, snum, pinfo2,
9348 r->in.job_id, &r->out.info->info2);
9351 result = WERR_UNKNOWN_LEVEL;
9356 TALLOC_FREE(pinfo2);
9358 if (!W_ERROR_IS_OK(result)) {
9359 TALLOC_FREE(r->out.info);
9363 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9365 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9367 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9370 /****************************************************************
9371 _spoolss_GetPrinterDataEx
9372 ****************************************************************/
9374 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9375 struct spoolss_GetPrinterDataEx *r)
9378 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9379 const char *printer;
9381 WERROR result = WERR_OK;
9383 enum winreg_Type val_type = REG_NONE;
9384 uint8_t *val_data = NULL;
9385 uint32_t val_size = 0;
9386 struct dcerpc_binding_handle *b;
9387 TALLOC_CTX *tmp_ctx;
9389 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9391 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9392 r->in.key_name, r->in.value_name));
9394 /* in case of problem, return some default values */
9397 *r->out.type = REG_NONE;
9399 tmp_ctx = talloc_new(p->mem_ctx);
9405 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9406 OUR_HANDLE(r->in.handle)));
9407 result = WERR_BADFID;
9411 /* check to see if the keyname is valid */
9412 if (!strlen(r->in.key_name)) {
9413 result = WERR_INVALID_PARAM;
9417 /* Is the handle to a printer or to the server? */
9419 if (Printer->printer_type == SPLHND_SERVER) {
9421 union spoolss_PrinterData data;
9423 result = getprinterdata_printer_server(tmp_ctx,
9427 if (!W_ERROR_IS_OK(result)) {
9431 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9432 *r->out.type, &data);
9433 if (!W_ERROR_IS_OK(result)) {
9437 *r->out.needed = blob.length;
9439 if (r->in.offered >= *r->out.needed) {
9440 memcpy(r->out.data, blob.data, blob.length);
9447 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9448 result = WERR_BADFID;
9451 printer = lp_const_servicename(snum);
9453 result = winreg_printer_binding_handle(tmp_ctx,
9454 get_session_info_system(),
9457 if (!W_ERROR_IS_OK(result)) {
9461 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9462 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9463 strequal(r->in.value_name, "ChangeId")) {
9464 *r->out.type = REG_DWORD;
9466 if (r->in.offered >= *r->out.needed) {
9467 uint32_t changeid = 0;
9469 result = winreg_printer_get_changeid(tmp_ctx, b,
9472 if (!W_ERROR_IS_OK(result)) {
9476 SIVAL(r->out.data, 0, changeid);
9482 result = winreg_get_printer_dataex(tmp_ctx, b,
9489 if (!W_ERROR_IS_OK(result)) {
9493 *r->out.needed = val_size;
9494 *r->out.type = val_type;
9496 if (r->in.offered >= *r->out.needed) {
9497 memcpy(r->out.data, val_data, val_size);
9501 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9503 if (W_ERROR_IS_OK(result)) {
9504 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9507 talloc_free(tmp_ctx);
9511 /****************************************************************
9512 _spoolss_SetPrinterDataEx
9513 ****************************************************************/
9515 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9516 struct spoolss_SetPrinterDataEx *r)
9518 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9520 WERROR result = WERR_OK;
9521 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9523 struct dcerpc_binding_handle *b;
9524 TALLOC_CTX *tmp_ctx;
9526 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9528 /* From MSDN documentation of SetPrinterDataEx: pass request to
9529 SetPrinterData if key is "PrinterDriverData" */
9532 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9533 OUR_HANDLE(r->in.handle)));
9537 if (Printer->printer_type == SPLHND_SERVER) {
9538 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9539 "Not implemented for server handles yet\n"));
9540 return WERR_INVALID_PARAM;
9543 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9548 * Access check : NT returns "access denied" if you make a
9549 * SetPrinterData call without the necessary privildge.
9550 * we were originally returning OK if nothing changed
9551 * which made Win2k issue **a lot** of SetPrinterData
9552 * when connecting to a printer --jerry
9555 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9556 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9557 "change denied by handle access permissions\n"));
9558 return WERR_ACCESS_DENIED;
9561 tmp_ctx = talloc_new(p->mem_ctx);
9566 result = winreg_printer_binding_handle(tmp_ctx,
9567 get_session_info_system(),
9570 if (!W_ERROR_IS_OK(result)) {
9574 result = winreg_get_printer(tmp_ctx, b,
9575 lp_servicename(snum),
9577 if (!W_ERROR_IS_OK(result)) {
9581 /* check for OID in valuename */
9583 oid_string = strchr(r->in.value_name, ',');
9589 /* save the registry data */
9591 result = winreg_set_printer_dataex(tmp_ctx, b,
9599 if (W_ERROR_IS_OK(result)) {
9600 /* save the OID if one was specified */
9602 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9603 r->in.key_name, SPOOL_OID_KEY);
9605 result = WERR_NOMEM;
9610 * I'm not checking the status here on purpose. Don't know
9611 * if this is right, but I'm returning the status from the
9612 * previous set_printer_dataex() call. I have no idea if
9613 * this is right. --jerry
9615 winreg_set_printer_dataex(tmp_ctx, b,
9620 (uint8_t *) oid_string,
9621 strlen(oid_string) + 1);
9624 result = winreg_printer_update_changeid(tmp_ctx, b,
9625 lp_const_servicename(snum));
9630 talloc_free(tmp_ctx);
9634 /****************************************************************
9635 _spoolss_DeletePrinterDataEx
9636 ****************************************************************/
9638 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9639 struct spoolss_DeletePrinterDataEx *r)
9641 const char *printer;
9643 WERROR status = WERR_OK;
9644 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9646 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9649 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9650 "Invalid handle (%s:%u:%u).\n",
9651 OUR_HANDLE(r->in.handle)));
9655 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9656 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9657 "printer properties change denied by handle\n"));
9658 return WERR_ACCESS_DENIED;
9661 if (!r->in.value_name || !r->in.key_name) {
9665 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9668 printer = lp_const_servicename(snum);
9670 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9671 get_session_info_system(),
9676 if (W_ERROR_IS_OK(status)) {
9677 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9678 get_session_info_system(),
9686 /****************************************************************
9687 _spoolss_EnumPrinterKey
9688 ****************************************************************/
9690 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9691 struct spoolss_EnumPrinterKey *r)
9694 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9696 WERROR result = WERR_BADFILE;
9697 const char **array = NULL;
9700 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9703 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9704 OUR_HANDLE(r->in.handle)));
9708 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9712 result = winreg_enum_printer_key_internal(p->mem_ctx,
9713 get_session_info_system(),
9715 lp_const_servicename(snum),
9719 if (!W_ERROR_IS_OK(result)) {
9723 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9724 result = WERR_NOMEM;
9728 *r->out._ndr_size = r->in.offered / 2;
9729 *r->out.needed = blob.length;
9731 if (r->in.offered < *r->out.needed) {
9732 result = WERR_MORE_DATA;
9735 r->out.key_buffer->string_array = array;
9739 if (!W_ERROR_IS_OK(result)) {
9741 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9749 /****************************************************************
9750 _spoolss_DeletePrinterKey
9751 ****************************************************************/
9753 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9754 struct spoolss_DeletePrinterKey *r)
9756 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9759 const char *printer;
9760 struct dcerpc_binding_handle *b;
9761 TALLOC_CTX *tmp_ctx;
9763 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9766 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9767 OUR_HANDLE(r->in.handle)));
9771 /* if keyname == NULL, return error */
9772 if ( !r->in.key_name )
9773 return WERR_INVALID_PARAM;
9775 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9779 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9780 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9781 "printer properties change denied by handle\n"));
9782 return WERR_ACCESS_DENIED;
9785 printer = lp_const_servicename(snum);
9787 tmp_ctx = talloc_new(p->mem_ctx);
9792 status = winreg_printer_binding_handle(tmp_ctx,
9793 get_session_info_system(),
9796 if (!W_ERROR_IS_OK(status)) {
9800 /* delete the key and all subkeys */
9801 status = winreg_delete_printer_key(tmp_ctx, b,
9804 if (W_ERROR_IS_OK(status)) {
9805 status = winreg_printer_update_changeid(tmp_ctx, b,
9810 talloc_free(tmp_ctx);
9814 /****************************************************************
9815 _spoolss_EnumPrinterDataEx
9816 ****************************************************************/
9818 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9819 struct spoolss_EnumPrinterDataEx *r)
9822 struct spoolss_PrinterEnumValues *info = NULL;
9823 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9827 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9831 *r->out.info = NULL;
9834 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9835 OUR_HANDLE(r->in.handle)));
9840 * first check for a keyname of NULL or "". Win2k seems to send
9841 * this a lot and we should send back WERR_INVALID_PARAM
9842 * no need to spend time looking up the printer in this case.
9846 if (!strlen(r->in.key_name)) {
9847 result = WERR_INVALID_PARAM;
9851 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9855 /* now look for a match on the key name */
9856 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9857 get_session_info_system(),
9859 lp_const_servicename(snum),
9863 if (!W_ERROR_IS_OK(result)) {
9867 #if 0 /* FIXME - gd */
9868 /* housekeeping information in the reply */
9870 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9871 * the hand marshalled container size is a multiple
9872 * of 4 bytes for RPC alignment.
9876 needed += 4-(needed % 4);
9879 *r->out.count = count;
9880 *r->out.info = info;
9883 if (!W_ERROR_IS_OK(result)) {
9887 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9888 spoolss_EnumPrinterDataEx,
9891 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9892 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9894 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9897 /****************************************************************************
9898 ****************************************************************************/
9900 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9901 const char *servername,
9902 const char *environment,
9903 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9908 werr = compose_spoolss_server_path(mem_ctx,
9911 SPOOLSS_PRTPROCS_PATH,
9913 if (!W_ERROR_IS_OK(werr)) {
9917 DEBUG(4,("print processor directory: [%s]\n", path));
9919 r->directory_name = path;
9924 /****************************************************************
9925 _spoolss_GetPrintProcessorDirectory
9926 ****************************************************************/
9928 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9929 struct spoolss_GetPrintProcessorDirectory *r)
9932 char *prnproc_share = NULL;
9933 bool prnproc_share_exists = false;
9936 /* that's an [in out] buffer */
9938 if (!r->in.buffer && (r->in.offered != 0)) {
9939 return WERR_INVALID_PARAM;
9942 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9947 /* r->in.level is ignored */
9949 /* We always should reply with a local print processor directory so that
9950 * users are not forced to have a [prnproc$] share on the Samba spoolss
9951 * server, if users decide to do so, lets announce it though - Guenther */
9953 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9954 if (!prnproc_share) {
9958 prnproc_share_exists = true;
9961 result = getprintprocessordirectory_level_1(p->mem_ctx,
9962 prnproc_share_exists ? r->in.server : NULL,
9964 &r->out.info->info1);
9965 if (!W_ERROR_IS_OK(result)) {
9966 TALLOC_FREE(r->out.info);
9970 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9971 r->out.info, r->in.level);
9972 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9974 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9977 /*******************************************************************
9978 ********************************************************************/
9980 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9981 const char *dllname)
9983 enum ndr_err_code ndr_err;
9984 struct spoolss_MonitorUi ui;
9986 ui.dll_name = dllname;
9988 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9989 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9990 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9991 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9993 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9996 /*******************************************************************
9997 Streams the monitor UI DLL name in UNICODE
9998 *******************************************************************/
10000 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10001 struct security_token *token, DATA_BLOB *in,
10002 DATA_BLOB *out, uint32_t *needed)
10004 const char *dllname = "tcpmonui.dll";
10006 *needed = (strlen(dllname)+1) * 2;
10008 if (out->length < *needed) {
10009 return WERR_INSUFFICIENT_BUFFER;
10012 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10019 /*******************************************************************
10020 ********************************************************************/
10022 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10023 struct spoolss_PortData1 *port1,
10024 const DATA_BLOB *buf)
10026 enum ndr_err_code ndr_err;
10027 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10028 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10029 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10030 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10032 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10035 /*******************************************************************
10036 ********************************************************************/
10038 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10039 struct spoolss_PortData2 *port2,
10040 const DATA_BLOB *buf)
10042 enum ndr_err_code ndr_err;
10043 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10044 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10045 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10046 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10048 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10051 /*******************************************************************
10052 Create a new TCP/IP port
10053 *******************************************************************/
10055 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10056 struct security_token *token, DATA_BLOB *in,
10057 DATA_BLOB *out, uint32_t *needed)
10059 struct spoolss_PortData1 port1;
10060 struct spoolss_PortData2 port2;
10061 char *device_uri = NULL;
10064 const char *portname;
10065 const char *hostaddress;
10067 uint32_t port_number;
10070 /* peek for spoolss_PortData version */
10072 if (!in || (in->length < (128 + 4))) {
10073 return WERR_GENERAL_FAILURE;
10076 version = IVAL(in->data, 128);
10080 ZERO_STRUCT(port1);
10082 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10086 portname = port1.portname;
10087 hostaddress = port1.hostaddress;
10088 queue = port1.queue;
10089 protocol = port1.protocol;
10090 port_number = port1.port_number;
10094 ZERO_STRUCT(port2);
10096 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10100 portname = port2.portname;
10101 hostaddress = port2.hostaddress;
10102 queue = port2.queue;
10103 protocol = port2.protocol;
10104 port_number = port2.port_number;
10108 DEBUG(1,("xcvtcp_addport: "
10109 "unknown version of port_data: %d\n", version));
10110 return WERR_UNKNOWN_PORT;
10113 /* create the device URI and call the add_port_hook() */
10115 switch (protocol) {
10116 case PROTOCOL_RAWTCP_TYPE:
10117 device_uri = talloc_asprintf(mem_ctx,
10118 "socket://%s:%d/", hostaddress,
10122 case PROTOCOL_LPR_TYPE:
10123 device_uri = talloc_asprintf(mem_ctx,
10124 "lpr://%s/%s", hostaddress, queue );
10128 return WERR_UNKNOWN_PORT;
10135 return add_port_hook(mem_ctx, token, portname, device_uri);
10138 /*******************************************************************
10139 *******************************************************************/
10141 struct xcv_api_table xcvtcp_cmds[] = {
10142 { "MonitorUI", xcvtcp_monitorui },
10143 { "AddPort", xcvtcp_addport},
10147 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10148 struct security_token *token, const char *command,
10155 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10157 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10158 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10159 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10162 return WERR_BADFUNC;
10165 /*******************************************************************
10166 *******************************************************************/
10167 #if 0 /* don't support management using the "Local Port" monitor */
10169 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10170 struct security_token *token, DATA_BLOB *in,
10171 DATA_BLOB *out, uint32_t *needed)
10173 const char *dllname = "localui.dll";
10175 *needed = (strlen(dllname)+1) * 2;
10177 if (out->length < *needed) {
10178 return WERR_INSUFFICIENT_BUFFER;
10181 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10188 /*******************************************************************
10189 *******************************************************************/
10191 struct xcv_api_table xcvlocal_cmds[] = {
10192 { "MonitorUI", xcvlocal_monitorui },
10196 struct xcv_api_table xcvlocal_cmds[] = {
10203 /*******************************************************************
10204 *******************************************************************/
10206 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10207 struct security_token *token, const char *command,
10208 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10213 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10215 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10216 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10217 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10219 return WERR_BADFUNC;
10222 /****************************************************************
10224 ****************************************************************/
10226 WERROR _spoolss_XcvData(struct pipes_struct *p,
10227 struct spoolss_XcvData *r)
10229 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10230 DATA_BLOB out_data = data_blob_null;
10234 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10235 OUR_HANDLE(r->in.handle)));
10236 return WERR_BADFID;
10239 /* Has to be a handle to the TCP/IP port monitor */
10241 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10242 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10243 return WERR_BADFID;
10246 /* requires administrative access to the server */
10248 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10249 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10250 return WERR_ACCESS_DENIED;
10253 /* Allocate the outgoing buffer */
10255 if (r->in.out_data_size) {
10256 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10257 if (out_data.data == NULL) {
10262 switch ( Printer->printer_type ) {
10263 case SPLHND_PORTMON_TCP:
10264 werror = process_xcvtcp_command(p->mem_ctx,
10265 p->session_info->security_token,
10266 r->in.function_name,
10267 &r->in.in_data, &out_data,
10270 case SPLHND_PORTMON_LOCAL:
10271 werror = process_xcvlocal_command(p->mem_ctx,
10272 p->session_info->security_token,
10273 r->in.function_name,
10274 &r->in.in_data, &out_data,
10278 werror = WERR_INVALID_PRINT_MONITOR;
10281 if (!W_ERROR_IS_OK(werror)) {
10285 *r->out.status_code = 0;
10287 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10288 memcpy(r->out.out_data, out_data.data,
10289 MIN(r->in.out_data_size, out_data.length));
10295 /****************************************************************
10296 _spoolss_AddPrintProcessor
10297 ****************************************************************/
10299 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10300 struct spoolss_AddPrintProcessor *r)
10302 /* for now, just indicate success and ignore the add. We'll
10303 automatically set the winprint processor for printer
10304 entries later. Used to debug the LexMark Optra S 1855 PCL
10310 /****************************************************************
10312 ****************************************************************/
10314 WERROR _spoolss_AddPort(struct pipes_struct *p,
10315 struct spoolss_AddPort *r)
10317 /* do what w2k3 does */
10319 return WERR_NOT_SUPPORTED;
10322 /****************************************************************
10323 _spoolss_GetPrinterDriver
10324 ****************************************************************/
10326 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10327 struct spoolss_GetPrinterDriver *r)
10329 p->rng_fault_state = true;
10330 return WERR_NOT_SUPPORTED;
10333 /****************************************************************
10334 _spoolss_ReadPrinter
10335 ****************************************************************/
10337 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10338 struct spoolss_ReadPrinter *r)
10340 p->rng_fault_state = true;
10341 return WERR_NOT_SUPPORTED;
10344 /****************************************************************
10345 _spoolss_WaitForPrinterChange
10346 ****************************************************************/
10348 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10349 struct spoolss_WaitForPrinterChange *r)
10351 p->rng_fault_state = true;
10352 return WERR_NOT_SUPPORTED;
10355 /****************************************************************
10356 _spoolss_ConfigurePort
10357 ****************************************************************/
10359 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10360 struct spoolss_ConfigurePort *r)
10362 p->rng_fault_state = true;
10363 return WERR_NOT_SUPPORTED;
10366 /****************************************************************
10367 _spoolss_DeletePort
10368 ****************************************************************/
10370 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10371 struct spoolss_DeletePort *r)
10373 p->rng_fault_state = true;
10374 return WERR_NOT_SUPPORTED;
10377 /****************************************************************
10378 _spoolss_CreatePrinterIC
10379 ****************************************************************/
10381 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10382 struct spoolss_CreatePrinterIC *r)
10384 p->rng_fault_state = true;
10385 return WERR_NOT_SUPPORTED;
10388 /****************************************************************
10389 _spoolss_PlayGDIScriptOnPrinterIC
10390 ****************************************************************/
10392 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10393 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10395 p->rng_fault_state = true;
10396 return WERR_NOT_SUPPORTED;
10399 /****************************************************************
10400 _spoolss_DeletePrinterIC
10401 ****************************************************************/
10403 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10404 struct spoolss_DeletePrinterIC *r)
10406 p->rng_fault_state = true;
10407 return WERR_NOT_SUPPORTED;
10410 /****************************************************************
10411 _spoolss_AddPrinterConnection
10412 ****************************************************************/
10414 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10415 struct spoolss_AddPrinterConnection *r)
10417 p->rng_fault_state = true;
10418 return WERR_NOT_SUPPORTED;
10421 /****************************************************************
10422 _spoolss_DeletePrinterConnection
10423 ****************************************************************/
10425 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10426 struct spoolss_DeletePrinterConnection *r)
10428 p->rng_fault_state = true;
10429 return WERR_NOT_SUPPORTED;
10432 /****************************************************************
10433 _spoolss_PrinterMessageBox
10434 ****************************************************************/
10436 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10437 struct spoolss_PrinterMessageBox *r)
10439 p->rng_fault_state = true;
10440 return WERR_NOT_SUPPORTED;
10443 /****************************************************************
10444 _spoolss_AddMonitor
10445 ****************************************************************/
10447 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10448 struct spoolss_AddMonitor *r)
10450 p->rng_fault_state = true;
10451 return WERR_NOT_SUPPORTED;
10454 /****************************************************************
10455 _spoolss_DeleteMonitor
10456 ****************************************************************/
10458 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10459 struct spoolss_DeleteMonitor *r)
10461 p->rng_fault_state = true;
10462 return WERR_NOT_SUPPORTED;
10465 /****************************************************************
10466 _spoolss_DeletePrintProcessor
10467 ****************************************************************/
10469 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10470 struct spoolss_DeletePrintProcessor *r)
10472 p->rng_fault_state = true;
10473 return WERR_NOT_SUPPORTED;
10476 /****************************************************************
10477 _spoolss_AddPrintProvidor
10478 ****************************************************************/
10480 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10481 struct spoolss_AddPrintProvidor *r)
10483 p->rng_fault_state = true;
10484 return WERR_NOT_SUPPORTED;
10487 /****************************************************************
10488 _spoolss_DeletePrintProvidor
10489 ****************************************************************/
10491 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10492 struct spoolss_DeletePrintProvidor *r)
10494 p->rng_fault_state = true;
10495 return WERR_NOT_SUPPORTED;
10498 /****************************************************************
10499 _spoolss_FindFirstPrinterChangeNotification
10500 ****************************************************************/
10502 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10503 struct spoolss_FindFirstPrinterChangeNotification *r)
10505 p->rng_fault_state = true;
10506 return WERR_NOT_SUPPORTED;
10509 /****************************************************************
10510 _spoolss_FindNextPrinterChangeNotification
10511 ****************************************************************/
10513 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10514 struct spoolss_FindNextPrinterChangeNotification *r)
10516 p->rng_fault_state = true;
10517 return WERR_NOT_SUPPORTED;
10520 /****************************************************************
10521 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10522 ****************************************************************/
10524 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10525 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10527 p->rng_fault_state = true;
10528 return WERR_NOT_SUPPORTED;
10531 /****************************************************************
10532 _spoolss_ReplyOpenPrinter
10533 ****************************************************************/
10535 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10536 struct spoolss_ReplyOpenPrinter *r)
10538 p->rng_fault_state = true;
10539 return WERR_NOT_SUPPORTED;
10542 /****************************************************************
10543 _spoolss_RouterReplyPrinter
10544 ****************************************************************/
10546 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10547 struct spoolss_RouterReplyPrinter *r)
10549 p->rng_fault_state = true;
10550 return WERR_NOT_SUPPORTED;
10553 /****************************************************************
10554 _spoolss_ReplyClosePrinter
10555 ****************************************************************/
10557 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10558 struct spoolss_ReplyClosePrinter *r)
10560 p->rng_fault_state = true;
10561 return WERR_NOT_SUPPORTED;
10564 /****************************************************************
10566 ****************************************************************/
10568 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10569 struct spoolss_AddPortEx *r)
10571 p->rng_fault_state = true;
10572 return WERR_NOT_SUPPORTED;
10575 /****************************************************************
10576 _spoolss_RouterFindFirstPrinterChangeNotification
10577 ****************************************************************/
10579 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10580 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10582 p->rng_fault_state = true;
10583 return WERR_NOT_SUPPORTED;
10586 /****************************************************************
10587 _spoolss_SpoolerInit
10588 ****************************************************************/
10590 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10591 struct spoolss_SpoolerInit *r)
10593 p->rng_fault_state = true;
10594 return WERR_NOT_SUPPORTED;
10597 /****************************************************************
10598 _spoolss_ResetPrinterEx
10599 ****************************************************************/
10601 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10602 struct spoolss_ResetPrinterEx *r)
10604 p->rng_fault_state = true;
10605 return WERR_NOT_SUPPORTED;
10608 /****************************************************************
10609 _spoolss_RouterReplyPrinterEx
10610 ****************************************************************/
10612 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10613 struct spoolss_RouterReplyPrinterEx *r)
10615 p->rng_fault_state = true;
10616 return WERR_NOT_SUPPORTED;
10619 /****************************************************************
10621 ****************************************************************/
10623 WERROR _spoolss_44(struct pipes_struct *p,
10624 struct spoolss_44 *r)
10626 p->rng_fault_state = true;
10627 return WERR_NOT_SUPPORTED;
10630 /****************************************************************
10632 ****************************************************************/
10634 WERROR _spoolss_SetPort(struct pipes_struct *p,
10635 struct spoolss_SetPort *r)
10637 p->rng_fault_state = true;
10638 return WERR_NOT_SUPPORTED;
10641 /****************************************************************
10643 ****************************************************************/
10645 WERROR _spoolss_4a(struct pipes_struct *p,
10646 struct spoolss_4a *r)
10648 p->rng_fault_state = true;
10649 return WERR_NOT_SUPPORTED;
10652 /****************************************************************
10654 ****************************************************************/
10656 WERROR _spoolss_4b(struct pipes_struct *p,
10657 struct spoolss_4b *r)
10659 p->rng_fault_state = true;
10660 return WERR_NOT_SUPPORTED;
10663 /****************************************************************
10665 ****************************************************************/
10667 WERROR _spoolss_4c(struct pipes_struct *p,
10668 struct spoolss_4c *r)
10670 p->rng_fault_state = true;
10671 return WERR_NOT_SUPPORTED;
10674 /****************************************************************
10676 ****************************************************************/
10678 WERROR _spoolss_53(struct pipes_struct *p,
10679 struct spoolss_53 *r)
10681 p->rng_fault_state = true;
10682 return WERR_NOT_SUPPORTED;
10685 /****************************************************************
10686 _spoolss_AddPerMachineConnection
10687 ****************************************************************/
10689 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10690 struct spoolss_AddPerMachineConnection *r)
10692 p->rng_fault_state = true;
10693 return WERR_NOT_SUPPORTED;
10696 /****************************************************************
10697 _spoolss_DeletePerMachineConnection
10698 ****************************************************************/
10700 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10701 struct spoolss_DeletePerMachineConnection *r)
10703 p->rng_fault_state = true;
10704 return WERR_NOT_SUPPORTED;
10707 /****************************************************************
10708 _spoolss_EnumPerMachineConnections
10709 ****************************************************************/
10711 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10712 struct spoolss_EnumPerMachineConnections *r)
10714 p->rng_fault_state = true;
10715 return WERR_NOT_SUPPORTED;
10718 /****************************************************************
10720 ****************************************************************/
10722 WERROR _spoolss_5a(struct pipes_struct *p,
10723 struct spoolss_5a *r)
10725 p->rng_fault_state = true;
10726 return WERR_NOT_SUPPORTED;
10729 /****************************************************************
10731 ****************************************************************/
10733 WERROR _spoolss_5b(struct pipes_struct *p,
10734 struct spoolss_5b *r)
10736 p->rng_fault_state = true;
10737 return WERR_NOT_SUPPORTED;
10740 /****************************************************************
10742 ****************************************************************/
10744 WERROR _spoolss_5c(struct pipes_struct *p,
10745 struct spoolss_5c *r)
10747 p->rng_fault_state = true;
10748 return WERR_NOT_SUPPORTED;
10751 /****************************************************************
10753 ****************************************************************/
10755 WERROR _spoolss_5d(struct pipes_struct *p,
10756 struct spoolss_5d *r)
10758 p->rng_fault_state = true;
10759 return WERR_NOT_SUPPORTED;
10762 /****************************************************************
10764 ****************************************************************/
10766 WERROR _spoolss_5e(struct pipes_struct *p,
10767 struct spoolss_5e *r)
10769 p->rng_fault_state = true;
10770 return WERR_NOT_SUPPORTED;
10773 /****************************************************************
10775 ****************************************************************/
10777 WERROR _spoolss_5f(struct pipes_struct *p,
10778 struct spoolss_5f *r)
10780 p->rng_fault_state = true;
10781 return WERR_NOT_SUPPORTED;
10784 /****************************************************************
10786 ****************************************************************/
10788 WERROR _spoolss_60(struct pipes_struct *p,
10789 struct spoolss_60 *r)
10791 p->rng_fault_state = true;
10792 return WERR_NOT_SUPPORTED;
10795 /****************************************************************
10797 ****************************************************************/
10799 WERROR _spoolss_61(struct pipes_struct *p,
10800 struct spoolss_61 *r)
10802 p->rng_fault_state = true;
10803 return WERR_NOT_SUPPORTED;
10806 /****************************************************************
10808 ****************************************************************/
10810 WERROR _spoolss_62(struct pipes_struct *p,
10811 struct spoolss_62 *r)
10813 p->rng_fault_state = true;
10814 return WERR_NOT_SUPPORTED;
10817 /****************************************************************
10819 ****************************************************************/
10821 WERROR _spoolss_63(struct pipes_struct *p,
10822 struct spoolss_63 *r)
10824 p->rng_fault_state = true;
10825 return WERR_NOT_SUPPORTED;
10828 /****************************************************************
10830 ****************************************************************/
10832 WERROR _spoolss_64(struct pipes_struct *p,
10833 struct spoolss_64 *r)
10835 p->rng_fault_state = true;
10836 return WERR_NOT_SUPPORTED;
10839 /****************************************************************
10841 ****************************************************************/
10843 WERROR _spoolss_65(struct pipes_struct *p,
10844 struct spoolss_65 *r)
10846 p->rng_fault_state = true;
10847 return WERR_NOT_SUPPORTED;
10850 /****************************************************************
10851 _spoolss_GetCorePrinterDrivers
10852 ****************************************************************/
10854 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10855 struct spoolss_GetCorePrinterDrivers *r)
10857 p->rng_fault_state = true;
10858 return WERR_NOT_SUPPORTED;
10861 /****************************************************************
10863 ****************************************************************/
10865 WERROR _spoolss_67(struct pipes_struct *p,
10866 struct spoolss_67 *r)
10868 p->rng_fault_state = true;
10869 return WERR_NOT_SUPPORTED;
10872 /****************************************************************
10873 _spoolss_GetPrinterDriverPackagePath
10874 ****************************************************************/
10876 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10877 struct spoolss_GetPrinterDriverPackagePath *r)
10879 p->rng_fault_state = true;
10880 return WERR_NOT_SUPPORTED;
10883 /****************************************************************
10885 ****************************************************************/
10887 WERROR _spoolss_69(struct pipes_struct *p,
10888 struct spoolss_69 *r)
10890 p->rng_fault_state = true;
10891 return WERR_NOT_SUPPORTED;
10894 /****************************************************************
10896 ****************************************************************/
10898 WERROR _spoolss_6a(struct pipes_struct *p,
10899 struct spoolss_6a *r)
10901 p->rng_fault_state = true;
10902 return WERR_NOT_SUPPORTED;
10905 /****************************************************************
10907 ****************************************************************/
10909 WERROR _spoolss_6b(struct pipes_struct *p,
10910 struct spoolss_6b *r)
10912 p->rng_fault_state = true;
10913 return WERR_NOT_SUPPORTED;
10916 /****************************************************************
10918 ****************************************************************/
10920 WERROR _spoolss_6c(struct pipes_struct *p,
10921 struct spoolss_6c *r)
10923 p->rng_fault_state = true;
10924 return WERR_NOT_SUPPORTED;
10927 /****************************************************************
10929 ****************************************************************/
10931 WERROR _spoolss_6d(struct pipes_struct *p,
10932 struct spoolss_6d *r)
10934 p->rng_fault_state = true;
10935 return WERR_NOT_SUPPORTED;