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(talloc_tos());
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;
1635 struct spoolss_UserLevel1 level1;
1638 ZERO_STRUCT(level1);
1640 e.in.printername = r->in.printername;
1641 e.in.datatype = r->in.datatype;
1642 e.in.devmode_ctr = r->in.devmode_ctr;
1643 e.in.access_mask = r->in.access_mask;
1644 e.in.userlevel_ctr.level = 1;
1645 e.in.userlevel_ctr.user_info.level1 = &level1;
1647 e.out.handle = r->out.handle;
1649 werr = _spoolss_OpenPrinterEx(p, &e);
1651 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1652 /* OpenPrinterEx returns this for a bad
1653 * printer name. We must return WERR_INVALID_PRINTER_NAME
1656 werr = WERR_INVALID_PRINTER_NAME;
1662 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1663 struct spoolss_DeviceMode *orig,
1664 struct spoolss_DeviceMode **dest)
1666 struct spoolss_DeviceMode *dm;
1668 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1673 /* copy all values, then duplicate strings and structs */
1676 dm->devicename = talloc_strdup(dm, orig->devicename);
1677 if (!dm->devicename) {
1680 dm->formname = talloc_strdup(dm, orig->formname);
1681 if (!dm->formname) {
1684 if (orig->driverextra_data.data) {
1685 dm->driverextra_data.data =
1686 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1687 orig->driverextra_data.length);
1688 if (!dm->driverextra_data.data) {
1697 /****************************************************************
1698 _spoolss_OpenPrinterEx
1699 ****************************************************************/
1701 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1702 struct spoolss_OpenPrinterEx *r)
1707 struct printer_handle *Printer=NULL;
1711 if (!r->in.printername) {
1712 return WERR_INVALID_PARAM;
1715 if (!*r->in.printername) {
1716 return WERR_INVALID_PARAM;
1719 if (r->in.userlevel_ctr.level > 3) {
1720 return WERR_INVALID_PARAM;
1722 if ((r->in.userlevel_ctr.level == 1 && !r->in.userlevel_ctr.user_info.level1) ||
1723 (r->in.userlevel_ctr.level == 2 && !r->in.userlevel_ctr.user_info.level2) ||
1724 (r->in.userlevel_ctr.level == 3 && !r->in.userlevel_ctr.user_info.level3)) {
1725 return WERR_INVALID_PARAM;
1728 /* some sanity check because you can open a printer or a print server */
1729 /* aka: \\server\printer or \\server */
1731 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1733 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1734 if (!W_ERROR_IS_OK(result)) {
1735 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1736 "for printer %s\n", r->in.printername));
1737 ZERO_STRUCTP(r->out.handle);
1741 Printer = find_printer_index_by_hnd(p, r->out.handle);
1743 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1744 "handle we created for printer %s\n", r->in.printername));
1745 close_printer_handle(p, r->out.handle);
1746 ZERO_STRUCTP(r->out.handle);
1747 return WERR_INVALID_PARAM;
1751 * First case: the user is opening the print server:
1753 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1754 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1756 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1757 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1758 * or if the user is listed in the smb.conf printer admin parameter.
1760 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1761 * client view printer folder, but does not show the MSAPW.
1763 * Note: this test needs code to check access rights here too. Jeremy
1764 * could you look at this?
1766 * Second case: the user is opening a printer:
1767 * NT doesn't let us connect to a printer if the connecting user
1768 * doesn't have print permission.
1770 * Third case: user is opening a Port Monitor
1771 * access checks same as opening a handle to the print server.
1774 switch (Printer->printer_type )
1777 case SPLHND_PORTMON_TCP:
1778 case SPLHND_PORTMON_LOCAL:
1779 /* Printserver handles use global struct... */
1783 /* Map standard access rights to object specific access rights */
1785 se_map_standard(&r->in.access_mask,
1786 &printserver_std_mapping);
1788 /* Deny any object specific bits that don't apply to print
1789 servers (i.e printer and job specific bits) */
1791 r->in.access_mask &= SEC_MASK_SPECIFIC;
1793 if (r->in.access_mask &
1794 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1795 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1796 close_printer_handle(p, r->out.handle);
1797 ZERO_STRUCTP(r->out.handle);
1798 return WERR_ACCESS_DENIED;
1801 /* Allow admin access */
1803 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1805 if (!lp_ms_add_printer_wizard()) {
1806 close_printer_handle(p, r->out.handle);
1807 ZERO_STRUCTP(r->out.handle);
1808 return WERR_ACCESS_DENIED;
1811 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1812 and not a printer admin, then fail */
1814 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1815 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1816 !nt_token_check_sid(&global_sid_Builtin_Print_Operators,
1817 p->session_info->security_token)) {
1818 close_printer_handle(p, r->out.handle);
1819 ZERO_STRUCTP(r->out.handle);
1820 DEBUG(3,("access DENIED as user is not root, "
1821 "has no printoperator privilege, "
1822 "not a member of the printoperator builtin group and "
1823 "is not in printer admin list"));
1824 return WERR_ACCESS_DENIED;
1827 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1831 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1834 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1835 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1837 /* We fall through to return WERR_OK */
1840 case SPLHND_PRINTER:
1841 /* NT doesn't let us connect to a printer if the connecting user
1842 doesn't have print permission. */
1844 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1845 close_printer_handle(p, r->out.handle);
1846 ZERO_STRUCTP(r->out.handle);
1850 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1851 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1854 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1856 /* map an empty access mask to the minimum access mask */
1857 if (r->in.access_mask == 0x0)
1858 r->in.access_mask = PRINTER_ACCESS_USE;
1861 * If we are not serving the printer driver for this printer,
1862 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1863 * will keep NT clients happy --jerry
1866 if (lp_use_client_driver(snum)
1867 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1869 r->in.access_mask = PRINTER_ACCESS_USE;
1872 /* check smb.conf parameters and the the sec_desc */
1873 raddr = tsocket_address_inet_addr_string(p->remote_address,
1875 if (raddr == NULL) {
1879 rc = get_remote_hostname(p->remote_address,
1885 if (strequal(rhost, "UNKNOWN")) {
1889 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1891 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1892 ZERO_STRUCTP(r->out.handle);
1893 return WERR_ACCESS_DENIED;
1896 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1897 p->session_info->security_token, snum) ||
1898 !print_access_check(p->session_info,
1901 r->in.access_mask)) {
1902 DEBUG(3, ("access DENIED for printer open\n"));
1903 close_printer_handle(p, r->out.handle);
1904 ZERO_STRUCTP(r->out.handle);
1905 return WERR_ACCESS_DENIED;
1908 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1909 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1910 close_printer_handle(p, r->out.handle);
1911 ZERO_STRUCTP(r->out.handle);
1912 return WERR_ACCESS_DENIED;
1915 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1916 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1918 r->in.access_mask = PRINTER_ACCESS_USE;
1920 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1921 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1923 winreg_create_printer_internal(p->mem_ctx,
1924 get_session_info_system(),
1926 lp_const_servicename(snum));
1931 /* sanity check to prevent programmer error */
1932 ZERO_STRUCTP(r->out.handle);
1936 Printer->access_granted = r->in.access_mask;
1939 * If the client sent a devmode in the OpenPrinter() call, then
1940 * save it here in case we get a job submission on this handle
1943 if ((Printer->printer_type != SPLHND_SERVER)
1944 && (r->in.devmode_ctr.devmode != NULL)) {
1945 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1952 /****************************************************************
1953 _spoolss_ClosePrinter
1954 ****************************************************************/
1956 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1957 struct spoolss_ClosePrinter *r)
1959 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1961 if (Printer && Printer->document_started) {
1962 struct spoolss_EndDocPrinter e;
1964 e.in.handle = r->in.handle;
1966 _spoolss_EndDocPrinter(p, &e);
1969 if (!close_printer_handle(p, r->in.handle))
1972 /* clear the returned printer handle. Observed behavior
1973 from Win2k server. Don't think this really matters.
1974 Previous code just copied the value of the closed
1977 ZERO_STRUCTP(r->out.handle);
1982 /****************************************************************
1983 _spoolss_DeletePrinter
1984 ****************************************************************/
1986 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
1987 struct spoolss_DeletePrinter *r)
1989 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1993 if (Printer && Printer->document_started) {
1994 struct spoolss_EndDocPrinter e;
1996 e.in.handle = r->in.handle;
1998 _spoolss_EndDocPrinter(p, &e);
2001 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2002 winreg_delete_printer_key_internal(p->mem_ctx,
2003 get_session_info_system(),
2005 lp_const_servicename(snum),
2009 result = delete_printer_handle(p, r->in.handle);
2014 /*******************************************************************
2015 * static function to lookup the version id corresponding to an
2016 * long architecture string
2017 ******************************************************************/
2019 static const struct print_architecture_table_node archi_table[]= {
2021 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2022 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2023 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2024 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2025 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2026 {"Windows IA64", SPL_ARCH_IA64, 3 },
2027 {"Windows x64", SPL_ARCH_X64, 3 },
2031 static const int drv_cversion[] = {SPOOLSS_DRIVER_VERSION_9X,
2032 SPOOLSS_DRIVER_VERSION_NT35,
2033 SPOOLSS_DRIVER_VERSION_NT4,
2034 SPOOLSS_DRIVER_VERSION_200X,
2037 static int get_version_id(const char *arch)
2041 for (i=0; archi_table[i].long_archi != NULL; i++)
2043 if (strcmp(arch, archi_table[i].long_archi) == 0)
2044 return (archi_table[i].version);
2050 /****************************************************************
2051 _spoolss_DeletePrinterDriver
2052 ****************************************************************/
2054 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2055 struct spoolss_DeletePrinterDriver *r)
2058 struct spoolss_DriverInfo8 *info = NULL;
2061 struct dcerpc_binding_handle *b;
2062 TALLOC_CTX *tmp_ctx = NULL;
2066 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2067 and not a printer admin, then fail */
2069 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2070 !security_token_has_privilege(p->session_info->security_token,
2071 SEC_PRIV_PRINT_OPERATOR)) {
2072 return WERR_ACCESS_DENIED;
2075 /* check that we have a valid driver name first */
2077 if ((version = get_version_id(r->in.architecture)) == -1) {
2078 return WERR_INVALID_ENVIRONMENT;
2081 tmp_ctx = talloc_new(p->mem_ctx);
2086 status = winreg_printer_binding_handle(tmp_ctx,
2087 get_session_info_system(),
2090 if (!W_ERROR_IS_OK(status)) {
2094 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2095 status = winreg_get_driver(tmp_ctx, b,
2096 r->in.architecture, r->in.driver,
2097 drv_cversion[i], &info);
2098 if (!W_ERROR_IS_OK(status)) {
2099 DEBUG(5, ("skipping del of driver with version %d\n",
2105 if (printer_driver_in_use(tmp_ctx, b, info)) {
2106 status = WERR_PRINTER_DRIVER_IN_USE;
2110 status = winreg_del_driver(tmp_ctx, b, info, drv_cversion[i]);
2111 if (!W_ERROR_IS_OK(status)) {
2112 DEBUG(0, ("failed del of driver with version %d\n",
2117 if (found == false) {
2118 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2119 status = WERR_UNKNOWN_PRINTER_DRIVER;
2125 talloc_free(tmp_ctx);
2130 static WERROR spoolss_dpd_version(TALLOC_CTX *mem_ctx,
2131 struct pipes_struct *p,
2132 struct spoolss_DeletePrinterDriverEx *r,
2133 struct dcerpc_binding_handle *b,
2134 struct spoolss_DriverInfo8 *info)
2139 if (printer_driver_in_use(mem_ctx, b, info)) {
2140 status = WERR_PRINTER_DRIVER_IN_USE;
2145 * we have a couple of cases to consider.
2146 * (1) Are any files in use? If so and DPD_DELETE_ALL_FILES is set,
2147 * then the delete should fail if **any** files overlap with
2149 * (2) If DPD_DELETE_UNUSED_FILES is set, then delete all
2150 * non-overlapping files
2151 * (3) If neither DPD_DELETE_ALL_FILES nor DPD_DELETE_UNUSED_FILES
2152 * are set, then do not delete any files
2153 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2156 delete_files = r->in.delete_flags
2157 & (DPD_DELETE_ALL_FILES | DPD_DELETE_UNUSED_FILES);
2161 bool in_use = printer_driver_files_in_use(mem_ctx, b, info);
2162 if (in_use && (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2163 status = WERR_PRINTER_DRIVER_IN_USE;
2167 * printer_driver_files_in_use() has trimmed overlapping files
2168 * from info so they are not removed on DPD_DELETE_UNUSED_FILES
2173 status = winreg_del_driver(mem_ctx, b, info, info->version);
2174 if (!W_ERROR_IS_OK(status)) {
2179 * now delete any associated files if delete_files is
2180 * true. Even if this part failes, we return succes
2181 * because the driver doesn not exist any more
2184 delete_driver_files(p->session_info, info);
2191 /****************************************************************
2192 _spoolss_DeletePrinterDriverEx
2193 ****************************************************************/
2195 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2196 struct spoolss_DeletePrinterDriverEx *r)
2198 struct spoolss_DriverInfo8 *info = NULL;
2200 struct dcerpc_binding_handle *b;
2201 TALLOC_CTX *tmp_ctx = NULL;
2205 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2206 and not a printer admin, then fail */
2208 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
2209 !security_token_has_privilege(p->session_info->security_token,
2210 SEC_PRIV_PRINT_OPERATOR)) {
2211 return WERR_ACCESS_DENIED;
2214 /* check that we have a valid driver name first */
2215 if (get_version_id(r->in.architecture) == -1) {
2216 /* this is what NT returns */
2217 return WERR_INVALID_ENVIRONMENT;
2220 tmp_ctx = talloc_new(p->mem_ctx);
2225 status = winreg_printer_binding_handle(tmp_ctx,
2226 get_session_info_system(),
2229 if (!W_ERROR_IS_OK(status)) {
2233 for (found = false, i = 0; drv_cversion[i] >= 0; i++) {
2234 if ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2235 && (drv_cversion[i] != r->in.version)) {
2239 /* check if a driver with this version exists before delete */
2240 status = winreg_get_driver(tmp_ctx, b,
2241 r->in.architecture, r->in.driver,
2242 drv_cversion[i], &info);
2243 if (!W_ERROR_IS_OK(status)) {
2244 DEBUG(5, ("skipping del of driver with version %d\n",
2250 status = spoolss_dpd_version(tmp_ctx, p, r, b, info);
2251 if (!W_ERROR_IS_OK(status)) {
2252 DEBUG(0, ("failed to delete driver with version %d\n",
2257 if (found == false) {
2258 DEBUG(0, ("driver %s not found for deletion\n", r->in.driver));
2259 status = WERR_UNKNOWN_PRINTER_DRIVER;
2265 talloc_free(tmp_ctx);
2270 /********************************************************************
2271 GetPrinterData on a printer server Handle.
2272 ********************************************************************/
2274 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2276 enum winreg_Type *type,
2277 union spoolss_PrinterData *data)
2279 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2281 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2283 SIVAL(&data->value, 0, 0x00);
2287 if (!strcasecmp_m(value, "BeepEnabled")) {
2289 SIVAL(&data->value, 0, 0x00);
2293 if (!strcasecmp_m(value, "EventLog")) {
2295 /* formally was 0x1b */
2296 SIVAL(&data->value, 0, 0x00);
2300 if (!strcasecmp_m(value, "NetPopup")) {
2302 SIVAL(&data->value, 0, 0x00);
2306 if (!strcasecmp_m(value, "MajorVersion")) {
2309 /* Windows NT 4.0 seems to not allow uploading of drivers
2310 to a server that reports 0x3 as the MajorVersion.
2311 need to investigate more how Win2k gets around this .
2314 if (RA_WINNT == get_remote_arch()) {
2315 SIVAL(&data->value, 0, 0x02);
2317 SIVAL(&data->value, 0, 0x03);
2323 if (!strcasecmp_m(value, "MinorVersion")) {
2325 SIVAL(&data->value, 0, 0x00);
2330 * uint32_t size = 0x114
2331 * uint32_t major = 5
2332 * uint32_t minor = [0|1]
2333 * uint32_t build = [2195|2600]
2334 * extra unicode string = e.g. "Service Pack 3"
2336 if (!strcasecmp_m(value, "OSVersion")) {
2338 enum ndr_err_code ndr_err;
2339 struct spoolss_OSVersion os;
2341 os.major = 5; /* Windows 2000 == 5.0 */
2343 os.build = 2195; /* build */
2344 os.extra_string = ""; /* leave extra string empty */
2346 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2347 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2348 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2349 return WERR_GENERAL_FAILURE;
2353 data->binary = blob;
2359 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2362 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2363 W_ERROR_HAVE_NO_MEMORY(data->string);
2368 if (!strcasecmp_m(value, "Architecture")) {
2370 data->string = talloc_strdup(mem_ctx,
2371 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2372 W_ERROR_HAVE_NO_MEMORY(data->string);
2377 if (!strcasecmp_m(value, "DsPresent")) {
2380 /* only show the publish check box if we are a
2381 member of a AD domain */
2383 if (lp_security() == SEC_ADS) {
2384 SIVAL(&data->value, 0, 0x01);
2386 SIVAL(&data->value, 0, 0x00);
2391 if (!strcasecmp_m(value, "DNSMachineName")) {
2392 const char *hostname = get_mydnsfullname();
2395 return WERR_BADFILE;
2399 data->string = talloc_strdup(mem_ctx, hostname);
2400 W_ERROR_HAVE_NO_MEMORY(data->string);
2407 return WERR_INVALID_PARAM;
2410 /****************************************************************
2411 _spoolss_GetPrinterData
2412 ****************************************************************/
2414 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2415 struct spoolss_GetPrinterData *r)
2417 struct spoolss_GetPrinterDataEx r2;
2419 r2.in.handle = r->in.handle;
2420 r2.in.key_name = "PrinterDriverData";
2421 r2.in.value_name = r->in.value_name;
2422 r2.in.offered = r->in.offered;
2423 r2.out.type = r->out.type;
2424 r2.out.data = r->out.data;
2425 r2.out.needed = r->out.needed;
2427 return _spoolss_GetPrinterDataEx(p, &r2);
2430 /*********************************************************
2431 Connect to the client machine.
2432 **********************************************************/
2434 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2435 struct sockaddr_storage *client_ss, const char *remote_machine)
2438 struct cli_state *the_cli;
2439 struct sockaddr_storage rm_addr;
2440 char addr[INET6_ADDRSTRLEN];
2442 if ( is_zero_addr(client_ss) ) {
2443 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2445 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2446 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2449 print_sockaddr(addr, sizeof(addr), &rm_addr);
2451 rm_addr = *client_ss;
2452 print_sockaddr(addr, sizeof(addr), &rm_addr);
2453 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2457 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2458 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2463 /* setup the connection */
2464 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2465 &rm_addr, 0, "IPC$", "IPC",
2469 0, lp_client_signing());
2471 if ( !NT_STATUS_IS_OK( ret ) ) {
2472 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2477 if ( smbXcli_conn_protocol(the_cli->conn) != PROTOCOL_NT1 ) {
2478 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2479 cli_shutdown(the_cli);
2484 * Ok - we have an anonymous connection to the IPC$ share.
2485 * Now start the NT Domain stuff :-).
2488 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2489 if (!NT_STATUS_IS_OK(ret)) {
2490 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2491 remote_machine, nt_errstr(ret)));
2492 cli_shutdown(the_cli);
2499 /***************************************************************************
2500 Connect to the client.
2501 ****************************************************************************/
2503 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2504 uint32_t localprinter,
2505 enum winreg_Type type,
2506 struct policy_handle *handle,
2507 struct notify_back_channel **_chan,
2508 struct sockaddr_storage *client_ss,
2509 struct messaging_context *msg_ctx)
2513 struct notify_back_channel *chan;
2515 for (chan = back_channels; chan; chan = chan->next) {
2516 if (memcmp(&chan->client_address, client_ss,
2517 sizeof(struct sockaddr_storage)) == 0) {
2523 * If it's the first connection, contact the client
2524 * and connect to the IPC$ share anonymously
2527 fstring unix_printer;
2529 /* the +2 is to strip the leading 2 backslashs */
2530 fstrcpy(unix_printer, printer + 2);
2532 chan = talloc_zero(NULL, struct notify_back_channel);
2536 chan->client_address = *client_ss;
2538 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2543 DLIST_ADD(back_channels, chan);
2545 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2546 receive_notify2_message_list);
2549 if (chan->cli_pipe == NULL ||
2550 chan->cli_pipe->binding_handle == NULL) {
2551 DEBUG(0, ("srv_spoolss_replyopenprinter: error - "
2552 "NULL %s for printer %s\n",
2553 chan->cli_pipe == NULL ?
2554 "chan->cli_pipe" : "chan->cli_pipe->binding_handle",
2560 * Tell the specific printing tdb we want messages for this printer
2561 * by registering our PID.
2564 if (!print_notify_register_pid(snum)) {
2565 DEBUG(0, ("Failed to register our pid for printer %s\n",
2569 status = dcerpc_spoolss_ReplyOpenPrinter(chan->cli_pipe->binding_handle,
2578 if (!NT_STATUS_IS_OK(status)) {
2579 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2580 result = ntstatus_to_werror(status);
2581 } else if (!W_ERROR_IS_OK(result)) {
2582 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2585 chan->active_connections++;
2588 return (W_ERROR_IS_OK(result));
2591 /****************************************************************
2592 ****************************************************************/
2594 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2595 const struct spoolss_NotifyOption *r)
2597 struct spoolss_NotifyOption *option;
2604 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2611 if (!option->count) {
2615 option->types = talloc_zero_array(option,
2616 struct spoolss_NotifyOptionType, option->count);
2617 if (!option->types) {
2618 talloc_free(option);
2622 for (i=0; i < option->count; i++) {
2623 option->types[i] = r->types[i];
2625 if (option->types[i].count) {
2626 option->types[i].fields = talloc_zero_array(option,
2627 union spoolss_Field, option->types[i].count);
2628 if (!option->types[i].fields) {
2629 talloc_free(option);
2632 for (k=0; k<option->types[i].count; k++) {
2633 option->types[i].fields[k] =
2634 r->types[i].fields[k];
2642 /****************************************************************
2643 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2645 * before replying OK: status=0 a rpc call is made to the workstation
2646 * asking ReplyOpenPrinter
2648 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2649 * called from api_spoolss_rffpcnex
2650 ****************************************************************/
2652 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2653 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2656 struct spoolss_NotifyOption *option = r->in.notify_options;
2657 struct sockaddr_storage client_ss;
2660 /* store the notify value in the printer struct */
2662 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2665 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2666 "Invalid handle (%s:%u:%u).\n",
2667 OUR_HANDLE(r->in.handle)));
2671 Printer->notify.flags = r->in.flags;
2672 Printer->notify.options = r->in.options;
2673 Printer->notify.printerlocal = r->in.printer_local;
2674 Printer->notify.msg_ctx = p->msg_ctx;
2676 TALLOC_FREE(Printer->notify.option);
2677 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2679 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2681 /* Connect to the client machine and send a ReplyOpenPrinter */
2683 if ( Printer->printer_type == SPLHND_SERVER)
2685 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2686 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2689 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2690 "remote_address is %s\n",
2691 tsocket_address_string(p->remote_address, p->mem_ctx)));
2693 if (!lp_print_notify_backchannel(snum)) {
2694 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2695 "backchannel disabled\n"));
2696 return WERR_SERVER_UNAVAILABLE;
2699 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2700 (struct sockaddr *) &client_ss,
2701 sizeof(struct sockaddr_storage));
2702 if (client_len < 0) {
2706 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2707 Printer->notify.printerlocal, REG_SZ,
2708 &Printer->notify.cli_hnd,
2709 &Printer->notify.cli_chan,
2710 &client_ss, p->msg_ctx)) {
2711 return WERR_SERVER_UNAVAILABLE;
2717 /*******************************************************************
2718 * fill a notify_info_data with the servername
2719 ********************************************************************/
2721 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2723 struct spoolss_Notify *data,
2724 print_queue_struct *queue,
2725 struct spoolss_PrinterInfo2 *pinfo2,
2726 TALLOC_CTX *mem_ctx)
2728 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2731 /*******************************************************************
2732 * fill a notify_info_data with the printername (not including the servername).
2733 ********************************************************************/
2735 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2737 struct spoolss_Notify *data,
2738 print_queue_struct *queue,
2739 struct spoolss_PrinterInfo2 *pinfo2,
2740 TALLOC_CTX *mem_ctx)
2742 /* the notify name should not contain the \\server\ part */
2743 const char *p = strrchr(pinfo2->printername, '\\');
2746 p = pinfo2->printername;
2751 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2754 /*******************************************************************
2755 * fill a notify_info_data with the servicename
2756 ********************************************************************/
2758 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2760 struct spoolss_Notify *data,
2761 print_queue_struct *queue,
2762 struct spoolss_PrinterInfo2 *pinfo2,
2763 TALLOC_CTX *mem_ctx)
2765 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(talloc_tos(), snum));
2768 /*******************************************************************
2769 * fill a notify_info_data with the port name
2770 ********************************************************************/
2772 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2774 struct spoolss_Notify *data,
2775 print_queue_struct *queue,
2776 struct spoolss_PrinterInfo2 *pinfo2,
2777 TALLOC_CTX *mem_ctx)
2779 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2782 /*******************************************************************
2783 * fill a notify_info_data with the printername
2784 * but it doesn't exist, have to see what to do
2785 ********************************************************************/
2787 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2789 struct spoolss_Notify *data,
2790 print_queue_struct *queue,
2791 struct spoolss_PrinterInfo2 *pinfo2,
2792 TALLOC_CTX *mem_ctx)
2794 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2797 /*******************************************************************
2798 * fill a notify_info_data with the comment
2799 ********************************************************************/
2801 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2803 struct spoolss_Notify *data,
2804 print_queue_struct *queue,
2805 struct spoolss_PrinterInfo2 *pinfo2,
2806 TALLOC_CTX *mem_ctx)
2810 if (*pinfo2->comment == '\0') {
2811 p = lp_comment(talloc_tos(), snum);
2813 p = pinfo2->comment;
2816 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2819 /*******************************************************************
2820 * fill a notify_info_data with the comment
2821 * location = "Room 1, floor 2, building 3"
2822 ********************************************************************/
2824 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2826 struct spoolss_Notify *data,
2827 print_queue_struct *queue,
2828 struct spoolss_PrinterInfo2 *pinfo2,
2829 TALLOC_CTX *mem_ctx)
2831 const char *loc = pinfo2->location;
2834 status = printer_list_get_printer(mem_ctx,
2839 if (NT_STATUS_IS_OK(status)) {
2841 loc = pinfo2->location;
2845 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2848 /*******************************************************************
2849 * fill a notify_info_data with the device mode
2850 * jfm:xxxx don't to it for know but that's a real problem !!!
2851 ********************************************************************/
2853 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2855 struct spoolss_Notify *data,
2856 print_queue_struct *queue,
2857 struct spoolss_PrinterInfo2 *pinfo2,
2858 TALLOC_CTX *mem_ctx)
2860 /* for a dummy implementation we have to zero the fields */
2861 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2864 /*******************************************************************
2865 * fill a notify_info_data with the separator file name
2866 ********************************************************************/
2868 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2870 struct spoolss_Notify *data,
2871 print_queue_struct *queue,
2872 struct spoolss_PrinterInfo2 *pinfo2,
2873 TALLOC_CTX *mem_ctx)
2875 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2878 /*******************************************************************
2879 * fill a notify_info_data with the print processor
2880 * jfm:xxxx return always winprint to indicate we don't do anything to it
2881 ********************************************************************/
2883 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2885 struct spoolss_Notify *data,
2886 print_queue_struct *queue,
2887 struct spoolss_PrinterInfo2 *pinfo2,
2888 TALLOC_CTX *mem_ctx)
2890 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2893 /*******************************************************************
2894 * fill a notify_info_data with the print processor options
2895 * jfm:xxxx send an empty string
2896 ********************************************************************/
2898 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2900 struct spoolss_Notify *data,
2901 print_queue_struct *queue,
2902 struct spoolss_PrinterInfo2 *pinfo2,
2903 TALLOC_CTX *mem_ctx)
2905 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2908 /*******************************************************************
2909 * fill a notify_info_data with the data type
2910 * jfm:xxxx always send RAW as data type
2911 ********************************************************************/
2913 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
2915 struct spoolss_Notify *data,
2916 print_queue_struct *queue,
2917 struct spoolss_PrinterInfo2 *pinfo2,
2918 TALLOC_CTX *mem_ctx)
2920 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
2923 /*******************************************************************
2924 * fill a notify_info_data with the security descriptor
2925 * jfm:xxxx send an null pointer to say no security desc
2926 * have to implement security before !
2927 ********************************************************************/
2929 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
2931 struct spoolss_Notify *data,
2932 print_queue_struct *queue,
2933 struct spoolss_PrinterInfo2 *pinfo2,
2934 TALLOC_CTX *mem_ctx)
2936 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
2939 /*******************************************************************
2940 * fill a notify_info_data with the attributes
2941 * jfm:xxxx a samba printer is always shared
2942 ********************************************************************/
2944 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
2946 struct spoolss_Notify *data,
2947 print_queue_struct *queue,
2948 struct spoolss_PrinterInfo2 *pinfo2,
2949 TALLOC_CTX *mem_ctx)
2951 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
2954 /*******************************************************************
2955 * fill a notify_info_data with the priority
2956 ********************************************************************/
2958 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
2960 struct spoolss_Notify *data,
2961 print_queue_struct *queue,
2962 struct spoolss_PrinterInfo2 *pinfo2,
2963 TALLOC_CTX *mem_ctx)
2965 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
2968 /*******************************************************************
2969 * fill a notify_info_data with the default priority
2970 ********************************************************************/
2972 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
2974 struct spoolss_Notify *data,
2975 print_queue_struct *queue,
2976 struct spoolss_PrinterInfo2 *pinfo2,
2977 TALLOC_CTX *mem_ctx)
2979 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
2982 /*******************************************************************
2983 * fill a notify_info_data with the start time
2984 ********************************************************************/
2986 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
2988 struct spoolss_Notify *data,
2989 print_queue_struct *queue,
2990 struct spoolss_PrinterInfo2 *pinfo2,
2991 TALLOC_CTX *mem_ctx)
2993 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
2996 /*******************************************************************
2997 * fill a notify_info_data with the until time
2998 ********************************************************************/
3000 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3002 struct spoolss_Notify *data,
3003 print_queue_struct *queue,
3004 struct spoolss_PrinterInfo2 *pinfo2,
3005 TALLOC_CTX *mem_ctx)
3007 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3010 /*******************************************************************
3011 * fill a notify_info_data with the status
3012 ********************************************************************/
3014 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3016 struct spoolss_Notify *data,
3017 print_queue_struct *queue,
3018 struct spoolss_PrinterInfo2 *pinfo2,
3019 TALLOC_CTX *mem_ctx)
3021 print_status_struct status;
3023 print_queue_length(msg_ctx, snum, &status);
3024 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3027 /*******************************************************************
3028 * fill a notify_info_data with the number of jobs queued
3029 ********************************************************************/
3031 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3033 struct spoolss_Notify *data,
3034 print_queue_struct *queue,
3035 struct spoolss_PrinterInfo2 *pinfo2,
3036 TALLOC_CTX *mem_ctx)
3038 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3039 data, print_queue_length(msg_ctx, snum, NULL));
3042 /*******************************************************************
3043 * fill a notify_info_data with the average ppm
3044 ********************************************************************/
3046 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3048 struct spoolss_Notify *data,
3049 print_queue_struct *queue,
3050 struct spoolss_PrinterInfo2 *pinfo2,
3051 TALLOC_CTX *mem_ctx)
3053 /* always respond 8 pages per minutes */
3054 /* a little hard ! */
3055 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3058 /*******************************************************************
3059 * fill a notify_info_data with username
3060 ********************************************************************/
3062 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3064 struct spoolss_Notify *data,
3065 print_queue_struct *queue,
3066 struct spoolss_PrinterInfo2 *pinfo2,
3067 TALLOC_CTX *mem_ctx)
3069 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3072 /*******************************************************************
3073 * fill a notify_info_data with job status
3074 ********************************************************************/
3076 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3078 struct spoolss_Notify *data,
3079 print_queue_struct *queue,
3080 struct spoolss_PrinterInfo2 *pinfo2,
3081 TALLOC_CTX *mem_ctx)
3083 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3086 /*******************************************************************
3087 * fill a notify_info_data with job name
3088 ********************************************************************/
3090 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3092 struct spoolss_Notify *data,
3093 print_queue_struct *queue,
3094 struct spoolss_PrinterInfo2 *pinfo2,
3095 TALLOC_CTX *mem_ctx)
3097 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3100 /*******************************************************************
3101 * fill a notify_info_data with job status
3102 ********************************************************************/
3104 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3106 struct spoolss_Notify *data,
3107 print_queue_struct *queue,
3108 struct spoolss_PrinterInfo2 *pinfo2,
3109 TALLOC_CTX *mem_ctx)
3112 * Now we're returning job status codes we just return a "" here. JRA.
3117 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3120 switch (queue->status) {
3125 p = ""; /* NT provides the paused string */
3134 #endif /* NO LONGER NEEDED. */
3136 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3139 /*******************************************************************
3140 * fill a notify_info_data with job time
3141 ********************************************************************/
3143 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3145 struct spoolss_Notify *data,
3146 print_queue_struct *queue,
3147 struct spoolss_PrinterInfo2 *pinfo2,
3148 TALLOC_CTX *mem_ctx)
3150 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3153 /*******************************************************************
3154 * fill a notify_info_data with job size
3155 ********************************************************************/
3157 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3159 struct spoolss_Notify *data,
3160 print_queue_struct *queue,
3161 struct spoolss_PrinterInfo2 *pinfo2,
3162 TALLOC_CTX *mem_ctx)
3164 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3167 /*******************************************************************
3168 * fill a notify_info_data with page info
3169 ********************************************************************/
3170 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3172 struct spoolss_Notify *data,
3173 print_queue_struct *queue,
3174 struct spoolss_PrinterInfo2 *pinfo2,
3175 TALLOC_CTX *mem_ctx)
3177 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3180 /*******************************************************************
3181 * fill a notify_info_data with pages printed info.
3182 ********************************************************************/
3183 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3185 struct spoolss_Notify *data,
3186 print_queue_struct *queue,
3187 struct spoolss_PrinterInfo2 *pinfo2,
3188 TALLOC_CTX *mem_ctx)
3190 /* Add code when back-end tracks this */
3191 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3194 /*******************************************************************
3195 Fill a notify_info_data with job position.
3196 ********************************************************************/
3198 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3200 struct spoolss_Notify *data,
3201 print_queue_struct *queue,
3202 struct spoolss_PrinterInfo2 *pinfo2,
3203 TALLOC_CTX *mem_ctx)
3205 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->sysjob);
3208 /*******************************************************************
3209 Fill a notify_info_data with submitted time.
3210 ********************************************************************/
3212 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3214 struct spoolss_Notify *data,
3215 print_queue_struct *queue,
3216 struct spoolss_PrinterInfo2 *pinfo2,
3217 TALLOC_CTX *mem_ctx)
3219 data->data.string.string = NULL;
3220 data->data.string.size = 0;
3222 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3223 &data->data.string.string,
3224 &data->data.string.size);
3228 struct s_notify_info_data_table
3230 enum spoolss_NotifyType type;
3233 enum spoolss_NotifyTable variable_type;
3234 void (*fn) (struct messaging_context *msg_ctx,
3235 int snum, struct spoolss_Notify *data,
3236 print_queue_struct *queue,
3237 struct spoolss_PrinterInfo2 *pinfo2,
3238 TALLOC_CTX *mem_ctx);
3241 /* A table describing the various print notification constants and
3242 whether the notification data is a pointer to a variable sized
3243 buffer, a one value uint32_t or a two value uint32_t. */
3245 static const struct s_notify_info_data_table notify_info_data_table[] =
3247 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3248 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3249 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3250 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3251 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3252 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3253 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3254 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3255 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3256 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3257 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3258 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3259 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3260 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3261 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3262 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3263 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3264 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3265 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3266 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3267 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3268 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3269 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3270 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3271 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3272 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3273 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3274 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3275 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3276 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3277 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3278 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3279 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3280 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3281 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3282 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3283 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3284 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3285 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3286 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3287 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3288 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3289 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3290 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3291 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3292 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3293 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3294 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3295 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3298 /*******************************************************************
3299 Return the variable_type of info_data structure.
3300 ********************************************************************/
3302 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3307 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3308 if ( (notify_info_data_table[i].type == type) &&
3309 (notify_info_data_table[i].field == field) ) {
3310 return notify_info_data_table[i].variable_type;
3314 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3316 return (enum spoolss_NotifyTable) 0;
3319 /****************************************************************************
3320 ****************************************************************************/
3322 static bool search_notify(enum spoolss_NotifyType type,
3328 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3329 if (notify_info_data_table[i].type == type &&
3330 notify_info_data_table[i].field == field &&
3331 notify_info_data_table[i].fn != NULL) {
3340 /****************************************************************************
3341 ****************************************************************************/
3343 static void construct_info_data(struct spoolss_Notify *info_data,
3344 enum spoolss_NotifyType type,
3345 uint16_t field, int id)
3347 info_data->type = type;
3348 info_data->field.field = field;
3349 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3350 info_data->job_id = id;
3353 /*******************************************************************
3355 * fill a notify_info struct with info asked
3357 ********************************************************************/
3359 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3360 struct printer_handle *print_hnd,
3361 struct spoolss_NotifyInfo *info,
3362 struct spoolss_PrinterInfo2 *pinfo2,
3364 const struct spoolss_NotifyOptionType *option_type,
3366 TALLOC_CTX *mem_ctx)
3369 enum spoolss_NotifyType type;
3372 struct spoolss_Notify *current_data;
3374 type = option_type->type;
3376 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3377 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3378 option_type->count, lp_servicename(talloc_tos(), snum)));
3380 for(field_num=0; field_num < option_type->count; field_num++) {
3381 field = option_type->fields[field_num].field;
3383 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3385 if (!search_notify(type, field, &j) )
3388 info->notifies = talloc_realloc(info, info->notifies,
3389 struct spoolss_Notify,
3391 if (info->notifies == NULL) {
3392 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3396 current_data = &info->notifies[info->count];
3398 construct_info_data(current_data, type, field, id);
3400 DEBUG(10, ("construct_notify_printer_info: "
3401 "calling [%s] snum=%d printername=[%s])\n",
3402 notify_info_data_table[j].name, snum,
3403 pinfo2->printername));
3405 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3406 NULL, pinfo2, mem_ctx);
3414 /*******************************************************************
3416 * fill a notify_info struct with info asked
3418 ********************************************************************/
3420 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3421 print_queue_struct *queue,
3422 struct spoolss_NotifyInfo *info,
3423 struct spoolss_PrinterInfo2 *pinfo2,
3425 const struct spoolss_NotifyOptionType *option_type,
3427 TALLOC_CTX *mem_ctx)
3430 enum spoolss_NotifyType type;
3432 struct spoolss_Notify *current_data;
3434 DEBUG(4,("construct_notify_jobs_info\n"));
3436 type = option_type->type;
3438 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3439 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3440 option_type->count));
3442 for(field_num=0; field_num<option_type->count; field_num++) {
3443 field = option_type->fields[field_num].field;
3445 if (!search_notify(type, field, &j) )
3448 info->notifies = talloc_realloc(info, info->notifies,
3449 struct spoolss_Notify,
3451 if (info->notifies == NULL) {
3452 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3456 current_data=&(info->notifies[info->count]);
3458 construct_info_data(current_data, type, field, id);
3459 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3460 queue, pinfo2, mem_ctx);
3468 * JFM: The enumeration is not that simple, it's even non obvious.
3470 * let's take an example: I want to monitor the PRINTER SERVER for
3471 * the printer's name and the number of jobs currently queued.
3472 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3473 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3475 * I have 3 printers on the back of my server.
3477 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3480 * 1 printer 1 name 1
3481 * 2 printer 1 cjob 1
3482 * 3 printer 2 name 2
3483 * 4 printer 2 cjob 2
3484 * 5 printer 3 name 3
3485 * 6 printer 3 name 3
3487 * that's the print server case, the printer case is even worse.
3490 /*******************************************************************
3492 * enumerate all printers on the printserver
3493 * fill a notify_info struct with info asked
3495 ********************************************************************/
3497 static WERROR printserver_notify_info(struct pipes_struct *p,
3498 struct policy_handle *hnd,
3499 struct spoolss_NotifyInfo *info,
3500 TALLOC_CTX *mem_ctx)
3503 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3504 int n_services=lp_numservices();
3506 struct spoolss_NotifyOption *option;
3507 struct spoolss_NotifyOptionType option_type;
3508 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3511 DEBUG(4,("printserver_notify_info\n"));
3516 option = Printer->notify.option;
3519 info->notifies = NULL;
3522 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3523 sending a ffpcn() request first */
3528 for (i=0; i<option->count; i++) {
3529 option_type = option->types[i];
3531 if (option_type.type != PRINTER_NOTIFY_TYPE)
3534 for (snum = 0; snum < n_services; snum++) {
3535 if (!lp_browseable(snum) ||
3536 !lp_snum_ok(snum) ||
3537 !lp_print_ok(snum)) {
3538 continue; /* skip */
3541 /* Maybe we should use the SYSTEM session_info here... */
3542 result = winreg_get_printer_internal(mem_ctx,
3543 get_session_info_system(),
3545 lp_servicename(talloc_tos(), snum),
3547 if (!W_ERROR_IS_OK(result)) {
3548 DEBUG(4, ("printserver_notify_info: "
3549 "Failed to get printer [%s]\n",
3550 lp_servicename(talloc_tos(), snum)));
3555 construct_notify_printer_info(p->msg_ctx,
3561 TALLOC_FREE(pinfo2);
3567 * Debugging information, don't delete.
3570 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3571 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3572 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3574 for (i=0; i<info->count; i++) {
3575 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3576 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3577 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3584 /*******************************************************************
3586 * fill a notify_info struct with info asked
3588 ********************************************************************/
3590 static WERROR printer_notify_info(struct pipes_struct *p,
3591 struct policy_handle *hnd,
3592 struct spoolss_NotifyInfo *info,
3593 TALLOC_CTX *mem_ctx)
3596 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3599 struct spoolss_NotifyOption *option;
3600 struct spoolss_NotifyOptionType option_type;
3602 print_queue_struct *queue=NULL;
3603 print_status_struct status;
3604 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3607 DEBUG(4,("printer_notify_info\n"));
3612 option = Printer->notify.option;
3616 info->notifies = NULL;
3619 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3620 sending a ffpcn() request first */
3625 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3629 /* Maybe we should use the SYSTEM session_info here... */
3630 result = winreg_get_printer_internal(mem_ctx,
3631 get_session_info_system(),
3633 lp_servicename(talloc_tos(), snum), &pinfo2);
3634 if (!W_ERROR_IS_OK(result)) {
3639 * When sending a PRINTER_NOTIFY_FIELD_SERVER_NAME we should send the
3640 * correct servername.
3642 pinfo2->servername = talloc_strdup(pinfo2, Printer->servername);
3643 if (pinfo2->servername == NULL) {
3647 for (i=0; i<option->count; i++) {
3648 option_type = option->types[i];
3650 switch (option_type.type) {
3651 case PRINTER_NOTIFY_TYPE:
3652 if (construct_notify_printer_info(p->msg_ctx,
3661 case JOB_NOTIFY_TYPE:
3663 count = print_queue_status(p->msg_ctx, snum, &queue,
3666 for (j=0; j<count; j++) {
3667 construct_notify_jobs_info(p->msg_ctx,
3681 * Debugging information, don't delete.
3684 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3685 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3686 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3688 for (i=0; i<info->count; i++) {
3689 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3690 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3691 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3695 talloc_free(pinfo2);
3699 /****************************************************************
3700 _spoolss_RouterRefreshPrinterChangeNotify
3701 ****************************************************************/
3703 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3704 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3706 struct spoolss_NotifyInfo *info;
3708 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3709 WERROR result = WERR_BADFID;
3711 /* we always have a spoolss_NotifyInfo struct */
3712 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3714 result = WERR_NOMEM;
3718 *r->out.info = info;
3721 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3722 "Invalid handle (%s:%u:%u).\n",
3723 OUR_HANDLE(r->in.handle)));
3727 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3730 * We are now using the change value, and
3731 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3732 * I don't have a global notification system, I'm sending back all the
3733 * information even when _NOTHING_ has changed.
3736 /* We need to keep track of the change value to send back in
3737 RRPCN replies otherwise our updates are ignored. */
3739 Printer->notify.fnpcn = true;
3741 if (Printer->notify.cli_chan != NULL &&
3742 Printer->notify.cli_chan->active_connections > 0) {
3743 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3744 "Saving change value in request [%x]\n",
3746 Printer->notify.change = r->in.change_low;
3749 /* just ignore the spoolss_NotifyOption */
3751 switch (Printer->printer_type) {
3753 result = printserver_notify_info(p, r->in.handle,
3757 case SPLHND_PRINTER:
3758 result = printer_notify_info(p, r->in.handle,
3763 Printer->notify.fnpcn = false;
3769 /********************************************************************
3770 ********************************************************************/
3772 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3773 const char *servername,
3774 const char *printername,
3775 const char **printername_p)
3777 /* FIXME: add lp_force_printername() */
3779 if (servername == NULL) {
3780 *printername_p = talloc_strdup(mem_ctx, printername);
3781 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3785 if (servername[0] == '\\' && servername[1] == '\\') {
3789 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3790 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3795 /********************************************************************
3796 ********************************************************************/
3798 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3799 const char *printername)
3805 dm->devicename = talloc_strndup(dm, printername,
3806 MIN(strlen(printername), 31));
3809 /********************************************************************
3810 * construct_printer_info_0
3811 * fill a printer_info_0 struct
3812 ********************************************************************/
3814 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3815 const struct auth_session_info *session_info,
3816 struct messaging_context *msg_ctx,
3817 struct spoolss_PrinterInfo2 *info2,
3818 const char *servername,
3819 struct spoolss_PrinterInfo0 *r,
3823 struct printer_session_counter *session_counter;
3824 struct timeval setuptime;
3825 print_status_struct status;
3828 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3829 if (!W_ERROR_IS_OK(result)) {
3834 r->servername = talloc_strdup(mem_ctx, servername);
3835 W_ERROR_HAVE_NO_MEMORY(r->servername);
3837 r->servername = NULL;
3840 count = print_queue_length(msg_ctx, snum, &status);
3842 /* check if we already have a counter for this printer */
3843 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3844 if (session_counter->snum == snum)
3848 /* it's the first time, add it to the list */
3849 if (session_counter == NULL) {
3850 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3851 W_ERROR_HAVE_NO_MEMORY(session_counter);
3852 session_counter->snum = snum;
3853 session_counter->counter = 0;
3854 DLIST_ADD(counter_list, session_counter);
3858 session_counter->counter++;
3864 get_startup_time(&setuptime);
3865 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3868 * the global_counter should be stored in a TDB as it's common to all the clients
3869 * and should be zeroed on samba startup
3871 r->global_counter = session_counter->counter;
3873 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3874 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3875 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3876 r->free_build = SPOOLSS_RELEASE_BUILD;
3878 r->max_spooling = 0;
3879 r->session_counter = session_counter->counter;
3880 r->num_error_out_of_paper = 0x0;
3881 r->num_error_not_ready = 0x0; /* number of print failure */
3883 r->number_of_processors = 0x1;
3884 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3885 r->high_part_total_bytes = 0x0;
3887 /* ChangeID in milliseconds*/
3888 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3889 info2->sharename, &r->change_id);
3891 r->last_error = WERR_OK;
3892 r->status = nt_printq_status(status.status);
3893 r->enumerate_network_printers = 0x0;
3894 r->c_setprinter = 0x0;
3895 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3896 r->processor_level = 0x6; /* 6 ???*/
3905 /********************************************************************
3906 * construct_printer_info1
3907 * fill a spoolss_PrinterInfo1 struct
3908 ********************************************************************/
3910 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3911 const struct spoolss_PrinterInfo2 *info2,
3913 const char *servername,
3914 struct spoolss_PrinterInfo1 *r,
3921 if (info2->comment == NULL || info2->comment[0] == '\0') {
3922 r->comment = lp_comment(mem_ctx, snum);
3924 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
3926 W_ERROR_HAVE_NO_MEMORY(r->comment);
3928 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
3929 if (!W_ERROR_IS_OK(result)) {
3933 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
3937 W_ERROR_HAVE_NO_MEMORY(r->description);
3942 /********************************************************************
3943 * construct_printer_info2
3944 * fill a spoolss_PrinterInfo2 struct
3945 ********************************************************************/
3947 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
3948 struct messaging_context *msg_ctx,
3949 const struct spoolss_PrinterInfo2 *info2,
3950 const char *servername,
3951 struct spoolss_PrinterInfo2 *r,
3955 print_status_struct status;
3958 count = print_queue_length(msg_ctx, snum, &status);
3961 r->servername = talloc_strdup(mem_ctx, servername);
3962 W_ERROR_HAVE_NO_MEMORY(r->servername);
3964 r->servername = NULL;
3967 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3968 if (!W_ERROR_IS_OK(result)) {
3972 r->sharename = lp_servicename(mem_ctx, snum);
3973 W_ERROR_HAVE_NO_MEMORY(r->sharename);
3974 r->portname = talloc_strdup(mem_ctx, info2->portname);
3975 W_ERROR_HAVE_NO_MEMORY(r->portname);
3976 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
3977 W_ERROR_HAVE_NO_MEMORY(r->drivername);
3979 if (info2->comment[0] == '\0') {
3980 r->comment = lp_comment(mem_ctx, snum);
3982 r->comment = talloc_strdup(mem_ctx, info2->comment);
3984 W_ERROR_HAVE_NO_MEMORY(r->comment);
3986 r->location = talloc_strdup(mem_ctx, info2->location);
3987 if (info2->location[0] == '\0') {
3988 const char *loc = NULL;
3991 nt_status = printer_list_get_printer(mem_ctx,
3996 if (NT_STATUS_IS_OK(nt_status)) {
3998 r->location = talloc_strdup(mem_ctx, loc);
4002 W_ERROR_HAVE_NO_MEMORY(r->location);
4004 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4005 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4006 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4007 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4008 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4009 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4010 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4011 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4013 r->attributes = info2->attributes;
4015 r->priority = info2->priority;
4016 r->defaultpriority = info2->defaultpriority;
4017 r->starttime = info2->starttime;
4018 r->untiltime = info2->untiltime;
4019 r->status = nt_printq_status(status.status);
4021 r->averageppm = info2->averageppm;
4023 if (info2->devmode != NULL) {
4024 result = copy_devicemode(mem_ctx,
4027 if (!W_ERROR_IS_OK(result)) {
4030 } else if (lp_default_devmode(snum)) {
4031 result = spoolss_create_default_devmode(mem_ctx,
4034 if (!W_ERROR_IS_OK(result)) {
4039 DEBUG(8,("Returning NULL Devicemode!\n"));
4042 compose_devicemode_devicename(r->devmode, r->printername);
4046 if (info2->secdesc != NULL) {
4047 /* don't use talloc_steal() here unless you do a deep steal of all
4048 the SEC_DESC members */
4050 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4056 /********************************************************************
4057 * construct_printer_info3
4058 * fill a spoolss_PrinterInfo3 struct
4059 ********************************************************************/
4061 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4062 const struct spoolss_PrinterInfo2 *info2,
4063 const char *servername,
4064 struct spoolss_PrinterInfo3 *r,
4067 /* These are the components of the SD we are returning. */
4069 if (info2->secdesc != NULL) {
4070 /* don't use talloc_steal() here unless you do a deep steal of all
4071 the SEC_DESC members */
4073 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4074 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4080 /********************************************************************
4081 * construct_printer_info4
4082 * fill a spoolss_PrinterInfo4 struct
4083 ********************************************************************/
4085 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4086 const struct spoolss_PrinterInfo2 *info2,
4087 const char *servername,
4088 struct spoolss_PrinterInfo4 *r,
4093 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4094 if (!W_ERROR_IS_OK(result)) {
4099 r->servername = talloc_strdup(mem_ctx, servername);
4100 W_ERROR_HAVE_NO_MEMORY(r->servername);
4102 r->servername = NULL;
4105 r->attributes = info2->attributes;
4110 /********************************************************************
4111 * construct_printer_info5
4112 * fill a spoolss_PrinterInfo5 struct
4113 ********************************************************************/
4115 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4116 const struct spoolss_PrinterInfo2 *info2,
4117 const char *servername,
4118 struct spoolss_PrinterInfo5 *r,
4123 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4124 if (!W_ERROR_IS_OK(result)) {
4128 r->portname = talloc_strdup(mem_ctx, info2->portname);
4129 W_ERROR_HAVE_NO_MEMORY(r->portname);
4131 r->attributes = info2->attributes;
4133 /* these two are not used by NT+ according to MSDN */
4134 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4135 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4140 /********************************************************************
4141 * construct_printer_info_6
4142 * fill a spoolss_PrinterInfo6 struct
4143 ********************************************************************/
4145 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4146 struct messaging_context *msg_ctx,
4147 const struct spoolss_PrinterInfo2 *info2,
4148 const char *servername,
4149 struct spoolss_PrinterInfo6 *r,
4152 print_status_struct status;
4154 print_queue_length(msg_ctx, snum, &status);
4156 r->status = nt_printq_status(status.status);
4161 /********************************************************************
4162 * construct_printer_info7
4163 * fill a spoolss_PrinterInfo7 struct
4164 ********************************************************************/
4166 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4167 struct messaging_context *msg_ctx,
4168 const char *servername,
4169 struct spoolss_PrinterInfo7 *r,
4172 const struct auth_session_info *session_info = get_session_info_system();
4175 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4177 lp_servicename(talloc_tos(), snum), &guid, NULL)) {
4178 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4179 r->action = DSPRINT_PUBLISH;
4181 r->guid = talloc_strdup(mem_ctx, "");
4182 r->action = DSPRINT_UNPUBLISH;
4184 W_ERROR_HAVE_NO_MEMORY(r->guid);
4189 /********************************************************************
4190 * construct_printer_info8
4191 * fill a spoolss_PrinterInfo8 struct
4192 ********************************************************************/
4194 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4195 const struct spoolss_PrinterInfo2 *info2,
4196 const char *servername,
4197 struct spoolss_DeviceModeInfo *r,
4201 const char *printername;
4203 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4204 if (!W_ERROR_IS_OK(result)) {
4208 if (info2->devmode != NULL) {
4209 result = copy_devicemode(mem_ctx,
4212 if (!W_ERROR_IS_OK(result)) {
4215 } else if (lp_default_devmode(snum)) {
4216 result = spoolss_create_default_devmode(mem_ctx,
4219 if (!W_ERROR_IS_OK(result)) {
4224 DEBUG(8,("Returning NULL Devicemode!\n"));
4227 compose_devicemode_devicename(r->devmode, printername);
4233 /********************************************************************
4234 ********************************************************************/
4236 static bool snum_is_shared_printer(int snum)
4238 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4241 /********************************************************************
4242 Spoolss_enumprinters.
4243 ********************************************************************/
4245 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4246 const struct auth_session_info *session_info,
4247 struct messaging_context *msg_ctx,
4248 const char *servername,
4251 union spoolss_PrinterInfo **info_p,
4255 int n_services = lp_numservices();
4256 union spoolss_PrinterInfo *info = NULL;
4258 WERROR result = WERR_OK;
4259 struct dcerpc_binding_handle *b = NULL;
4260 TALLOC_CTX *tmp_ctx = NULL;
4262 tmp_ctx = talloc_new(mem_ctx);
4270 for (snum = 0; snum < n_services; snum++) {
4272 const char *printer;
4273 struct spoolss_PrinterInfo2 *info2;
4275 if (!snum_is_shared_printer(snum)) {
4279 printer = lp_const_servicename(snum);
4281 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4285 result = winreg_printer_binding_handle(tmp_ctx,
4289 if (!W_ERROR_IS_OK(result)) {
4294 result = winreg_create_printer(tmp_ctx, b,
4296 if (!W_ERROR_IS_OK(result)) {
4300 info = talloc_realloc(tmp_ctx, info,
4301 union spoolss_PrinterInfo,
4304 result = WERR_NOMEM;
4308 result = winreg_get_printer(tmp_ctx, b,
4310 if (!W_ERROR_IS_OK(result)) {
4316 result = construct_printer_info0(info, session_info,
4319 &info[count].info0, snum);
4322 result = construct_printer_info1(info, info2, flags,
4324 &info[count].info1, snum);
4327 result = construct_printer_info2(info, msg_ctx, info2,
4329 &info[count].info2, snum);
4332 result = construct_printer_info4(info, info2,
4334 &info[count].info4, snum);
4337 result = construct_printer_info5(info, info2,
4339 &info[count].info5, snum);
4343 result = WERR_UNKNOWN_LEVEL;
4347 if (!W_ERROR_IS_OK(result)) {
4355 if (W_ERROR_IS_OK(result)) {
4356 *info_p = talloc_move(mem_ctx, &info);
4360 talloc_free(tmp_ctx);
4365 /********************************************************************
4366 * handle enumeration of printers at level 0
4367 ********************************************************************/
4369 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4370 const struct auth_session_info *session_info,
4371 struct messaging_context *msg_ctx,
4373 const char *servername,
4374 union spoolss_PrinterInfo **info,
4377 DEBUG(4,("enum_all_printers_info_0\n"));
4379 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4380 servername, 0, flags, info, count);
4384 /********************************************************************
4385 ********************************************************************/
4387 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4388 const struct auth_session_info *session_info,
4389 struct messaging_context *msg_ctx,
4390 const char *servername,
4392 union spoolss_PrinterInfo **info,
4395 DEBUG(4,("enum_all_printers_info_1\n"));
4397 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4398 servername, 1, flags, info, count);
4401 /********************************************************************
4402 enum_all_printers_info_1_local.
4403 *********************************************************************/
4405 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4406 const struct auth_session_info *session_info,
4407 struct messaging_context *msg_ctx,
4408 const char *servername,
4409 union spoolss_PrinterInfo **info,
4412 DEBUG(4,("enum_all_printers_info_1_local\n"));
4414 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4415 servername, PRINTER_ENUM_ICON8, info, count);
4418 /********************************************************************
4419 enum_all_printers_info_1_name.
4420 *********************************************************************/
4422 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4423 const struct auth_session_info *session_info,
4424 struct messaging_context *msg_ctx,
4425 const char *servername,
4426 union spoolss_PrinterInfo **info,
4429 const char *s = servername;
4431 DEBUG(4,("enum_all_printers_info_1_name\n"));
4433 if (servername != NULL &&
4434 (servername[0] == '\\') && (servername[1] == '\\')) {
4438 if (!is_myname_or_ipaddr(s)) {
4439 return WERR_INVALID_NAME;
4442 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4443 servername, PRINTER_ENUM_ICON8, info, count);
4446 /********************************************************************
4447 enum_all_printers_info_1_network.
4448 *********************************************************************/
4450 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4451 const struct auth_session_info *session_info,
4452 struct messaging_context *msg_ctx,
4453 const char *servername,
4454 union spoolss_PrinterInfo **info,
4457 const char *s = servername;
4459 DEBUG(4,("enum_all_printers_info_1_network\n"));
4461 /* If we respond to a enum_printers level 1 on our name with flags
4462 set to PRINTER_ENUM_REMOTE with a list of printers then these
4463 printers incorrectly appear in the APW browse list.
4464 Specifically the printers for the server appear at the workgroup
4465 level where all the other servers in the domain are
4466 listed. Windows responds to this call with a
4467 WERR_CAN_NOT_COMPLETE so we should do the same. */
4469 if (servername[0] == '\\' && servername[1] == '\\') {
4473 if (is_myname_or_ipaddr(s)) {
4474 return WERR_CAN_NOT_COMPLETE;
4477 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4478 servername, PRINTER_ENUM_NAME, info, count);
4481 /********************************************************************
4482 * api_spoolss_enumprinters
4484 * called from api_spoolss_enumprinters (see this to understand)
4485 ********************************************************************/
4487 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4488 const struct auth_session_info *session_info,
4489 struct messaging_context *msg_ctx,
4490 const char *servername,
4491 union spoolss_PrinterInfo **info,
4494 DEBUG(4,("enum_all_printers_info_2\n"));
4496 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4497 servername, 2, 0, info, count);
4500 /********************************************************************
4501 * handle enumeration of printers at level 1
4502 ********************************************************************/
4504 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4505 const struct auth_session_info *session_info,
4506 struct messaging_context *msg_ctx,
4508 const char *servername,
4509 union spoolss_PrinterInfo **info,
4512 /* Not all the flags are equals */
4514 if (flags & PRINTER_ENUM_LOCAL) {
4515 return enum_all_printers_info_1_local(mem_ctx, session_info,
4516 msg_ctx, servername, info, count);
4519 if (flags & PRINTER_ENUM_NAME) {
4520 return enum_all_printers_info_1_name(mem_ctx, session_info,
4521 msg_ctx, servername, info,
4525 if (flags & PRINTER_ENUM_NETWORK) {
4526 return enum_all_printers_info_1_network(mem_ctx, session_info,
4527 msg_ctx, servername, info,
4531 return WERR_OK; /* NT4sp5 does that */
4534 /********************************************************************
4535 * handle enumeration of printers at level 2
4536 ********************************************************************/
4538 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4539 const struct auth_session_info *session_info,
4540 struct messaging_context *msg_ctx,
4542 const char *servername,
4543 union spoolss_PrinterInfo **info,
4546 if (flags & PRINTER_ENUM_LOCAL) {
4548 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4553 if (flags & PRINTER_ENUM_NAME) {
4554 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4555 return WERR_INVALID_NAME;
4558 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4563 if (flags & PRINTER_ENUM_REMOTE) {
4564 return WERR_UNKNOWN_LEVEL;
4570 /********************************************************************
4571 * handle enumeration of printers at level 4
4572 ********************************************************************/
4574 static WERROR enumprinters_level4(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_4\n"));
4584 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4585 servername, 4, flags, info, count);
4589 /********************************************************************
4590 * handle enumeration of printers at level 5
4591 ********************************************************************/
4593 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4594 const struct auth_session_info *session_info,
4595 struct messaging_context *msg_ctx,
4597 const char *servername,
4598 union spoolss_PrinterInfo **info,
4601 DEBUG(4,("enum_all_printers_info_5\n"));
4603 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4604 servername, 5, flags, info, count);
4607 /****************************************************************
4608 _spoolss_EnumPrinters
4609 ****************************************************************/
4611 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4612 struct spoolss_EnumPrinters *r)
4614 const struct auth_session_info *session_info = get_session_info_system();
4617 /* that's an [in out] buffer */
4619 if (!r->in.buffer && (r->in.offered != 0)) {
4620 return WERR_INVALID_PARAM;
4623 DEBUG(4,("_spoolss_EnumPrinters\n"));
4627 *r->out.info = NULL;
4631 * flags==PRINTER_ENUM_NAME
4632 * if name=="" then enumerates all printers
4633 * if name!="" then enumerate the printer
4634 * flags==PRINTER_ENUM_REMOTE
4635 * name is NULL, enumerate printers
4636 * Level 2: name!="" enumerates printers, name can't be NULL
4637 * Level 3: doesn't exist
4638 * Level 4: does a local registry lookup
4639 * Level 5: same as Level 2
4642 if (r->in.server && r->in.server[0] == '\0') {
4643 r->in.server = NULL;
4646 switch (r->in.level) {
4648 result = enumprinters_level0(p->mem_ctx, session_info,
4649 p->msg_ctx, r->in.flags,
4651 r->out.info, r->out.count);
4654 result = enumprinters_level1(p->mem_ctx, session_info,
4655 p->msg_ctx, r->in.flags,
4657 r->out.info, r->out.count);
4660 result = enumprinters_level2(p->mem_ctx, session_info,
4661 p->msg_ctx, r->in.flags,
4663 r->out.info, r->out.count);
4666 result = enumprinters_level4(p->mem_ctx, session_info,
4667 p->msg_ctx, r->in.flags,
4669 r->out.info, r->out.count);
4672 result = enumprinters_level5(p->mem_ctx, session_info,
4673 p->msg_ctx, r->in.flags,
4675 r->out.info, r->out.count);
4678 return WERR_UNKNOWN_LEVEL;
4681 if (!W_ERROR_IS_OK(result)) {
4685 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4686 spoolss_EnumPrinters,
4687 *r->out.info, r->in.level,
4689 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4690 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4692 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4695 /****************************************************************
4697 ****************************************************************/
4699 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4700 struct spoolss_GetPrinter *r)
4702 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4703 struct spoolss_PrinterInfo2 *info2 = NULL;
4704 WERROR result = WERR_OK;
4707 /* that's an [in out] buffer */
4709 if (!r->in.buffer && (r->in.offered != 0)) {
4710 return WERR_INVALID_PARAM;
4715 if (Printer == NULL) {
4719 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4723 result = winreg_get_printer_internal(p->mem_ctx,
4724 get_session_info_system(),
4726 lp_const_servicename(snum),
4728 if (!W_ERROR_IS_OK(result)) {
4732 switch (r->in.level) {
4734 result = construct_printer_info0(p->mem_ctx,
4735 get_session_info_system(),
4738 Printer->servername,
4739 &r->out.info->info0,
4743 result = construct_printer_info1(p->mem_ctx, info2,
4745 Printer->servername,
4746 &r->out.info->info1, snum);
4749 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4750 Printer->servername,
4751 &r->out.info->info2, snum);
4754 result = construct_printer_info3(p->mem_ctx, info2,
4755 Printer->servername,
4756 &r->out.info->info3, snum);
4759 result = construct_printer_info4(p->mem_ctx, info2,
4760 Printer->servername,
4761 &r->out.info->info4, snum);
4764 result = construct_printer_info5(p->mem_ctx, info2,
4765 Printer->servername,
4766 &r->out.info->info5, snum);
4769 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4770 Printer->servername,
4771 &r->out.info->info6, snum);
4774 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4775 Printer->servername,
4776 &r->out.info->info7, snum);
4779 result = construct_printer_info8(p->mem_ctx, info2,
4780 Printer->servername,
4781 &r->out.info->info8, snum);
4784 result = WERR_UNKNOWN_LEVEL;
4790 if (!W_ERROR_IS_OK(result)) {
4791 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4792 r->in.level, win_errstr(result)));
4793 TALLOC_FREE(r->out.info);
4797 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4798 r->out.info, r->in.level);
4799 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4801 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4804 /********************************************************************
4805 ********************************************************************/
4807 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4809 if (in && strlen(in)) { \
4810 out = talloc_strdup(mem_ctx, in); \
4812 out = talloc_strdup(mem_ctx, ""); \
4814 W_ERROR_HAVE_NO_MEMORY(out); \
4817 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4819 if (in && strlen(in)) { \
4820 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4822 out = talloc_strdup(mem_ctx, ""); \
4824 W_ERROR_HAVE_NO_MEMORY(out); \
4827 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4828 const char **string_array,
4829 const char ***presult,
4830 const char *cservername,
4834 int i, num_strings = 0;
4835 const char **array = NULL;
4837 if (string_array == NULL) {
4838 return WERR_INVALID_PARAMETER;
4841 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4842 const char *str = NULL;
4844 if (cservername == NULL || arch == NULL) {
4845 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4847 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4850 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4857 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4858 &array, &num_strings);
4868 /********************************************************************
4869 * fill a spoolss_DriverInfo1 struct
4870 ********************************************************************/
4872 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4873 struct spoolss_DriverInfo1 *r,
4874 const struct spoolss_DriverInfo8 *driver,
4875 const char *servername)
4877 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4878 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4883 /********************************************************************
4884 * fill a spoolss_DriverInfo2 struct
4885 ********************************************************************/
4887 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4888 struct spoolss_DriverInfo2 *r,
4889 const struct spoolss_DriverInfo8 *driver,
4890 const char *servername)
4893 const char *cservername = canon_servername(servername);
4895 r->version = driver->version;
4897 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4898 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4899 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4900 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4902 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4903 driver->architecture,
4905 driver->driver_path,
4908 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4909 driver->architecture,
4914 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4915 driver->architecture,
4917 driver->config_file,
4923 /********************************************************************
4924 * fill a spoolss_DriverInfo3 struct
4925 ********************************************************************/
4927 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4928 struct spoolss_DriverInfo3 *r,
4929 const struct spoolss_DriverInfo8 *driver,
4930 const char *servername)
4932 const char *cservername = canon_servername(servername);
4934 r->version = driver->version;
4936 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4937 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4938 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4939 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4941 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4942 driver->architecture,
4944 driver->driver_path,
4947 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4948 driver->architecture,
4953 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4954 driver->architecture,
4956 driver->config_file,
4959 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4960 driver->architecture,
4965 FILL_DRIVER_STRING(mem_ctx,
4966 driver->monitor_name,
4969 FILL_DRIVER_STRING(mem_ctx,
4970 driver->default_datatype,
4971 r->default_datatype);
4973 return string_array_from_driver_info(mem_ctx,
4974 driver->dependent_files,
4975 &r->dependent_files,
4977 driver->architecture,
4981 /********************************************************************
4982 * fill a spoolss_DriverInfo4 struct
4983 ********************************************************************/
4985 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
4986 struct spoolss_DriverInfo4 *r,
4987 const struct spoolss_DriverInfo8 *driver,
4988 const char *servername)
4990 const char *cservername = canon_servername(servername);
4993 r->version = driver->version;
4995 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4996 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4997 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4998 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5000 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5001 driver->architecture,
5003 driver->driver_path,
5006 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5007 driver->architecture,
5012 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5013 driver->architecture,
5015 driver->config_file,
5018 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5019 driver->architecture,
5024 result = string_array_from_driver_info(mem_ctx,
5025 driver->dependent_files,
5026 &r->dependent_files,
5028 driver->architecture,
5030 if (!W_ERROR_IS_OK(result)) {
5034 FILL_DRIVER_STRING(mem_ctx,
5035 driver->monitor_name,
5038 FILL_DRIVER_STRING(mem_ctx,
5039 driver->default_datatype,
5040 r->default_datatype);
5043 result = string_array_from_driver_info(mem_ctx,
5044 driver->previous_names,
5051 /********************************************************************
5052 * fill a spoolss_DriverInfo5 struct
5053 ********************************************************************/
5055 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5056 struct spoolss_DriverInfo5 *r,
5057 const struct spoolss_DriverInfo8 *driver,
5058 const char *servername)
5060 const char *cservername = canon_servername(servername);
5062 r->version = driver->version;
5064 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5065 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5066 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5067 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5069 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5070 driver->architecture,
5072 driver->driver_path,
5075 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5076 driver->architecture,
5081 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5082 driver->architecture,
5084 driver->config_file,
5087 r->driver_attributes = 0;
5088 r->config_version = 0;
5089 r->driver_version = 0;
5093 /********************************************************************
5094 * fill a spoolss_DriverInfo6 struct
5095 ********************************************************************/
5097 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5098 struct spoolss_DriverInfo6 *r,
5099 const struct spoolss_DriverInfo8 *driver,
5100 const char *servername)
5102 const char *cservername = canon_servername(servername);
5105 r->version = driver->version;
5107 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5108 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5109 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5110 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5112 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5113 driver->architecture,
5115 driver->driver_path,
5118 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5119 driver->architecture,
5124 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5125 driver->architecture,
5127 driver->config_file,
5130 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5131 driver->architecture,
5136 FILL_DRIVER_STRING(mem_ctx,
5137 driver->monitor_name,
5140 FILL_DRIVER_STRING(mem_ctx,
5141 driver->default_datatype,
5142 r->default_datatype);
5144 result = string_array_from_driver_info(mem_ctx,
5145 driver->dependent_files,
5146 &r->dependent_files,
5148 driver->architecture,
5150 if (!W_ERROR_IS_OK(result)) {
5154 result = string_array_from_driver_info(mem_ctx,
5155 driver->previous_names,
5158 if (!W_ERROR_IS_OK(result)) {
5162 r->driver_date = driver->driver_date;
5163 r->driver_version = driver->driver_version;
5165 FILL_DRIVER_STRING(mem_ctx,
5166 driver->manufacturer_name,
5167 r->manufacturer_name);
5168 FILL_DRIVER_STRING(mem_ctx,
5169 driver->manufacturer_url,
5170 r->manufacturer_url);
5171 FILL_DRIVER_STRING(mem_ctx,
5172 driver->hardware_id,
5174 FILL_DRIVER_STRING(mem_ctx,
5181 /********************************************************************
5182 * fill a spoolss_DriverInfo8 struct
5183 ********************************************************************/
5185 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5186 struct spoolss_DriverInfo8 *r,
5187 const struct spoolss_DriverInfo8 *driver,
5188 const char *servername)
5190 const char *cservername = canon_servername(servername);
5193 r->version = driver->version;
5195 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5196 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5197 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5198 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5200 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5201 driver->architecture,
5203 driver->driver_path,
5206 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5207 driver->architecture,
5212 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5213 driver->architecture,
5215 driver->config_file,
5218 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5219 driver->architecture,
5224 FILL_DRIVER_STRING(mem_ctx,
5225 driver->monitor_name,
5228 FILL_DRIVER_STRING(mem_ctx,
5229 driver->default_datatype,
5230 r->default_datatype);
5232 result = string_array_from_driver_info(mem_ctx,
5233 driver->dependent_files,
5234 &r->dependent_files,
5236 driver->architecture,
5238 if (!W_ERROR_IS_OK(result)) {
5242 result = string_array_from_driver_info(mem_ctx,
5243 driver->previous_names,
5246 if (!W_ERROR_IS_OK(result)) {
5250 r->driver_date = driver->driver_date;
5251 r->driver_version = driver->driver_version;
5253 FILL_DRIVER_STRING(mem_ctx,
5254 driver->manufacturer_name,
5255 r->manufacturer_name);
5256 FILL_DRIVER_STRING(mem_ctx,
5257 driver->manufacturer_url,
5258 r->manufacturer_url);
5259 FILL_DRIVER_STRING(mem_ctx,
5260 driver->hardware_id,
5262 FILL_DRIVER_STRING(mem_ctx,
5266 FILL_DRIVER_STRING(mem_ctx,
5267 driver->print_processor,
5268 r->print_processor);
5269 FILL_DRIVER_STRING(mem_ctx,
5270 driver->vendor_setup,
5273 result = string_array_from_driver_info(mem_ctx,
5274 driver->color_profiles,
5277 if (!W_ERROR_IS_OK(result)) {
5281 FILL_DRIVER_STRING(mem_ctx,
5285 r->printer_driver_attributes = driver->printer_driver_attributes;
5287 result = string_array_from_driver_info(mem_ctx,
5288 driver->core_driver_dependencies,
5289 &r->core_driver_dependencies,
5291 if (!W_ERROR_IS_OK(result)) {
5295 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5296 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5301 #if 0 /* disabled until marshalling issues are resolved - gd */
5302 /********************************************************************
5303 ********************************************************************/
5305 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5306 struct spoolss_DriverFileInfo *r,
5307 const char *cservername,
5308 const char *file_name,
5309 enum spoolss_DriverFileType file_type,
5310 uint32_t file_version)
5312 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5313 cservername, file_name);
5314 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5315 r->file_type = file_type;
5316 r->file_version = file_version;
5321 /********************************************************************
5322 ********************************************************************/
5324 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5325 const struct spoolss_DriverInfo8 *driver,
5326 const char *cservername,
5327 struct spoolss_DriverFileInfo **info_p,
5330 struct spoolss_DriverFileInfo *info = NULL;
5338 if (strlen(driver->driver_path)) {
5339 info = talloc_realloc(mem_ctx, info,
5340 struct spoolss_DriverFileInfo,
5342 W_ERROR_HAVE_NO_MEMORY(info);
5343 result = fill_spoolss_DriverFileInfo(info,
5346 driver->driver_path,
5347 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5349 W_ERROR_NOT_OK_RETURN(result);
5353 if (strlen(driver->config_file)) {
5354 info = talloc_realloc(mem_ctx, info,
5355 struct spoolss_DriverFileInfo,
5357 W_ERROR_HAVE_NO_MEMORY(info);
5358 result = fill_spoolss_DriverFileInfo(info,
5361 driver->config_file,
5362 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5364 W_ERROR_NOT_OK_RETURN(result);
5368 if (strlen(driver->data_file)) {
5369 info = talloc_realloc(mem_ctx, info,
5370 struct spoolss_DriverFileInfo,
5372 W_ERROR_HAVE_NO_MEMORY(info);
5373 result = fill_spoolss_DriverFileInfo(info,
5377 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5379 W_ERROR_NOT_OK_RETURN(result);
5383 if (strlen(driver->help_file)) {
5384 info = talloc_realloc(mem_ctx, info,
5385 struct spoolss_DriverFileInfo,
5387 W_ERROR_HAVE_NO_MEMORY(info);
5388 result = fill_spoolss_DriverFileInfo(info,
5392 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5394 W_ERROR_NOT_OK_RETURN(result);
5398 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5399 info = talloc_realloc(mem_ctx, info,
5400 struct spoolss_DriverFileInfo,
5402 W_ERROR_HAVE_NO_MEMORY(info);
5403 result = fill_spoolss_DriverFileInfo(info,
5406 driver->dependent_files[i],
5407 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5409 W_ERROR_NOT_OK_RETURN(result);
5419 /********************************************************************
5420 * fill a spoolss_DriverInfo101 struct
5421 ********************************************************************/
5423 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5424 struct spoolss_DriverInfo101 *r,
5425 const struct spoolss_DriverInfo8 *driver,
5426 const char *servername)
5428 const char *cservername = canon_servername(servername);
5431 r->version = driver->version;
5433 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5434 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5435 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5436 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5438 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5442 if (!W_ERROR_IS_OK(result)) {
5446 FILL_DRIVER_STRING(mem_ctx,
5447 driver->monitor_name,
5450 FILL_DRIVER_STRING(mem_ctx,
5451 driver->default_datatype,
5452 r->default_datatype);
5454 result = string_array_from_driver_info(mem_ctx,
5455 driver->previous_names,
5458 if (!W_ERROR_IS_OK(result)) {
5462 r->driver_date = driver->driver_date;
5463 r->driver_version = driver->driver_version;
5465 FILL_DRIVER_STRING(mem_ctx,
5466 driver->manufacturer_name,
5467 r->manufacturer_name);
5468 FILL_DRIVER_STRING(mem_ctx,
5469 driver->manufacturer_url,
5470 r->manufacturer_url);
5471 FILL_DRIVER_STRING(mem_ctx,
5472 driver->hardware_id,
5474 FILL_DRIVER_STRING(mem_ctx,
5481 /********************************************************************
5482 ********************************************************************/
5484 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5485 const struct auth_session_info *session_info,
5486 struct messaging_context *msg_ctx,
5488 union spoolss_DriverInfo *r,
5490 const char *servername,
5491 const char *architecture,
5494 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5495 struct spoolss_DriverInfo8 *driver;
5497 struct dcerpc_binding_handle *b;
5498 TALLOC_CTX *tmp_ctx = NULL;
5501 return WERR_UNKNOWN_LEVEL;
5504 tmp_ctx = talloc_new(mem_ctx);
5509 result = winreg_printer_binding_handle(tmp_ctx,
5513 if (!W_ERROR_IS_OK(result)) {
5517 result = winreg_get_printer(tmp_ctx, b,
5518 lp_const_servicename(snum),
5521 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5522 win_errstr(result)));
5524 if (!W_ERROR_IS_OK(result)) {
5525 result = WERR_INVALID_PRINTER_NAME;
5529 result = winreg_get_driver(tmp_ctx, b,
5531 pinfo2->drivername, version, &driver);
5533 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5534 win_errstr(result)));
5536 if (!W_ERROR_IS_OK(result)) {
5538 * Is this a W2k client ?
5542 result = WERR_UNKNOWN_PRINTER_DRIVER;
5546 /* Yes - try again with a WinNT driver. */
5548 result = winreg_get_driver(tmp_ctx, b,
5552 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5553 win_errstr(result)));
5554 if (!W_ERROR_IS_OK(result)) {
5555 result = WERR_UNKNOWN_PRINTER_DRIVER;
5560 /* these are allocated on mem_ctx and not tmp_ctx because they are
5561 * the 'return value' and need to utlive this call */
5564 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5567 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5570 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5573 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5576 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5579 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5582 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5584 #if 0 /* disabled until marshalling issues are resolved - gd */
5586 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5590 result = WERR_UNKNOWN_LEVEL;
5595 talloc_free(tmp_ctx);
5599 /****************************************************************
5600 _spoolss_GetPrinterDriver2
5601 ****************************************************************/
5603 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5604 struct spoolss_GetPrinterDriver2 *r)
5606 struct printer_handle *printer;
5611 /* that's an [in out] buffer */
5613 if (!r->in.buffer && (r->in.offered != 0)) {
5614 return WERR_INVALID_PARAM;
5617 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5619 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5620 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5621 return WERR_INVALID_PRINTER_NAME;
5625 *r->out.server_major_version = 0;
5626 *r->out.server_minor_version = 0;
5628 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5632 result = construct_printer_driver_info_level(p->mem_ctx,
5633 get_session_info_system(),
5635 r->in.level, r->out.info,
5636 snum, printer->servername,
5638 r->in.client_major_version);
5639 if (!W_ERROR_IS_OK(result)) {
5640 TALLOC_FREE(r->out.info);
5644 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5645 r->out.info, r->in.level);
5646 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5648 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5652 /****************************************************************
5653 _spoolss_StartPagePrinter
5654 ****************************************************************/
5656 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5657 struct spoolss_StartPagePrinter *r)
5659 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5662 DEBUG(3,("_spoolss_StartPagePrinter: "
5663 "Error in startpageprinter printer handle\n"));
5667 Printer->page_started = true;
5671 /****************************************************************
5672 _spoolss_EndPagePrinter
5673 ****************************************************************/
5675 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5676 struct spoolss_EndPagePrinter *r)
5680 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5683 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5684 OUR_HANDLE(r->in.handle)));
5688 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5691 Printer->page_started = false;
5692 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5697 /****************************************************************
5698 _spoolss_StartDocPrinter
5699 ****************************************************************/
5701 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5702 struct spoolss_StartDocPrinter *r)
5704 struct spoolss_DocumentInfo1 *info_1;
5706 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5712 DEBUG(2,("_spoolss_StartDocPrinter: "
5713 "Invalid handle (%s:%u:%u)\n",
5714 OUR_HANDLE(r->in.handle)));
5718 if (Printer->jobid) {
5719 DEBUG(2, ("_spoolss_StartDocPrinter: "
5720 "StartDocPrinter called twice! "
5721 "(existing jobid = %d)\n", Printer->jobid));
5722 return WERR_INVALID_HANDLE;
5725 if (r->in.level != 1) {
5726 return WERR_UNKNOWN_LEVEL;
5729 info_1 = r->in.info.info1;
5732 * a nice thing with NT is it doesn't listen to what you tell it.
5733 * when asked to send _only_ RAW datas, it tries to send datas
5736 * So I add checks like in NT Server ...
5739 if (info_1->datatype) {
5740 if (strcmp(info_1->datatype, "RAW") != 0) {
5742 return WERR_INVALID_DATATYPE;
5746 /* get the share number of the printer */
5747 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5751 rc = get_remote_hostname(p->remote_address,
5757 if (strequal(rhost,"UNKNOWN")) {
5758 rhost = tsocket_address_inet_addr_string(p->remote_address,
5760 if (rhost == NULL) {
5765 werr = print_job_start(p->session_info,
5769 info_1->document_name,
5770 info_1->output_file,
5774 /* An error occured in print_job_start() so return an appropriate
5777 if (!W_ERROR_IS_OK(werr)) {
5781 Printer->document_started = true;
5782 *r->out.job_id = Printer->jobid;
5787 /****************************************************************
5788 _spoolss_EndDocPrinter
5789 ****************************************************************/
5791 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5792 struct spoolss_EndDocPrinter *r)
5794 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5799 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5800 OUR_HANDLE(r->in.handle)));
5804 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5808 Printer->document_started = false;
5809 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5810 if (!NT_STATUS_IS_OK(status)) {
5811 DEBUG(2, ("_spoolss_EndDocPrinter: "
5812 "print_job_end failed [%s]\n",
5813 nt_errstr(status)));
5817 return ntstatus_to_werror(status);
5820 /****************************************************************
5821 _spoolss_WritePrinter
5822 ****************************************************************/
5824 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5825 struct spoolss_WritePrinter *r)
5827 ssize_t buffer_written;
5829 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5832 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5833 OUR_HANDLE(r->in.handle)));
5834 *r->out.num_written = r->in._data_size;
5838 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5841 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5842 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5843 snum, Printer->jobid,
5844 (const char *)r->in.data.data,
5845 (size_t)r->in._data_size);
5846 if (buffer_written == (ssize_t)-1) {
5847 *r->out.num_written = 0;
5848 if (errno == ENOSPC)
5849 return WERR_NO_SPOOL_SPACE;
5851 return WERR_ACCESS_DENIED;
5854 *r->out.num_written = r->in._data_size;
5859 /********************************************************************
5860 * api_spoolss_getprinter
5861 * called from the spoolss dispatcher
5863 ********************************************************************/
5865 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5866 struct pipes_struct *p)
5868 const struct auth_session_info *session_info = p->session_info;
5870 WERROR errcode = WERR_BADFUNC;
5871 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5874 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5875 OUR_HANDLE(handle)));
5879 if (!get_printer_snum(p, handle, &snum, NULL))
5883 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5884 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5886 case SPOOLSS_PRINTER_CONTROL_RESUME:
5887 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5888 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5890 case SPOOLSS_PRINTER_CONTROL_PURGE:
5891 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5894 return WERR_UNKNOWN_LEVEL;
5901 /****************************************************************
5902 _spoolss_AbortPrinter
5903 * From MSDN: "Deletes printer's spool file if printer is configured
5905 ****************************************************************/
5907 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5908 struct spoolss_AbortPrinter *r)
5910 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5912 WERROR errcode = WERR_OK;
5915 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5916 OUR_HANDLE(r->in.handle)));
5920 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5923 if (!Printer->document_started) {
5924 return WERR_SPL_NO_STARTDOC;
5927 errcode = print_job_delete(p->session_info,
5935 /********************************************************************
5936 * called by spoolss_api_setprinter
5937 * when updating a printer description
5938 ********************************************************************/
5940 static WERROR update_printer_sec(struct policy_handle *handle,
5941 struct pipes_struct *p,
5942 struct sec_desc_buf *secdesc_ctr)
5944 struct spoolss_security_descriptor *new_secdesc = NULL;
5945 struct spoolss_security_descriptor *old_secdesc = NULL;
5946 const char *printer;
5949 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5950 struct dcerpc_binding_handle *b;
5951 TALLOC_CTX *tmp_ctx = NULL;
5953 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
5954 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
5955 OUR_HANDLE(handle)));
5957 result = WERR_BADFID;
5961 if (secdesc_ctr == NULL) {
5962 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
5963 result = WERR_INVALID_PARAM;
5966 printer = lp_const_servicename(snum);
5968 /* Check the user has permissions to change the security
5969 descriptor. By experimentation with two NT machines, the user
5970 requires Full Access to the printer to change security
5973 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
5974 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
5975 result = WERR_ACCESS_DENIED;
5979 tmp_ctx = talloc_new(p->mem_ctx);
5984 result = winreg_printer_binding_handle(tmp_ctx,
5985 get_session_info_system(),
5988 if (!W_ERROR_IS_OK(result)) {
5992 /* NT seems to like setting the security descriptor even though
5993 nothing may have actually changed. */
5994 result = winreg_get_printer_secdesc(tmp_ctx, b,
5997 if (!W_ERROR_IS_OK(result)) {
5998 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
5999 result = WERR_BADFID;
6003 if (DEBUGLEVEL >= 10) {
6004 struct security_acl *the_acl;
6007 the_acl = old_secdesc->dacl;
6008 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6009 printer, the_acl->num_aces));
6011 for (i = 0; i < the_acl->num_aces; i++) {
6012 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6013 &the_acl->aces[i].trustee),
6014 the_acl->aces[i].access_mask));
6017 the_acl = secdesc_ctr->sd->dacl;
6020 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6021 printer, the_acl->num_aces));
6023 for (i = 0; i < the_acl->num_aces; i++) {
6024 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6025 &the_acl->aces[i].trustee),
6026 the_acl->aces[i].access_mask));
6029 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6033 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6034 if (new_secdesc == NULL) {
6035 result = WERR_NOMEM;
6039 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6044 result = winreg_set_printer_secdesc(tmp_ctx, b,
6049 talloc_free(tmp_ctx);
6053 /********************************************************************
6054 Canonicalize printer info from a client
6055 ********************************************************************/
6057 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6058 struct spoolss_SetPrinterInfo2 *info2,
6061 fstring printername;
6064 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6065 "portname=%s drivername=%s comment=%s location=%s\n",
6066 info2->servername, info2->printername, info2->sharename,
6067 info2->portname, info2->drivername, info2->comment,
6070 /* we force some elements to "correct" values */
6071 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6072 if (info2->servername == NULL) {
6075 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6076 if (info2->sharename == NULL) {
6080 /* check to see if we allow printername != sharename */
6081 if (lp_force_printername(snum)) {
6082 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6083 lp_netbios_name(), info2->sharename);
6085 /* make sure printername is in \\server\printername format */
6086 fstrcpy(printername, info2->printername);
6088 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6089 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6093 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6094 lp_netbios_name(), p);
6096 if (info2->printername == NULL) {
6100 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6101 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6106 /****************************************************************************
6107 ****************************************************************************/
6109 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6111 char *cmd = lp_addport_cmd(talloc_tos());
6112 char *command = NULL;
6114 bool is_print_op = false;
6117 return WERR_ACCESS_DENIED;
6120 command = talloc_asprintf(ctx,
6121 "%s \"%s\" \"%s\"", cmd, portname, uri );
6127 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6129 DEBUG(10,("Running [%s]\n", command));
6131 /********* BEGIN SePrintOperatorPrivilege **********/
6136 ret = smbrun(command, NULL);
6141 /********* END SePrintOperatorPrivilege **********/
6143 DEBUGADD(10,("returned [%d]\n", ret));
6145 TALLOC_FREE(command);
6148 return WERR_ACCESS_DENIED;
6154 /****************************************************************************
6155 ****************************************************************************/
6157 static bool spoolss_conn_snum_used(struct smbd_server_connection *sconn,
6161 * As we do not know if we are embedded in the file server process
6162 * or not, we have to pretend that all shares are in use.
6167 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6168 struct spoolss_SetPrinterInfo2 *info2,
6169 const char *remote_machine,
6170 struct messaging_context *msg_ctx)
6172 char *cmd = lp_addprinter_cmd(talloc_tos());
6174 char *command = NULL;
6178 bool is_print_op = false;
6180 if (!remote_machine) {
6184 command = talloc_asprintf(ctx,
6185 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6186 cmd, info2->printername, info2->sharename,
6187 info2->portname, info2->drivername,
6188 info2->location, info2->comment, remote_machine);
6194 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6196 DEBUG(10,("Running [%s]\n", command));
6198 /********* BEGIN SePrintOperatorPrivilege **********/
6203 if ( (ret = smbrun(command, &fd)) == 0 ) {
6204 /* Tell everyone we updated smb.conf. */
6205 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6211 /********* END SePrintOperatorPrivilege **********/
6213 DEBUGADD(10,("returned [%d]\n", ret));
6215 TALLOC_FREE(command);
6223 /* reload our services immediately */
6225 reload_services(NULL, spoolss_conn_snum_used, false);
6229 /* Get lines and convert them back to dos-codepage */
6230 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6231 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6234 /* Set the portname to what the script says the portname should be. */
6235 /* but don't require anything to be return from the script exit a good error code */
6238 /* Set the portname to what the script says the portname should be. */
6239 info2->portname = talloc_strdup(ctx, qlines[0]);
6240 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6243 TALLOC_FREE(qlines);
6247 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6248 const struct auth_session_info *session_info,
6249 struct messaging_context *msg_ctx,
6251 struct spoolss_SetPrinterInfo2 *printer,
6252 struct spoolss_PrinterInfo2 *old_printer)
6254 bool force_update = (old_printer == NULL);
6255 const char *dnsdomname;
6256 const char *longname;
6257 const char *uncname;
6258 const char *spooling;
6260 WERROR result = WERR_OK;
6261 struct dcerpc_binding_handle *b;
6262 TALLOC_CTX *tmp_ctx;
6265 tmp_ctx = talloc_new(mem_ctx);
6270 result = winreg_printer_binding_handle(tmp_ctx,
6274 if (!W_ERROR_IS_OK(result)) {
6278 if (printer->drivername != NULL &&
6280 !strequal(printer->drivername, old_printer->drivername))) {
6281 ok = push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6283 DEBUG(0, ("%s data corrupted\n", SPOOL_REG_DRIVERNAME));
6284 result = WERR_INVALID_DATA;
6287 result = winreg_set_printer_dataex(tmp_ctx, b,
6289 SPOOL_DSSPOOLER_KEY,
6290 SPOOL_REG_DRIVERNAME,
6294 if (!W_ERROR_IS_OK(result)) {
6295 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DRIVERNAME));
6299 if (!force_update) {
6300 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6301 printer->drivername));
6303 notify_printer_driver(server_event_context(), msg_ctx,
6304 snum, printer->drivername ?
6305 printer->drivername : "");
6309 if (printer->comment != NULL &&
6311 !strequal(printer->comment, old_printer->comment))) {
6312 ok = push_reg_sz(tmp_ctx, &buffer, printer->comment);
6314 DEBUG(0, ("comment data corrupted\n"));
6315 result = WERR_INVALID_DATA;
6318 result = winreg_set_printer_dataex(tmp_ctx, b,
6320 SPOOL_DSSPOOLER_KEY,
6321 SPOOL_REG_DESCRIPTION,
6325 if (!W_ERROR_IS_OK(result)) {
6326 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_DESCRIPTION));
6330 if (!force_update) {
6331 notify_printer_comment(server_event_context(), msg_ctx,
6332 snum, printer->comment ?
6333 printer->comment : "");
6337 if (printer->sharename != NULL &&
6339 !strequal(printer->sharename, old_printer->sharename))) {
6340 ok = push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6342 DEBUG(0, ("sharename data corrupted\n"));
6343 result = WERR_INVALID_DATA;
6346 result = winreg_set_printer_dataex(tmp_ctx, b,
6348 SPOOL_DSSPOOLER_KEY,
6349 SPOOL_REG_PRINTSHARENAME,
6353 if (!W_ERROR_IS_OK(result)) {
6354 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6358 if (!force_update) {
6359 notify_printer_sharename(server_event_context(),
6361 snum, printer->sharename ?
6362 printer->sharename : "");
6366 if (printer->printername != NULL &&
6368 !strequal(printer->printername, old_printer->printername))) {
6371 p = strrchr(printer->printername, '\\' );
6375 p = printer->printername;
6378 ok = push_reg_sz(tmp_ctx, &buffer, p);
6380 DEBUG(0, ("printername data corrupted\n"));
6381 result = WERR_INVALID_DATA;
6384 result = winreg_set_printer_dataex(tmp_ctx, b,
6386 SPOOL_DSSPOOLER_KEY,
6387 SPOOL_REG_PRINTERNAME,
6391 if (!W_ERROR_IS_OK(result)) {
6392 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSHARENAME));
6396 if (!force_update) {
6397 notify_printer_printername(server_event_context(),
6398 msg_ctx, snum, p ? p : "");
6402 if (printer->portname != NULL &&
6404 !strequal(printer->portname, old_printer->portname))) {
6405 ok = push_reg_sz(tmp_ctx, &buffer, printer->portname);
6407 DEBUG(0, ("portname data corrupted\n"));
6408 result = WERR_INVALID_DATA;
6411 result = winreg_set_printer_dataex(tmp_ctx, b,
6413 SPOOL_DSSPOOLER_KEY,
6418 if (!W_ERROR_IS_OK(result)) {
6419 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PORTNAME));
6423 if (!force_update) {
6424 notify_printer_port(server_event_context(),
6425 msg_ctx, snum, printer->portname ?
6426 printer->portname : "");
6430 if (printer->location != NULL &&
6432 !strequal(printer->location, old_printer->location))) {
6433 ok = push_reg_sz(tmp_ctx, &buffer, printer->location);
6435 DEBUG(0, ("location data corrupted\n"));
6436 result = WERR_INVALID_DATA;
6439 result = winreg_set_printer_dataex(tmp_ctx, b,
6441 SPOOL_DSSPOOLER_KEY,
6446 if (!W_ERROR_IS_OK(result)) {
6447 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_LOCATION));
6451 if (!force_update) {
6452 notify_printer_location(server_event_context(),
6455 printer->location : "");
6459 if (printer->sepfile != NULL &&
6461 !strequal(printer->sepfile, old_printer->sepfile))) {
6462 ok = push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6464 DEBUG(0, ("sepfile data corrupted\n"));
6465 result = WERR_INVALID_DATA;
6468 result = winreg_set_printer_dataex(tmp_ctx, b,
6470 SPOOL_DSSPOOLER_KEY,
6471 SPOOL_REG_PRINTSEPARATORFILE,
6475 if (!W_ERROR_IS_OK(result)) {
6476 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSEPARATORFILE));
6480 if (!force_update) {
6481 notify_printer_sepfile(server_event_context(),
6484 printer->sepfile : "");
6488 if (printer->starttime != 0 &&
6490 printer->starttime != old_printer->starttime)) {
6491 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6492 SIVAL(buffer.data, 0, printer->starttime);
6493 result = winreg_set_printer_dataex(tmp_ctx, b,
6495 SPOOL_DSSPOOLER_KEY,
6496 SPOOL_REG_PRINTSTARTTIME,
6500 if (!W_ERROR_IS_OK(result)) {
6501 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTSTARTTIME));
6506 if (printer->untiltime != 0 &&
6508 printer->untiltime != old_printer->untiltime)) {
6509 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6510 SIVAL(buffer.data, 0, printer->untiltime);
6511 result = winreg_set_printer_dataex(tmp_ctx, b,
6513 SPOOL_DSSPOOLER_KEY,
6514 SPOOL_REG_PRINTENDTIME,
6518 if (!W_ERROR_IS_OK(result)) {
6519 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6524 if (force_update || printer->priority != old_printer->priority) {
6525 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6526 SIVAL(buffer.data, 0, printer->priority);
6527 result = winreg_set_printer_dataex(tmp_ctx, b,
6529 SPOOL_DSSPOOLER_KEY,
6534 if (!W_ERROR_IS_OK(result)) {
6535 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6540 if (force_update || printer->attributes != old_printer->attributes) {
6541 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6542 SIVAL(buffer.data, 0, (printer->attributes &
6543 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6544 result = winreg_set_printer_dataex(tmp_ctx, b,
6546 SPOOL_DSSPOOLER_KEY,
6547 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6551 if (!W_ERROR_IS_OK(result)) {
6552 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_PRINTENDTIME));
6556 switch (printer->attributes & 0x3) {
6558 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6561 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6564 spooling = SPOOL_REGVAL_PRINTDIRECT;
6567 spooling = "unknown";
6569 ok = push_reg_sz(tmp_ctx, &buffer, spooling);
6571 DEBUG(0, ("printSpooling data corrupted\n"));
6572 result = WERR_INVALID_DATA;
6575 winreg_set_printer_dataex(tmp_ctx, b,
6577 SPOOL_DSSPOOLER_KEY,
6578 SPOOL_REG_PRINTSPOOLING,
6584 ok = push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6586 DEBUG(0, ("shortServerName data corrupted\n"));
6587 result = WERR_INVALID_DATA;
6590 result = winreg_set_printer_dataex(tmp_ctx, b,
6592 SPOOL_DSSPOOLER_KEY,
6593 SPOOL_REG_SHORTSERVERNAME,
6597 if (!W_ERROR_IS_OK(result)) {
6598 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SHORTSERVERNAME));
6602 dnsdomname = get_mydnsfullname();
6603 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6604 longname = talloc_strdup(tmp_ctx, dnsdomname);
6606 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6608 if (longname == NULL) {
6609 result = WERR_NOMEM;
6613 ok = push_reg_sz(tmp_ctx, &buffer, longname);
6615 DEBUG(0, ("longname data corrupted\n"));
6616 result = WERR_INVALID_DATA;
6619 result = winreg_set_printer_dataex(tmp_ctx, b,
6621 SPOOL_DSSPOOLER_KEY,
6622 SPOOL_REG_SERVERNAME,
6626 if (!W_ERROR_IS_OK(result)) {
6627 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_SERVERNAME));
6631 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6632 lp_netbios_name(), printer->sharename);
6633 ok = push_reg_sz(tmp_ctx, &buffer, uncname);
6635 DEBUG(0, ("uncName data corrupted\n"));
6636 result = WERR_INVALID_DATA;
6639 result = winreg_set_printer_dataex(tmp_ctx, b,
6641 SPOOL_DSSPOOLER_KEY,
6646 if (!W_ERROR_IS_OK(result)) {
6647 DEBUG(0, ("Failed to set %s\n", SPOOL_REG_UNCNAME));
6652 talloc_free(tmp_ctx);
6656 /********************************************************************
6657 * Called by spoolss_api_setprinter
6658 * when updating a printer description.
6659 ********************************************************************/
6661 static WERROR update_printer(struct pipes_struct *p,
6662 struct policy_handle *handle,
6663 struct spoolss_SetPrinterInfoCtr *info_ctr,
6664 struct spoolss_DeviceMode *devmode)
6666 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6667 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6668 struct spoolss_PrinterInfo2 *old_printer;
6669 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6671 WERROR result = WERR_OK;
6672 TALLOC_CTX *tmp_ctx;
6673 struct dcerpc_binding_handle *b;
6675 DEBUG(8,("update_printer\n"));
6677 tmp_ctx = talloc_new(p->mem_ctx);
6678 if (tmp_ctx == NULL) {
6683 result = WERR_BADFID;
6687 if (!get_printer_snum(p, handle, &snum, NULL)) {
6688 result = WERR_BADFID;
6692 result = winreg_printer_binding_handle(tmp_ctx,
6693 get_session_info_system(),
6696 if (!W_ERROR_IS_OK(result)) {
6700 result = winreg_get_printer(tmp_ctx, b,
6701 lp_const_servicename(snum),
6703 if (!W_ERROR_IS_OK(result)) {
6704 result = WERR_BADFID;
6708 /* Do sanity check on the requested changes for Samba */
6709 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6710 result = WERR_INVALID_PARAM;
6714 /* FIXME!!! If the driver has changed we really should verify that
6715 it is installed before doing much else --jerry */
6717 /* Check calling user has permission to update printer description */
6718 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6719 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6720 result = WERR_ACCESS_DENIED;
6724 /* Call addprinter hook */
6725 /* Check changes to see if this is really needed */
6727 if (*lp_addprinter_cmd(talloc_tos()) &&
6728 (!strequal(printer->drivername, old_printer->drivername) ||
6729 !strequal(printer->comment, old_printer->comment) ||
6730 !strequal(printer->portname, old_printer->portname) ||
6731 !strequal(printer->location, old_printer->location)) )
6735 raddr = tsocket_address_inet_addr_string(p->remote_address,
6737 if (raddr == NULL) {
6741 /* add_printer_hook() will call reload_services() */
6742 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6745 result = WERR_ACCESS_DENIED;
6750 result = update_dsspooler(tmp_ctx,
6751 get_session_info_system(),
6756 if (!W_ERROR_IS_OK(result)) {
6760 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6762 if (devmode == NULL) {
6763 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6765 result = winreg_update_printer(tmp_ctx, b,
6773 talloc_free(tmp_ctx);
6778 /****************************************************************************
6779 ****************************************************************************/
6780 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6781 struct policy_handle *handle,
6782 struct spoolss_SetPrinterInfo7 *info7)
6785 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6788 struct printer_handle *Printer;
6790 if ( lp_security() != SEC_ADS ) {
6791 return WERR_UNKNOWN_LEVEL;
6794 Printer = find_printer_index_by_hnd(p, handle);
6796 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6801 if (!get_printer_snum(p, handle, &snum, NULL))
6804 result = winreg_get_printer_internal(p->mem_ctx,
6805 get_session_info_system(),
6807 lp_servicename(talloc_tos(), snum),
6809 if (!W_ERROR_IS_OK(result)) {
6813 nt_printer_publish(pinfo2,
6814 get_session_info_system(),
6819 TALLOC_FREE(pinfo2);
6822 return WERR_UNKNOWN_LEVEL;
6826 /********************************************************************
6827 ********************************************************************/
6829 static WERROR update_printer_devmode(struct pipes_struct *p,
6830 struct policy_handle *handle,
6831 struct spoolss_DeviceMode *devmode)
6834 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6835 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6837 DEBUG(8,("update_printer_devmode\n"));
6843 if (!get_printer_snum(p, handle, &snum, NULL)) {
6847 /* Check calling user has permission to update printer description */
6848 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6849 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6850 return WERR_ACCESS_DENIED;
6853 return winreg_update_printer_internal(p->mem_ctx,
6854 get_session_info_system(),
6856 lp_const_servicename(snum),
6864 /****************************************************************
6866 ****************************************************************/
6868 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6869 struct spoolss_SetPrinter *r)
6873 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6876 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6877 OUR_HANDLE(r->in.handle)));
6881 /* check the level */
6882 switch (r->in.info_ctr->level) {
6884 return control_printer(r->in.handle, r->in.command, p);
6886 result = update_printer(p, r->in.handle,
6888 r->in.devmode_ctr->devmode);
6889 if (!W_ERROR_IS_OK(result))
6891 if (r->in.secdesc_ctr->sd)
6892 result = update_printer_sec(r->in.handle, p,
6896 return update_printer_sec(r->in.handle, p,
6899 return publish_or_unpublish_printer(p, r->in.handle,
6900 r->in.info_ctr->info.info7);
6902 return update_printer_devmode(p, r->in.handle,
6903 r->in.devmode_ctr->devmode);
6905 return WERR_UNKNOWN_LEVEL;
6909 /****************************************************************
6910 _spoolss_FindClosePrinterNotify
6911 ****************************************************************/
6913 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6914 struct spoolss_FindClosePrinterNotify *r)
6916 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6919 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6920 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6924 if (Printer->notify.cli_chan != NULL &&
6925 Printer->notify.cli_chan->active_connections > 0) {
6928 if (Printer->printer_type == SPLHND_PRINTER) {
6929 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6934 srv_spoolss_replycloseprinter(snum, Printer);
6937 Printer->notify.flags=0;
6938 Printer->notify.options=0;
6939 Printer->notify.localmachine[0]='\0';
6940 Printer->notify.printerlocal=0;
6941 TALLOC_FREE(Printer->notify.option);
6946 /****************************************************************
6948 ****************************************************************/
6950 WERROR _spoolss_AddJob(struct pipes_struct *p,
6951 struct spoolss_AddJob *r)
6953 if (!r->in.buffer && (r->in.offered != 0)) {
6954 return WERR_INVALID_PARAM;
6957 /* this is what a NT server returns for AddJob. AddJob must fail on
6958 * non-local printers */
6960 if (r->in.level != 1) {
6961 return WERR_UNKNOWN_LEVEL;
6964 return WERR_INVALID_PARAM;
6967 /****************************************************************************
6969 ****************************************************************************/
6971 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6972 struct spoolss_JobInfo1 *r,
6973 const print_queue_struct *queue,
6974 int position, int snum,
6975 struct spoolss_PrinterInfo2 *pinfo2)
6979 t = gmtime(&queue->time);
6981 r->job_id = queue->sysjob;
6983 r->printer_name = lp_servicename(mem_ctx, snum);
6984 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6985 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6986 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6987 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6988 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6989 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6990 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6991 r->data_type = talloc_strdup(mem_ctx, "RAW");
6992 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6993 r->text_status = talloc_strdup(mem_ctx, "");
6994 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6996 r->status = nt_printj_status(queue->status);
6997 r->priority = queue->priority;
6998 r->position = position;
6999 r->total_pages = queue->page_count;
7000 r->pages_printed = 0; /* ??? */
7002 init_systemtime(&r->submitted, t);
7007 /****************************************************************************
7009 ****************************************************************************/
7011 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
7012 struct spoolss_JobInfo2 *r,
7013 const print_queue_struct *queue,
7014 int position, int snum,
7015 struct spoolss_PrinterInfo2 *pinfo2,
7016 struct spoolss_DeviceMode *devmode)
7020 t = gmtime(&queue->time);
7022 r->job_id = queue->sysjob;
7024 r->printer_name = lp_servicename(mem_ctx, snum);
7025 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
7026 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
7027 W_ERROR_HAVE_NO_MEMORY(r->server_name);
7028 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
7029 W_ERROR_HAVE_NO_MEMORY(r->user_name);
7030 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
7031 W_ERROR_HAVE_NO_MEMORY(r->document_name);
7032 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
7033 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
7034 r->data_type = talloc_strdup(mem_ctx, "RAW");
7035 W_ERROR_HAVE_NO_MEMORY(r->data_type);
7036 r->print_processor = talloc_strdup(mem_ctx, "winprint");
7037 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
7038 r->parameters = talloc_strdup(mem_ctx, "");
7039 W_ERROR_HAVE_NO_MEMORY(r->parameters);
7040 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
7041 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
7043 r->devmode = devmode;
7045 r->text_status = talloc_strdup(mem_ctx, "");
7046 W_ERROR_HAVE_NO_MEMORY(r->text_status);
7050 r->status = nt_printj_status(queue->status);
7051 r->priority = queue->priority;
7052 r->position = position;
7055 r->total_pages = queue->page_count;
7056 r->size = queue->size;
7057 init_systemtime(&r->submitted, t);
7059 r->pages_printed = 0; /* ??? */
7064 /****************************************************************************
7066 ****************************************************************************/
7068 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
7069 struct spoolss_JobInfo3 *r,
7070 const print_queue_struct *queue,
7071 const print_queue_struct *next_queue,
7072 int position, int snum,
7073 struct spoolss_PrinterInfo2 *pinfo2)
7075 r->job_id = queue->sysjob;
7078 r->next_job_id = next_queue->sysjob;
7085 /****************************************************************************
7086 Enumjobs at level 1.
7087 ****************************************************************************/
7089 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
7090 const print_queue_struct *queue,
7091 uint32_t num_queues, int snum,
7092 struct spoolss_PrinterInfo2 *pinfo2,
7093 union spoolss_JobInfo **info_p,
7096 union spoolss_JobInfo *info;
7098 WERROR result = WERR_OK;
7100 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7101 W_ERROR_HAVE_NO_MEMORY(info);
7103 *count = num_queues;
7105 for (i=0; i<*count; i++) {
7106 result = fill_job_info1(info,
7112 if (!W_ERROR_IS_OK(result)) {
7118 if (!W_ERROR_IS_OK(result)) {
7129 /****************************************************************************
7130 Enumjobs at level 2.
7131 ****************************************************************************/
7133 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7134 const print_queue_struct *queue,
7135 uint32_t num_queues, int snum,
7136 struct spoolss_PrinterInfo2 *pinfo2,
7137 union spoolss_JobInfo **info_p,
7140 union spoolss_JobInfo *info;
7142 WERROR result = WERR_OK;
7144 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7145 W_ERROR_HAVE_NO_MEMORY(info);
7147 *count = num_queues;
7149 for (i=0; i<*count; i++) {
7150 struct spoolss_DeviceMode *devmode;
7152 result = spoolss_create_default_devmode(info,
7153 pinfo2->printername,
7155 if (!W_ERROR_IS_OK(result)) {
7156 DEBUG(3, ("Can't proceed w/o a devmode!"));
7160 result = fill_job_info2(info,
7167 if (!W_ERROR_IS_OK(result)) {
7173 if (!W_ERROR_IS_OK(result)) {
7184 /****************************************************************************
7185 Enumjobs at level 3.
7186 ****************************************************************************/
7188 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7189 const print_queue_struct *queue,
7190 uint32_t num_queues, int snum,
7191 struct spoolss_PrinterInfo2 *pinfo2,
7192 union spoolss_JobInfo **info_p,
7195 union spoolss_JobInfo *info;
7197 WERROR result = WERR_OK;
7199 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7200 W_ERROR_HAVE_NO_MEMORY(info);
7202 *count = num_queues;
7204 for (i=0; i<*count; i++) {
7205 const print_queue_struct *next_queue = NULL;
7208 next_queue = &queue[i+1];
7211 result = fill_job_info3(info,
7218 if (!W_ERROR_IS_OK(result)) {
7224 if (!W_ERROR_IS_OK(result)) {
7235 /****************************************************************
7237 ****************************************************************/
7239 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7240 struct spoolss_EnumJobs *r)
7243 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7245 print_status_struct prt_status;
7246 print_queue_struct *queue = NULL;
7249 /* that's an [in out] buffer */
7251 if (!r->in.buffer && (r->in.offered != 0)) {
7252 return WERR_INVALID_PARAM;
7255 DEBUG(4,("_spoolss_EnumJobs\n"));
7259 *r->out.info = NULL;
7261 /* lookup the printer snum and tdb entry */
7263 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7267 result = winreg_get_printer_internal(p->mem_ctx,
7268 get_session_info_system(),
7270 lp_const_servicename(snum),
7272 if (!W_ERROR_IS_OK(result)) {
7276 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7277 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7278 count, prt_status.status, prt_status.message));
7282 TALLOC_FREE(pinfo2);
7286 switch (r->in.level) {
7288 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7289 pinfo2, r->out.info, r->out.count);
7292 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7293 pinfo2, r->out.info, r->out.count);
7296 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7297 pinfo2, r->out.info, r->out.count);
7300 result = WERR_UNKNOWN_LEVEL;
7305 TALLOC_FREE(pinfo2);
7307 if (!W_ERROR_IS_OK(result)) {
7311 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7313 *r->out.info, r->in.level,
7315 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7316 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7318 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7321 /****************************************************************
7322 _spoolss_ScheduleJob
7323 ****************************************************************/
7325 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7326 struct spoolss_ScheduleJob *r)
7331 /****************************************************************
7332 ****************************************************************/
7334 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7335 struct messaging_context *msg_ctx,
7336 const char *printer_name,
7338 struct spoolss_SetJobInfo1 *r)
7342 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7346 if (strequal(old_doc_name, r->document_name)) {
7350 if (!print_job_set_name(server_event_context(), msg_ctx,
7351 printer_name, job_id, r->document_name)) {
7358 /****************************************************************
7360 ****************************************************************/
7362 WERROR _spoolss_SetJob(struct pipes_struct *p,
7363 struct spoolss_SetJob *r)
7365 const struct auth_session_info *session_info = p->session_info;
7367 WERROR errcode = WERR_BADFUNC;
7369 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7373 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7374 return WERR_INVALID_PRINTER_NAME;
7377 switch (r->in.command) {
7378 case SPOOLSS_JOB_CONTROL_CANCEL:
7379 case SPOOLSS_JOB_CONTROL_DELETE:
7380 errcode = print_job_delete(session_info, p->msg_ctx,
7381 snum, r->in.job_id);
7382 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7386 case SPOOLSS_JOB_CONTROL_PAUSE:
7387 errcode = print_job_pause(session_info, p->msg_ctx,
7388 snum, r->in.job_id);
7390 case SPOOLSS_JOB_CONTROL_RESTART:
7391 case SPOOLSS_JOB_CONTROL_RESUME:
7392 errcode = print_job_resume(session_info, p->msg_ctx,
7393 snum, r->in.job_id);
7399 return WERR_UNKNOWN_LEVEL;
7402 if (!W_ERROR_IS_OK(errcode)) {
7406 if (r->in.ctr == NULL) {
7410 switch (r->in.ctr->level) {
7412 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7413 lp_const_servicename(snum),
7415 r->in.ctr->info.info1);
7421 return WERR_UNKNOWN_LEVEL;
7427 /****************************************************************************
7428 Enumerates all printer drivers by level and architecture.
7429 ****************************************************************************/
7431 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7432 const struct auth_session_info *session_info,
7433 struct messaging_context *msg_ctx,
7434 const char *servername,
7435 const char *architecture,
7437 union spoolss_DriverInfo **info_p,
7442 struct spoolss_DriverInfo8 *driver;
7443 union spoolss_DriverInfo *info = NULL;
7445 WERROR result = WERR_OK;
7446 uint32_t num_drivers;
7447 const char **drivers;
7448 struct dcerpc_binding_handle *b;
7449 TALLOC_CTX *tmp_ctx = NULL;
7454 tmp_ctx = talloc_new(mem_ctx);
7459 result = winreg_printer_binding_handle(tmp_ctx,
7463 if (!W_ERROR_IS_OK(result)) {
7467 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7468 result = winreg_get_driver_list(tmp_ctx, b,
7469 architecture, version,
7470 &num_drivers, &drivers);
7471 if (!W_ERROR_IS_OK(result)) {
7474 DEBUG(4, ("we have:[%d] drivers in environment"
7475 " [%s] and version [%d]\n",
7476 num_drivers, architecture, version));
7478 if (num_drivers != 0) {
7479 info = talloc_realloc(tmp_ctx, info,
7480 union spoolss_DriverInfo,
7481 count + num_drivers);
7483 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7484 "failed to enlarge driver info buffer!\n"));
7485 result = WERR_NOMEM;
7490 for (i = 0; i < num_drivers; i++) {
7491 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7493 result = winreg_get_driver(tmp_ctx, b,
7494 architecture, drivers[i],
7496 if (!W_ERROR_IS_OK(result)) {
7502 result = fill_printer_driver_info1(info, &info[count+i].info1,
7503 driver, servername);
7506 result = fill_printer_driver_info2(info, &info[count+i].info2,
7507 driver, servername);
7510 result = fill_printer_driver_info3(info, &info[count+i].info3,
7511 driver, servername);
7514 result = fill_printer_driver_info4(info, &info[count+i].info4,
7515 driver, servername);
7518 result = fill_printer_driver_info5(info, &info[count+i].info5,
7519 driver, servername);
7522 result = fill_printer_driver_info6(info, &info[count+i].info6,
7523 driver, servername);
7526 result = fill_printer_driver_info8(info, &info[count+i].info8,
7527 driver, servername);
7530 result = WERR_UNKNOWN_LEVEL;
7534 TALLOC_FREE(driver);
7536 if (!W_ERROR_IS_OK(result)) {
7541 count += num_drivers;
7542 TALLOC_FREE(drivers);
7546 if (W_ERROR_IS_OK(result)) {
7547 *info_p = talloc_move(mem_ctx, &info);
7551 talloc_free(tmp_ctx);
7555 /****************************************************************************
7556 Enumerates all printer drivers by level.
7557 ****************************************************************************/
7559 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7560 const struct auth_session_info *session_info,
7561 struct messaging_context *msg_ctx,
7562 const char *servername,
7563 const char *architecture,
7565 union spoolss_DriverInfo **info_p,
7569 WERROR result = WERR_OK;
7571 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7573 for (a=0; archi_table[a].long_archi != NULL; a++) {
7575 union spoolss_DriverInfo *info = NULL;
7578 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7582 archi_table[a].long_archi,
7586 if (!W_ERROR_IS_OK(result)) {
7590 for (i=0; i < count; i++) {
7591 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7592 info[i], info_p, count_p);
7599 return enumprinterdrivers_level_by_architecture(mem_ctx,
7609 /****************************************************************
7610 _spoolss_EnumPrinterDrivers
7611 ****************************************************************/
7613 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7614 struct spoolss_EnumPrinterDrivers *r)
7616 const char *cservername;
7619 /* that's an [in out] buffer */
7621 if (!r->in.buffer && (r->in.offered != 0)) {
7622 return WERR_INVALID_PARAM;
7625 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7629 *r->out.info = NULL;
7631 cservername = canon_servername(r->in.server);
7633 if (!is_myname_or_ipaddr(cservername)) {
7634 return WERR_UNKNOWN_PRINTER_DRIVER;
7637 result = enumprinterdrivers_level(p->mem_ctx,
7638 get_session_info_system(),
7645 if (!W_ERROR_IS_OK(result)) {
7649 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7650 spoolss_EnumPrinterDrivers,
7651 *r->out.info, r->in.level,
7653 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7654 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7656 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7659 /****************************************************************
7661 ****************************************************************/
7663 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7664 struct spoolss_EnumForms *r)
7670 *r->out.info = NULL;
7672 /* that's an [in out] buffer */
7674 if (!r->in.buffer && (r->in.offered != 0) ) {
7675 return WERR_INVALID_PARAM;
7678 DEBUG(4,("_spoolss_EnumForms\n"));
7679 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7680 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7682 switch (r->in.level) {
7684 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7685 get_session_info_system(),
7691 result = WERR_UNKNOWN_LEVEL;
7695 if (!W_ERROR_IS_OK(result)) {
7699 if (*r->out.count == 0) {
7700 return WERR_NO_MORE_ITEMS;
7703 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7705 *r->out.info, r->in.level,
7707 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7708 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7710 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7713 /****************************************************************
7715 ****************************************************************/
7717 WERROR _spoolss_GetForm(struct pipes_struct *p,
7718 struct spoolss_GetForm *r)
7722 /* that's an [in out] buffer */
7724 if (!r->in.buffer && (r->in.offered != 0)) {
7725 return WERR_INVALID_PARAM;
7728 DEBUG(4,("_spoolss_GetForm\n"));
7729 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7730 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7732 switch (r->in.level) {
7734 result = winreg_printer_getform1_internal(p->mem_ctx,
7735 get_session_info_system(),
7738 &r->out.info->info1);
7741 result = WERR_UNKNOWN_LEVEL;
7745 if (!W_ERROR_IS_OK(result)) {
7746 TALLOC_FREE(r->out.info);
7750 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7751 r->out.info, r->in.level);
7752 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7754 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7757 /****************************************************************************
7758 ****************************************************************************/
7760 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7761 struct spoolss_PortInfo1 *r,
7764 r->port_name = talloc_strdup(mem_ctx, name);
7765 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7770 /****************************************************************************
7771 TODO: This probably needs distinguish between TCP/IP and Local ports
7773 ****************************************************************************/
7775 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7776 struct spoolss_PortInfo2 *r,
7779 r->port_name = talloc_strdup(mem_ctx, name);
7780 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7782 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7783 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7785 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7786 W_ERROR_HAVE_NO_MEMORY(r->description);
7788 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7795 /****************************************************************************
7796 wrapper around the enumer ports command
7797 ****************************************************************************/
7799 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7801 char *cmd = lp_enumports_cmd(talloc_tos());
7802 char **qlines = NULL;
7803 char *command = NULL;
7811 /* if no hook then just fill in the default port */
7814 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7817 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7818 TALLOC_FREE(qlines);
7825 /* we have a valid enumport command */
7827 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7832 DEBUG(10,("Running [%s]\n", command));
7833 ret = smbrun(command, &fd);
7834 DEBUG(10,("Returned [%d]\n", ret));
7835 TALLOC_FREE(command);
7840 return WERR_ACCESS_DENIED;
7844 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7845 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7855 /****************************************************************************
7857 ****************************************************************************/
7859 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7860 union spoolss_PortInfo **info_p,
7863 union spoolss_PortInfo *info = NULL;
7865 WERROR result = WERR_OK;
7866 char **qlines = NULL;
7869 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7870 if (!W_ERROR_IS_OK(result)) {
7875 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7877 DEBUG(10,("Returning WERR_NOMEM\n"));
7878 result = WERR_NOMEM;
7882 for (i=0; i<numlines; i++) {
7883 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7884 result = fill_port_1(info, &info[i].info1, qlines[i]);
7885 if (!W_ERROR_IS_OK(result)) {
7890 TALLOC_FREE(qlines);
7893 if (!W_ERROR_IS_OK(result)) {
7895 TALLOC_FREE(qlines);
7907 /****************************************************************************
7909 ****************************************************************************/
7911 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7912 union spoolss_PortInfo **info_p,
7915 union spoolss_PortInfo *info = NULL;
7917 WERROR result = WERR_OK;
7918 char **qlines = NULL;
7921 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7922 if (!W_ERROR_IS_OK(result)) {
7927 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7929 DEBUG(10,("Returning WERR_NOMEM\n"));
7930 result = WERR_NOMEM;
7934 for (i=0; i<numlines; i++) {
7935 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7936 result = fill_port_2(info, &info[i].info2, qlines[i]);
7937 if (!W_ERROR_IS_OK(result)) {
7942 TALLOC_FREE(qlines);
7945 if (!W_ERROR_IS_OK(result)) {
7947 TALLOC_FREE(qlines);
7959 /****************************************************************
7961 ****************************************************************/
7963 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7964 struct spoolss_EnumPorts *r)
7968 /* that's an [in out] buffer */
7970 if (!r->in.buffer && (r->in.offered != 0)) {
7971 return WERR_INVALID_PARAM;
7974 DEBUG(4,("_spoolss_EnumPorts\n"));
7978 *r->out.info = NULL;
7980 switch (r->in.level) {
7982 result = enumports_level_1(p->mem_ctx, r->out.info,
7986 result = enumports_level_2(p->mem_ctx, r->out.info,
7990 return WERR_UNKNOWN_LEVEL;
7993 if (!W_ERROR_IS_OK(result)) {
7997 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7999 *r->out.info, r->in.level,
8001 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8002 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8004 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8007 /****************************************************************************
8008 ****************************************************************************/
8010 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
8012 struct spoolss_SetPrinterInfoCtr *info_ctr,
8013 struct spoolss_DeviceMode *devmode,
8014 struct security_descriptor *secdesc,
8015 struct spoolss_UserLevelCtr *user_ctr,
8016 struct policy_handle *handle)
8018 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
8019 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
8021 WERROR err = WERR_OK;
8023 /* samba does not have a concept of local, non-shared printers yet, so
8024 * make sure we always setup sharename - gd */
8025 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
8026 (info2->printername != NULL && info2->printername[0] != '\0')) {
8027 DEBUG(5, ("spoolss_addprinterex_level_2: "
8028 "no sharename has been set, setting printername %s as sharename\n",
8029 info2->printername));
8030 info2->sharename = info2->printername;
8033 /* check to see if the printer already exists */
8034 if ((snum = print_queue_snum(info2->sharename)) != -1) {
8035 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8037 return WERR_PRINTER_ALREADY_EXISTS;
8040 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
8041 if ((snum = print_queue_snum(info2->printername)) != -1) {
8042 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
8043 info2->printername));
8044 return WERR_PRINTER_ALREADY_EXISTS;
8048 /* validate printer info struct */
8049 if (!info2->printername || strlen(info2->printername) == 0) {
8050 return WERR_INVALID_PRINTER_NAME;
8052 if (!info2->portname || strlen(info2->portname) == 0) {
8053 return WERR_UNKNOWN_PORT;
8055 if (!info2->drivername || strlen(info2->drivername) == 0) {
8056 return WERR_UNKNOWN_PRINTER_DRIVER;
8058 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
8059 return WERR_UNKNOWN_PRINTPROCESSOR;
8062 /* FIXME!!! smbd should check to see if the driver is installed before
8063 trying to add a printer like this --jerry */
8065 if (*lp_addprinter_cmd(talloc_tos()) ) {
8068 raddr = tsocket_address_inet_addr_string(p->remote_address,
8070 if (raddr == NULL) {
8074 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
8077 return WERR_ACCESS_DENIED;
8080 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
8081 "smb.conf parameter \"addprinter command\" is defined. This "
8082 "parameter must exist for this call to succeed\n",
8083 info2->sharename ));
8086 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8087 return WERR_ACCESS_DENIED;
8090 /* you must be a printer admin to add a new printer */
8091 if (!print_access_check(p->session_info,
8094 PRINTER_ACCESS_ADMINISTER)) {
8095 return WERR_ACCESS_DENIED;
8099 * Do sanity check on the requested changes for Samba.
8102 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8103 return WERR_INVALID_PARAM;
8106 if (devmode == NULL) {
8107 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8110 err = update_dsspooler(p->mem_ctx,
8111 get_session_info_system(),
8116 if (!W_ERROR_IS_OK(err)) {
8120 err = winreg_update_printer_internal(p->mem_ctx,
8121 get_session_info_system(),
8128 if (!W_ERROR_IS_OK(err)) {
8132 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8133 if (!W_ERROR_IS_OK(err)) {
8134 /* Handle open failed - remove addition. */
8135 ZERO_STRUCTP(handle);
8142 /****************************************************************
8143 _spoolss_AddPrinterEx
8144 ****************************************************************/
8146 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8147 struct spoolss_AddPrinterEx *r)
8149 switch (r->in.info_ctr->level) {
8151 /* we don't handle yet */
8152 /* but I know what to do ... */
8153 return WERR_UNKNOWN_LEVEL;
8155 return spoolss_addprinterex_level_2(p, r->in.server,
8157 r->in.devmode_ctr->devmode,
8158 r->in.secdesc_ctr->sd,
8159 r->in.userlevel_ctr,
8162 return WERR_UNKNOWN_LEVEL;
8166 /****************************************************************
8168 ****************************************************************/
8170 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8171 struct spoolss_AddPrinter *r)
8173 struct spoolss_AddPrinterEx a;
8174 struct spoolss_UserLevelCtr userlevel_ctr;
8176 ZERO_STRUCT(userlevel_ctr);
8178 userlevel_ctr.level = 1;
8180 a.in.server = r->in.server;
8181 a.in.info_ctr = r->in.info_ctr;
8182 a.in.devmode_ctr = r->in.devmode_ctr;
8183 a.in.secdesc_ctr = r->in.secdesc_ctr;
8184 a.in.userlevel_ctr = &userlevel_ctr;
8185 a.out.handle = r->out.handle;
8187 return _spoolss_AddPrinterEx(p, &a);
8190 /****************************************************************
8191 _spoolss_AddPrinterDriverEx
8192 ****************************************************************/
8194 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8195 struct spoolss_AddPrinterDriverEx *r)
8197 WERROR err = WERR_OK;
8198 const char *driver_name = NULL;
8203 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8204 fn = "_spoolss_AddPrinterDriver";
8206 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8207 fn = "_spoolss_AddPrinterDriverEx";
8210 return WERR_INVALID_PARAM;
8214 * we only support the semantics of AddPrinterDriver()
8215 * i.e. only copy files that are newer than existing ones
8218 if (r->in.flags == 0) {
8219 return WERR_INVALID_PARAM;
8222 if (r->in.flags != APD_COPY_NEW_FILES) {
8223 return WERR_ACCESS_DENIED;
8227 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8228 /* Clever hack from Martin Zielinski <mz@seh.de>
8229 * to allow downgrade from level 8 (Vista).
8231 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8232 r->in.info_ctr->level));
8233 return WERR_UNKNOWN_LEVEL;
8236 DEBUG(5,("Cleaning driver's information\n"));
8237 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8238 if (!W_ERROR_IS_OK(err))
8241 DEBUG(5,("Moving driver to final destination\n"));
8242 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8243 if (!W_ERROR_IS_OK(err)) {
8247 err = winreg_add_driver_internal(p->mem_ctx,
8248 get_session_info_system(),
8253 if (!W_ERROR_IS_OK(err)) {
8258 * I think this is where he DrvUpgradePrinter() hook would be
8259 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8260 * server. Right now, we just need to send ourselves a message
8261 * to update each printer bound to this driver. --jerry
8264 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8265 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8273 /****************************************************************
8274 _spoolss_AddPrinterDriver
8275 ****************************************************************/
8277 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8278 struct spoolss_AddPrinterDriver *r)
8280 struct spoolss_AddPrinterDriverEx a;
8282 switch (r->in.info_ctr->level) {
8289 return WERR_UNKNOWN_LEVEL;
8292 a.in.servername = r->in.servername;
8293 a.in.info_ctr = r->in.info_ctr;
8294 a.in.flags = APD_COPY_NEW_FILES;
8296 return _spoolss_AddPrinterDriverEx(p, &a);
8299 /****************************************************************************
8300 ****************************************************************************/
8302 struct _spoolss_paths {
8308 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8310 static const struct _spoolss_paths spoolss_paths[]= {
8311 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8312 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8315 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8316 const char *servername,
8317 const char *environment,
8321 const char *pservername = NULL;
8322 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8323 const char *short_archi;
8327 /* environment may be empty */
8328 if (environment && strlen(environment)) {
8329 long_archi = environment;
8332 /* servername may be empty */
8333 if (servername && strlen(servername)) {
8334 pservername = canon_servername(servername);
8336 if (!is_myname_or_ipaddr(pservername)) {
8337 return WERR_INVALID_PARAM;
8341 if (!(short_archi = get_short_archi(long_archi))) {
8342 return WERR_INVALID_ENVIRONMENT;
8345 switch (component) {
8346 case SPOOLSS_PRTPROCS_PATH:
8347 case SPOOLSS_DRIVER_PATH:
8349 *path = talloc_asprintf(mem_ctx,
8352 spoolss_paths[component].share,
8355 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8356 SPOOLSS_DEFAULT_SERVER_PATH,
8357 spoolss_paths[component].dir,
8362 return WERR_INVALID_PARAM;
8372 /****************************************************************************
8373 ****************************************************************************/
8375 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8376 const char *servername,
8377 const char *environment,
8378 struct spoolss_DriverDirectoryInfo1 *r)
8383 werr = compose_spoolss_server_path(mem_ctx,
8386 SPOOLSS_DRIVER_PATH,
8388 if (!W_ERROR_IS_OK(werr)) {
8392 DEBUG(4,("printer driver directory: [%s]\n", path));
8394 r->directory_name = path;
8399 /****************************************************************
8400 _spoolss_GetPrinterDriverDirectory
8401 ****************************************************************/
8403 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8404 struct spoolss_GetPrinterDriverDirectory *r)
8408 /* that's an [in out] buffer */
8410 if (!r->in.buffer && (r->in.offered != 0)) {
8411 return WERR_INVALID_PARAM;
8414 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8419 /* r->in.level is ignored */
8421 werror = getprinterdriverdir_level_1(p->mem_ctx,
8424 &r->out.info->info1);
8425 if (!W_ERROR_IS_OK(werror)) {
8426 TALLOC_FREE(r->out.info);
8430 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8431 r->out.info, r->in.level);
8432 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8434 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8437 /****************************************************************
8438 _spoolss_EnumPrinterData
8439 ****************************************************************/
8441 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8442 struct spoolss_EnumPrinterData *r)
8445 struct spoolss_EnumPrinterDataEx r2;
8447 struct spoolss_PrinterEnumValues *info, *val = NULL;
8450 r2.in.handle = r->in.handle;
8451 r2.in.key_name = "PrinterDriverData";
8453 r2.out.count = &count;
8454 r2.out.info = &info;
8455 r2.out.needed = &needed;
8457 result = _spoolss_EnumPrinterDataEx(p, &r2);
8458 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8459 r2.in.offered = needed;
8460 result = _spoolss_EnumPrinterDataEx(p, &r2);
8462 if (!W_ERROR_IS_OK(result)) {
8467 * The NT machine wants to know the biggest size of value and data
8469 * cf: MSDN EnumPrinterData remark section
8472 if (!r->in.value_offered && !r->in.data_offered) {
8473 uint32_t biggest_valuesize = 0;
8474 uint32_t biggest_datasize = 0;
8477 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8479 for (i=0; i<count; i++) {
8481 name_length = strlen(info[i].value_name);
8482 if (strlen(info[i].value_name) > biggest_valuesize) {
8483 biggest_valuesize = name_length;
8486 if (info[i].data_length > biggest_datasize) {
8487 biggest_datasize = info[i].data_length;
8490 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8494 /* the value is an UNICODE string but real_value_size is the length
8495 in bytes including the trailing 0 */
8497 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8498 *r->out.data_needed = biggest_datasize;
8500 DEBUG(6,("final values: [%d], [%d]\n",
8501 *r->out.value_needed, *r->out.data_needed));
8506 if (r->in.enum_index < count) {
8507 val = &info[r->in.enum_index];
8511 /* out_value should default to "" or else NT4 has
8512 problems unmarshalling the response */
8514 if (r->in.value_offered) {
8515 *r->out.value_needed = 1;
8516 r->out.value_name = talloc_strdup(r, "");
8517 if (!r->out.value_name) {
8521 r->out.value_name = NULL;
8522 *r->out.value_needed = 0;
8525 /* the data is counted in bytes */
8527 *r->out.data_needed = r->in.data_offered;
8529 result = WERR_NO_MORE_ITEMS;
8533 * - counted in bytes in the request
8534 * - counted in UNICODE chars in the max reply
8535 * - counted in bytes in the real size
8537 * take a pause *before* coding not *during* coding
8541 if (r->in.value_offered) {
8542 r->out.value_name = talloc_strdup(r, val->value_name);
8543 if (!r->out.value_name) {
8546 *r->out.value_needed = val->value_name_len;
8548 r->out.value_name = NULL;
8549 *r->out.value_needed = 0;
8554 *r->out.type = val->type;
8556 /* data - counted in bytes */
8559 * See the section "Dynamically Typed Query Parameters"
8563 if (r->out.data && val->data && val->data->data &&
8564 val->data_length && r->in.data_offered) {
8565 memcpy(r->out.data, val->data->data,
8566 MIN(val->data_length,r->in.data_offered));
8569 *r->out.data_needed = val->data_length;
8577 /****************************************************************
8578 _spoolss_SetPrinterData
8579 ****************************************************************/
8581 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8582 struct spoolss_SetPrinterData *r)
8584 struct spoolss_SetPrinterDataEx r2;
8586 r2.in.handle = r->in.handle;
8587 r2.in.key_name = "PrinterDriverData";
8588 r2.in.value_name = r->in.value_name;
8589 r2.in.type = r->in.type;
8590 r2.in.data = r->in.data;
8591 r2.in.offered = r->in.offered;
8593 return _spoolss_SetPrinterDataEx(p, &r2);
8596 /****************************************************************
8597 _spoolss_ResetPrinter
8598 ****************************************************************/
8600 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8601 struct spoolss_ResetPrinter *r)
8603 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8606 DEBUG(5,("_spoolss_ResetPrinter\n"));
8609 * All we do is to check to see if the handle and queue is valid.
8610 * This call really doesn't mean anything to us because we only
8611 * support RAW printing. --jerry
8615 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8616 OUR_HANDLE(r->in.handle)));
8620 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8624 /* blindly return success */
8628 /****************************************************************
8629 _spoolss_DeletePrinterData
8630 ****************************************************************/
8632 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8633 struct spoolss_DeletePrinterData *r)
8635 struct spoolss_DeletePrinterDataEx r2;
8637 r2.in.handle = r->in.handle;
8638 r2.in.key_name = "PrinterDriverData";
8639 r2.in.value_name = r->in.value_name;
8641 return _spoolss_DeletePrinterDataEx(p, &r2);
8644 /****************************************************************
8646 ****************************************************************/
8648 WERROR _spoolss_AddForm(struct pipes_struct *p,
8649 struct spoolss_AddForm *r)
8651 struct spoolss_AddFormInfo1 *form;
8653 WERROR status = WERR_OK;
8654 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8655 struct dcerpc_binding_handle *b;
8656 TALLOC_CTX *tmp_ctx = NULL;
8658 DEBUG(5,("_spoolss_AddForm\n"));
8661 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8662 OUR_HANDLE(r->in.handle)));
8666 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8667 and not a printer admin, then fail */
8669 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8670 !security_token_has_privilege(p->session_info->security_token,
8671 SEC_PRIV_PRINT_OPERATOR)) {
8672 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8673 return WERR_ACCESS_DENIED;
8676 if (r->in.info_ctr->level != 1) {
8677 return WERR_INVALID_LEVEL;
8680 form = r->in.info_ctr->info.info1;
8682 return WERR_INVALID_PARAM;
8685 switch (form->flags) {
8686 case SPOOLSS_FORM_USER:
8687 case SPOOLSS_FORM_BUILTIN:
8688 case SPOOLSS_FORM_PRINTER:
8691 return WERR_INVALID_PARAM;
8694 tmp_ctx = talloc_new(p->mem_ctx);
8699 status = winreg_printer_binding_handle(tmp_ctx,
8700 get_session_info_system(),
8703 if (!W_ERROR_IS_OK(status)) {
8707 status = winreg_printer_addform1(tmp_ctx, b, form);
8708 if (!W_ERROR_IS_OK(status)) {
8713 * ChangeID must always be set if this is a printer
8715 if (Printer->printer_type == SPLHND_PRINTER) {
8716 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8717 status = WERR_BADFID;
8721 status = winreg_printer_update_changeid(tmp_ctx, b,
8722 lp_const_servicename(snum));
8726 talloc_free(tmp_ctx);
8730 /****************************************************************
8732 ****************************************************************/
8734 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8735 struct spoolss_DeleteForm *r)
8737 const char *form_name = r->in.form_name;
8738 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8740 WERROR status = WERR_OK;
8741 struct dcerpc_binding_handle *b;
8742 TALLOC_CTX *tmp_ctx = NULL;
8744 DEBUG(5,("_spoolss_DeleteForm\n"));
8747 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8748 OUR_HANDLE(r->in.handle)));
8752 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8753 !security_token_has_privilege(p->session_info->security_token,
8754 SEC_PRIV_PRINT_OPERATOR)) {
8755 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8756 return WERR_ACCESS_DENIED;
8759 tmp_ctx = talloc_new(p->mem_ctx);
8764 status = winreg_printer_binding_handle(tmp_ctx,
8765 get_session_info_system(),
8768 if (!W_ERROR_IS_OK(status)) {
8772 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8773 if (!W_ERROR_IS_OK(status)) {
8778 * ChangeID must always be set if this is a printer
8780 if (Printer->printer_type == SPLHND_PRINTER) {
8781 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8782 status = WERR_BADFID;
8786 status = winreg_printer_update_changeid(tmp_ctx, b,
8787 lp_const_servicename(snum));
8791 talloc_free(tmp_ctx);
8795 /****************************************************************
8797 ****************************************************************/
8799 WERROR _spoolss_SetForm(struct pipes_struct *p,
8800 struct spoolss_SetForm *r)
8802 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8803 const char *form_name = r->in.form_name;
8805 WERROR status = WERR_OK;
8806 struct dcerpc_binding_handle *b;
8807 TALLOC_CTX *tmp_ctx = NULL;
8809 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8811 DEBUG(5,("_spoolss_SetForm\n"));
8814 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8815 OUR_HANDLE(r->in.handle)));
8819 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8820 and not a printer admin, then fail */
8822 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8823 !security_token_has_privilege(p->session_info->security_token,
8824 SEC_PRIV_PRINT_OPERATOR)) {
8825 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8826 return WERR_ACCESS_DENIED;
8829 tmp_ctx = talloc_new(p->mem_ctx);
8834 status = winreg_printer_binding_handle(tmp_ctx,
8835 get_session_info_system(),
8838 if (!W_ERROR_IS_OK(status)) {
8842 status = winreg_printer_setform1(tmp_ctx, b,
8845 if (!W_ERROR_IS_OK(status)) {
8850 * ChangeID must always be set if this is a printer
8852 if (Printer->printer_type == SPLHND_PRINTER) {
8853 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8854 status = WERR_BADFID;
8858 status = winreg_printer_update_changeid(tmp_ctx, b,
8859 lp_const_servicename(snum));
8863 talloc_free(tmp_ctx);
8867 /****************************************************************************
8868 fill_print_processor1
8869 ****************************************************************************/
8871 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8872 struct spoolss_PrintProcessorInfo1 *r,
8873 const char *print_processor_name)
8875 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8876 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8881 /****************************************************************************
8882 enumprintprocessors level 1.
8883 ****************************************************************************/
8885 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8886 union spoolss_PrintProcessorInfo **info_p,
8889 union spoolss_PrintProcessorInfo *info;
8892 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8893 W_ERROR_HAVE_NO_MEMORY(info);
8897 result = fill_print_processor1(info, &info[0].info1, "winprint");
8898 if (!W_ERROR_IS_OK(result)) {
8903 if (!W_ERROR_IS_OK(result)) {
8914 /****************************************************************
8915 _spoolss_EnumPrintProcessors
8916 ****************************************************************/
8918 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8919 struct spoolss_EnumPrintProcessors *r)
8923 /* that's an [in out] buffer */
8925 if (!r->in.buffer && (r->in.offered != 0)) {
8926 return WERR_INVALID_PARAM;
8929 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8932 * Enumerate the print processors ...
8934 * Just reply with "winprint", to keep NT happy
8935 * and I can use my nice printer checker.
8940 *r->out.info = NULL;
8942 if (!get_short_archi(r->in.environment)) {
8943 return WERR_INVALID_ENVIRONMENT;
8946 switch (r->in.level) {
8948 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8952 return WERR_UNKNOWN_LEVEL;
8955 if (!W_ERROR_IS_OK(result)) {
8959 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8960 spoolss_EnumPrintProcessors,
8961 *r->out.info, r->in.level,
8963 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8964 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8966 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8969 /****************************************************************************
8970 fill_printprocdatatype1
8971 ****************************************************************************/
8973 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8974 struct spoolss_PrintProcDataTypesInfo1 *r,
8975 const char *name_array)
8977 r->name_array = talloc_strdup(mem_ctx, name_array);
8978 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8983 /****************************************************************************
8984 enumprintprocdatatypes level 1.
8985 ****************************************************************************/
8987 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8988 union spoolss_PrintProcDataTypesInfo **info_p,
8992 union spoolss_PrintProcDataTypesInfo *info;
8994 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8995 W_ERROR_HAVE_NO_MEMORY(info);
8999 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
9000 if (!W_ERROR_IS_OK(result)) {
9005 if (!W_ERROR_IS_OK(result)) {
9016 /****************************************************************
9017 _spoolss_EnumPrintProcDataTypes
9018 ****************************************************************/
9020 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
9021 struct spoolss_EnumPrintProcDataTypes *r)
9025 /* that's an [in out] buffer */
9027 if (!r->in.buffer && (r->in.offered != 0)) {
9028 return WERR_INVALID_PARAM;
9031 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
9035 *r->out.info = NULL;
9037 if (r->in.print_processor_name == NULL ||
9038 !strequal(r->in.print_processor_name, "winprint")) {
9039 return WERR_UNKNOWN_PRINTPROCESSOR;
9042 switch (r->in.level) {
9044 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
9048 return WERR_UNKNOWN_LEVEL;
9051 if (!W_ERROR_IS_OK(result)) {
9055 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9056 spoolss_EnumPrintProcDataTypes,
9057 *r->out.info, r->in.level,
9059 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9060 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9062 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9065 /****************************************************************************
9067 ****************************************************************************/
9069 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
9070 struct spoolss_MonitorInfo1 *r,
9071 const char *monitor_name)
9073 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9074 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9079 /****************************************************************************
9081 ****************************************************************************/
9083 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
9084 struct spoolss_MonitorInfo2 *r,
9085 const char *monitor_name,
9086 const char *environment,
9087 const char *dll_name)
9089 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9090 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9091 r->environment = talloc_strdup(mem_ctx, environment);
9092 W_ERROR_HAVE_NO_MEMORY(r->environment);
9093 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9094 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9099 /****************************************************************************
9100 enumprintmonitors level 1.
9101 ****************************************************************************/
9103 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9104 union spoolss_MonitorInfo **info_p,
9107 union spoolss_MonitorInfo *info;
9108 WERROR result = WERR_OK;
9110 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9111 W_ERROR_HAVE_NO_MEMORY(info);
9115 result = fill_monitor_1(info, &info[0].info1,
9117 if (!W_ERROR_IS_OK(result)) {
9121 result = fill_monitor_1(info, &info[1].info1,
9123 if (!W_ERROR_IS_OK(result)) {
9128 if (!W_ERROR_IS_OK(result)) {
9139 /****************************************************************************
9140 enumprintmonitors level 2.
9141 ****************************************************************************/
9143 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9144 union spoolss_MonitorInfo **info_p,
9147 union spoolss_MonitorInfo *info;
9148 WERROR result = WERR_OK;
9150 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9151 W_ERROR_HAVE_NO_MEMORY(info);
9155 result = fill_monitor_2(info, &info[0].info2,
9157 "Windows NT X86", /* FIXME */
9159 if (!W_ERROR_IS_OK(result)) {
9163 result = fill_monitor_2(info, &info[1].info2,
9165 "Windows NT X86", /* FIXME */
9167 if (!W_ERROR_IS_OK(result)) {
9172 if (!W_ERROR_IS_OK(result)) {
9183 /****************************************************************
9184 _spoolss_EnumMonitors
9185 ****************************************************************/
9187 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9188 struct spoolss_EnumMonitors *r)
9192 /* that's an [in out] buffer */
9194 if (!r->in.buffer && (r->in.offered != 0)) {
9195 return WERR_INVALID_PARAM;
9198 DEBUG(5,("_spoolss_EnumMonitors\n"));
9201 * Enumerate the print monitors ...
9203 * Just reply with "Local Port", to keep NT happy
9204 * and I can use my nice printer checker.
9209 *r->out.info = NULL;
9211 switch (r->in.level) {
9213 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9217 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9221 return WERR_UNKNOWN_LEVEL;
9224 if (!W_ERROR_IS_OK(result)) {
9228 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9229 spoolss_EnumMonitors,
9230 *r->out.info, r->in.level,
9232 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9233 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9235 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9238 /****************************************************************************
9239 ****************************************************************************/
9241 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9242 const print_queue_struct *queue,
9243 int count, int snum,
9244 struct spoolss_PrinterInfo2 *pinfo2,
9246 struct spoolss_JobInfo1 *r)
9251 for (i=0; i<count; i++) {
9252 if (queue[i].sysjob == (int)jobid) {
9258 if (found == false) {
9259 /* NT treats not found as bad param... yet another bad choice */
9260 return WERR_INVALID_PARAM;
9263 return fill_job_info1(mem_ctx,
9271 /****************************************************************************
9272 ****************************************************************************/
9274 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9275 const print_queue_struct *queue,
9276 int count, int snum,
9277 struct spoolss_PrinterInfo2 *pinfo2,
9279 struct spoolss_JobInfo2 *r)
9283 struct spoolss_DeviceMode *devmode;
9286 for (i=0; i<count; i++) {
9287 if (queue[i].sysjob == (int)jobid) {
9293 if (found == false) {
9294 /* NT treats not found as bad param... yet another bad
9296 return WERR_INVALID_PARAM;
9300 * if the print job does not have a DEVMODE associated with it,
9301 * just use the one for the printer. A NULL devicemode is not
9302 * a failure condition
9305 devmode = print_job_devmode(mem_ctx, lp_const_servicename(snum), jobid);
9307 result = spoolss_create_default_devmode(mem_ctx,
9308 pinfo2->printername,
9310 if (!W_ERROR_IS_OK(result)) {
9311 DEBUG(3, ("Can't proceed w/o a devmode!"));
9316 return fill_job_info2(mem_ctx,
9325 /****************************************************************
9327 ****************************************************************/
9329 WERROR _spoolss_GetJob(struct pipes_struct *p,
9330 struct spoolss_GetJob *r)
9332 WERROR result = WERR_OK;
9333 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9336 print_queue_struct *queue = NULL;
9337 print_status_struct prt_status;
9339 /* that's an [in out] buffer */
9341 if (!r->in.buffer && (r->in.offered != 0)) {
9342 return WERR_INVALID_PARAM;
9345 DEBUG(5,("_spoolss_GetJob\n"));
9349 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9353 result = winreg_get_printer_internal(p->mem_ctx,
9354 get_session_info_system(),
9356 lp_const_servicename(snum),
9358 if (!W_ERROR_IS_OK(result)) {
9362 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9364 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9365 count, prt_status.status, prt_status.message));
9367 switch (r->in.level) {
9369 result = getjob_level_1(p->mem_ctx,
9370 queue, count, snum, pinfo2,
9371 r->in.job_id, &r->out.info->info1);
9374 result = getjob_level_2(p->mem_ctx,
9375 queue, count, snum, pinfo2,
9376 r->in.job_id, &r->out.info->info2);
9379 result = WERR_UNKNOWN_LEVEL;
9384 TALLOC_FREE(pinfo2);
9386 if (!W_ERROR_IS_OK(result)) {
9387 TALLOC_FREE(r->out.info);
9391 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9393 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9395 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9398 /****************************************************************
9399 _spoolss_GetPrinterDataEx
9400 ****************************************************************/
9402 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9403 struct spoolss_GetPrinterDataEx *r)
9406 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9407 const char *printer;
9409 WERROR result = WERR_OK;
9411 enum winreg_Type val_type = REG_NONE;
9412 uint8_t *val_data = NULL;
9413 uint32_t val_size = 0;
9414 struct dcerpc_binding_handle *b;
9415 TALLOC_CTX *tmp_ctx;
9417 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9419 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9420 r->in.key_name, r->in.value_name));
9422 /* in case of problem, return some default values */
9425 *r->out.type = REG_NONE;
9427 tmp_ctx = talloc_new(p->mem_ctx);
9433 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9434 OUR_HANDLE(r->in.handle)));
9435 result = WERR_BADFID;
9439 /* check to see if the keyname is valid */
9440 if (!strlen(r->in.key_name)) {
9441 result = WERR_INVALID_PARAM;
9445 /* Is the handle to a printer or to the server? */
9447 if (Printer->printer_type == SPLHND_SERVER) {
9449 union spoolss_PrinterData data;
9451 result = getprinterdata_printer_server(tmp_ctx,
9455 if (!W_ERROR_IS_OK(result)) {
9459 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9460 *r->out.type, &data);
9461 if (!W_ERROR_IS_OK(result)) {
9465 *r->out.needed = blob.length;
9467 if (r->in.offered >= *r->out.needed) {
9468 memcpy(r->out.data, blob.data, blob.length);
9475 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9476 result = WERR_BADFID;
9479 printer = lp_const_servicename(snum);
9481 result = winreg_printer_binding_handle(tmp_ctx,
9482 get_session_info_system(),
9485 if (!W_ERROR_IS_OK(result)) {
9489 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9490 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9491 strequal(r->in.value_name, "ChangeId")) {
9492 *r->out.type = REG_DWORD;
9494 if (r->in.offered >= *r->out.needed) {
9495 uint32_t changeid = 0;
9497 result = winreg_printer_get_changeid(tmp_ctx, b,
9500 if (!W_ERROR_IS_OK(result)) {
9504 SIVAL(r->out.data, 0, changeid);
9510 result = winreg_get_printer_dataex(tmp_ctx, b,
9517 if (!W_ERROR_IS_OK(result)) {
9521 *r->out.needed = val_size;
9522 *r->out.type = val_type;
9524 if (r->in.offered >= *r->out.needed) {
9525 memcpy(r->out.data, val_data, val_size);
9529 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9531 if (W_ERROR_IS_OK(result)) {
9532 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9535 talloc_free(tmp_ctx);
9539 /****************************************************************
9540 _spoolss_SetPrinterDataEx
9541 ****************************************************************/
9543 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9544 struct spoolss_SetPrinterDataEx *r)
9546 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9548 WERROR result = WERR_OK;
9549 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9551 struct dcerpc_binding_handle *b;
9552 TALLOC_CTX *tmp_ctx;
9554 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9556 /* From MSDN documentation of SetPrinterDataEx: pass request to
9557 SetPrinterData if key is "PrinterDriverData" */
9560 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9561 OUR_HANDLE(r->in.handle)));
9565 if (Printer->printer_type == SPLHND_SERVER) {
9566 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9567 "Not implemented for server handles yet\n"));
9568 return WERR_INVALID_PARAM;
9571 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9576 * Access check : NT returns "access denied" if you make a
9577 * SetPrinterData call without the necessary privildge.
9578 * we were originally returning OK if nothing changed
9579 * which made Win2k issue **a lot** of SetPrinterData
9580 * when connecting to a printer --jerry
9583 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9584 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9585 "change denied by handle access permissions\n"));
9586 return WERR_ACCESS_DENIED;
9589 tmp_ctx = talloc_new(p->mem_ctx);
9594 result = winreg_printer_binding_handle(tmp_ctx,
9595 get_session_info_system(),
9598 if (!W_ERROR_IS_OK(result)) {
9602 result = winreg_get_printer(tmp_ctx, b,
9603 lp_servicename(talloc_tos(), snum),
9605 if (!W_ERROR_IS_OK(result)) {
9609 /* check for OID in valuename */
9611 oid_string = strchr(r->in.value_name, ',');
9617 /* save the registry data */
9619 result = winreg_set_printer_dataex(tmp_ctx, b,
9627 if (W_ERROR_IS_OK(result)) {
9628 /* save the OID if one was specified */
9630 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9631 r->in.key_name, SPOOL_OID_KEY);
9633 result = WERR_NOMEM;
9638 * I'm not checking the status here on purpose. Don't know
9639 * if this is right, but I'm returning the status from the
9640 * previous set_printer_dataex() call. I have no idea if
9641 * this is right. --jerry
9643 winreg_set_printer_dataex(tmp_ctx, b,
9648 (uint8_t *) oid_string,
9649 strlen(oid_string) + 1);
9652 result = winreg_printer_update_changeid(tmp_ctx, b,
9653 lp_const_servicename(snum));
9658 talloc_free(tmp_ctx);
9662 /****************************************************************
9663 _spoolss_DeletePrinterDataEx
9664 ****************************************************************/
9666 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9667 struct spoolss_DeletePrinterDataEx *r)
9669 const char *printer;
9671 WERROR status = WERR_OK;
9672 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9674 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9677 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9678 "Invalid handle (%s:%u:%u).\n",
9679 OUR_HANDLE(r->in.handle)));
9683 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9684 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9685 "printer properties change denied by handle\n"));
9686 return WERR_ACCESS_DENIED;
9689 if (!r->in.value_name || !r->in.key_name) {
9693 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9696 printer = lp_const_servicename(snum);
9698 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9699 get_session_info_system(),
9704 if (W_ERROR_IS_OK(status)) {
9705 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9706 get_session_info_system(),
9714 /****************************************************************
9715 _spoolss_EnumPrinterKey
9716 ****************************************************************/
9718 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9719 struct spoolss_EnumPrinterKey *r)
9722 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9724 WERROR result = WERR_BADFILE;
9725 const char **array = NULL;
9728 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9731 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9732 OUR_HANDLE(r->in.handle)));
9736 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9740 result = winreg_enum_printer_key_internal(p->mem_ctx,
9741 get_session_info_system(),
9743 lp_const_servicename(snum),
9747 if (!W_ERROR_IS_OK(result)) {
9751 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9752 result = WERR_NOMEM;
9756 *r->out._ndr_size = r->in.offered / 2;
9757 *r->out.needed = blob.length;
9759 if (r->in.offered < *r->out.needed) {
9760 result = WERR_MORE_DATA;
9763 r->out.key_buffer->string_array = array;
9767 if (!W_ERROR_IS_OK(result)) {
9769 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9777 /****************************************************************
9778 _spoolss_DeletePrinterKey
9779 ****************************************************************/
9781 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9782 struct spoolss_DeletePrinterKey *r)
9784 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9787 const char *printer;
9788 struct dcerpc_binding_handle *b;
9789 TALLOC_CTX *tmp_ctx;
9791 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9794 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9795 OUR_HANDLE(r->in.handle)));
9799 /* if keyname == NULL, return error */
9800 if ( !r->in.key_name )
9801 return WERR_INVALID_PARAM;
9803 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9807 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9808 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9809 "printer properties change denied by handle\n"));
9810 return WERR_ACCESS_DENIED;
9813 printer = lp_const_servicename(snum);
9815 tmp_ctx = talloc_new(p->mem_ctx);
9820 status = winreg_printer_binding_handle(tmp_ctx,
9821 get_session_info_system(),
9824 if (!W_ERROR_IS_OK(status)) {
9828 /* delete the key and all subkeys */
9829 status = winreg_delete_printer_key(tmp_ctx, b,
9832 if (W_ERROR_IS_OK(status)) {
9833 status = winreg_printer_update_changeid(tmp_ctx, b,
9838 talloc_free(tmp_ctx);
9842 /****************************************************************
9843 _spoolss_EnumPrinterDataEx
9844 ****************************************************************/
9846 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9847 struct spoolss_EnumPrinterDataEx *r)
9850 struct spoolss_PrinterEnumValues *info = NULL;
9851 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9855 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9859 *r->out.info = NULL;
9862 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9863 OUR_HANDLE(r->in.handle)));
9868 * first check for a keyname of NULL or "". Win2k seems to send
9869 * this a lot and we should send back WERR_INVALID_PARAM
9870 * no need to spend time looking up the printer in this case.
9874 if (!strlen(r->in.key_name)) {
9875 result = WERR_INVALID_PARAM;
9879 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9883 /* now look for a match on the key name */
9884 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9885 get_session_info_system(),
9887 lp_const_servicename(snum),
9891 if (!W_ERROR_IS_OK(result)) {
9895 #if 0 /* FIXME - gd */
9896 /* housekeeping information in the reply */
9898 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9899 * the hand marshalled container size is a multiple
9900 * of 4 bytes for RPC alignment.
9904 needed += 4-(needed % 4);
9907 *r->out.count = count;
9908 *r->out.info = info;
9911 if (!W_ERROR_IS_OK(result)) {
9915 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9916 spoolss_EnumPrinterDataEx,
9919 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9920 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9922 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9925 /****************************************************************************
9926 ****************************************************************************/
9928 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9929 const char *servername,
9930 const char *environment,
9931 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9936 werr = compose_spoolss_server_path(mem_ctx,
9939 SPOOLSS_PRTPROCS_PATH,
9941 if (!W_ERROR_IS_OK(werr)) {
9945 DEBUG(4,("print processor directory: [%s]\n", path));
9947 r->directory_name = path;
9952 /****************************************************************
9953 _spoolss_GetPrintProcessorDirectory
9954 ****************************************************************/
9956 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9957 struct spoolss_GetPrintProcessorDirectory *r)
9960 char *prnproc_share = NULL;
9961 bool prnproc_share_exists = false;
9964 /* that's an [in out] buffer */
9966 if (!r->in.buffer && (r->in.offered != 0)) {
9967 return WERR_INVALID_PARAM;
9970 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9975 /* r->in.level is ignored */
9977 /* We always should reply with a local print processor directory so that
9978 * users are not forced to have a [prnproc$] share on the Samba spoolss
9979 * server, if users decide to do so, lets announce it though - Guenther */
9981 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9982 if (!prnproc_share) {
9986 prnproc_share_exists = true;
9989 result = getprintprocessordirectory_level_1(p->mem_ctx,
9990 prnproc_share_exists ? r->in.server : NULL,
9992 &r->out.info->info1);
9993 if (!W_ERROR_IS_OK(result)) {
9994 TALLOC_FREE(r->out.info);
9998 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9999 r->out.info, r->in.level);
10000 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
10002 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
10005 /*******************************************************************
10006 ********************************************************************/
10008 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
10009 const char *dllname)
10011 enum ndr_err_code ndr_err;
10012 struct spoolss_MonitorUi ui;
10014 ui.dll_name = dllname;
10016 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
10017 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
10018 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10019 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
10021 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10024 /*******************************************************************
10025 Streams the monitor UI DLL name in UNICODE
10026 *******************************************************************/
10028 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
10029 struct security_token *token, DATA_BLOB *in,
10030 DATA_BLOB *out, uint32_t *needed)
10032 const char *dllname = "tcpmonui.dll";
10034 *needed = (strlen(dllname)+1) * 2;
10036 if (out->length < *needed) {
10037 return WERR_INSUFFICIENT_BUFFER;
10040 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10047 /*******************************************************************
10048 ********************************************************************/
10050 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
10051 struct spoolss_PortData1 *port1,
10052 const DATA_BLOB *buf)
10054 enum ndr_err_code ndr_err;
10055 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
10056 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
10057 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10058 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
10060 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10063 /*******************************************************************
10064 ********************************************************************/
10066 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
10067 struct spoolss_PortData2 *port2,
10068 const DATA_BLOB *buf)
10070 enum ndr_err_code ndr_err;
10071 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
10072 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
10073 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
10074 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
10076 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
10079 /*******************************************************************
10080 Create a new TCP/IP port
10081 *******************************************************************/
10083 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
10084 struct security_token *token, DATA_BLOB *in,
10085 DATA_BLOB *out, uint32_t *needed)
10087 struct spoolss_PortData1 port1;
10088 struct spoolss_PortData2 port2;
10089 char *device_uri = NULL;
10092 const char *portname;
10093 const char *hostaddress;
10095 uint32_t port_number;
10098 /* peek for spoolss_PortData version */
10100 if (!in || (in->length < (128 + 4))) {
10101 return WERR_GENERAL_FAILURE;
10104 version = IVAL(in->data, 128);
10108 ZERO_STRUCT(port1);
10110 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10114 portname = port1.portname;
10115 hostaddress = port1.hostaddress;
10116 queue = port1.queue;
10117 protocol = port1.protocol;
10118 port_number = port1.port_number;
10122 ZERO_STRUCT(port2);
10124 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10128 portname = port2.portname;
10129 hostaddress = port2.hostaddress;
10130 queue = port2.queue;
10131 protocol = port2.protocol;
10132 port_number = port2.port_number;
10136 DEBUG(1,("xcvtcp_addport: "
10137 "unknown version of port_data: %d\n", version));
10138 return WERR_UNKNOWN_PORT;
10141 /* create the device URI and call the add_port_hook() */
10143 switch (protocol) {
10144 case PROTOCOL_RAWTCP_TYPE:
10145 device_uri = talloc_asprintf(mem_ctx,
10146 "socket://%s:%d/", hostaddress,
10150 case PROTOCOL_LPR_TYPE:
10151 device_uri = talloc_asprintf(mem_ctx,
10152 "lpr://%s/%s", hostaddress, queue );
10156 return WERR_UNKNOWN_PORT;
10163 return add_port_hook(mem_ctx, token, portname, device_uri);
10166 /*******************************************************************
10167 *******************************************************************/
10169 struct xcv_api_table xcvtcp_cmds[] = {
10170 { "MonitorUI", xcvtcp_monitorui },
10171 { "AddPort", xcvtcp_addport},
10175 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10176 struct security_token *token, const char *command,
10183 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10185 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10186 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10187 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10190 return WERR_BADFUNC;
10193 /*******************************************************************
10194 *******************************************************************/
10195 #if 0 /* don't support management using the "Local Port" monitor */
10197 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10198 struct security_token *token, DATA_BLOB *in,
10199 DATA_BLOB *out, uint32_t *needed)
10201 const char *dllname = "localui.dll";
10203 *needed = (strlen(dllname)+1) * 2;
10205 if (out->length < *needed) {
10206 return WERR_INSUFFICIENT_BUFFER;
10209 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10216 /*******************************************************************
10217 *******************************************************************/
10219 struct xcv_api_table xcvlocal_cmds[] = {
10220 { "MonitorUI", xcvlocal_monitorui },
10224 struct xcv_api_table xcvlocal_cmds[] = {
10231 /*******************************************************************
10232 *******************************************************************/
10234 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10235 struct security_token *token, const char *command,
10236 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10241 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10243 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10244 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10245 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10247 return WERR_BADFUNC;
10250 /****************************************************************
10252 ****************************************************************/
10254 WERROR _spoolss_XcvData(struct pipes_struct *p,
10255 struct spoolss_XcvData *r)
10257 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10258 DATA_BLOB out_data = data_blob_null;
10262 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10263 OUR_HANDLE(r->in.handle)));
10264 return WERR_BADFID;
10267 /* Has to be a handle to the TCP/IP port monitor */
10269 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10270 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10271 return WERR_BADFID;
10274 /* requires administrative access to the server */
10276 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10277 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10278 return WERR_ACCESS_DENIED;
10281 /* Allocate the outgoing buffer */
10283 if (r->in.out_data_size) {
10284 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10285 if (out_data.data == NULL) {
10290 switch ( Printer->printer_type ) {
10291 case SPLHND_PORTMON_TCP:
10292 werror = process_xcvtcp_command(p->mem_ctx,
10293 p->session_info->security_token,
10294 r->in.function_name,
10295 &r->in.in_data, &out_data,
10298 case SPLHND_PORTMON_LOCAL:
10299 werror = process_xcvlocal_command(p->mem_ctx,
10300 p->session_info->security_token,
10301 r->in.function_name,
10302 &r->in.in_data, &out_data,
10306 werror = WERR_INVALID_PRINT_MONITOR;
10309 if (!W_ERROR_IS_OK(werror)) {
10313 *r->out.status_code = 0;
10315 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10316 memcpy(r->out.out_data, out_data.data,
10317 MIN(r->in.out_data_size, out_data.length));
10323 /****************************************************************
10324 _spoolss_AddPrintProcessor
10325 ****************************************************************/
10327 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10328 struct spoolss_AddPrintProcessor *r)
10330 /* for now, just indicate success and ignore the add. We'll
10331 automatically set the winprint processor for printer
10332 entries later. Used to debug the LexMark Optra S 1855 PCL
10338 /****************************************************************
10340 ****************************************************************/
10342 WERROR _spoolss_AddPort(struct pipes_struct *p,
10343 struct spoolss_AddPort *r)
10345 /* do what w2k3 does */
10347 return WERR_NOT_SUPPORTED;
10350 /****************************************************************
10351 _spoolss_GetPrinterDriver
10352 ****************************************************************/
10354 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10355 struct spoolss_GetPrinterDriver *r)
10357 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10358 return WERR_NOT_SUPPORTED;
10361 /****************************************************************
10362 _spoolss_ReadPrinter
10363 ****************************************************************/
10365 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10366 struct spoolss_ReadPrinter *r)
10368 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10369 return WERR_NOT_SUPPORTED;
10372 /****************************************************************
10373 _spoolss_WaitForPrinterChange
10374 ****************************************************************/
10376 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10377 struct spoolss_WaitForPrinterChange *r)
10379 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10380 return WERR_NOT_SUPPORTED;
10383 /****************************************************************
10384 _spoolss_ConfigurePort
10385 ****************************************************************/
10387 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10388 struct spoolss_ConfigurePort *r)
10390 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10391 return WERR_NOT_SUPPORTED;
10394 /****************************************************************
10395 _spoolss_DeletePort
10396 ****************************************************************/
10398 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10399 struct spoolss_DeletePort *r)
10401 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10402 return WERR_NOT_SUPPORTED;
10405 /****************************************************************
10406 _spoolss_CreatePrinterIC
10407 ****************************************************************/
10409 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10410 struct spoolss_CreatePrinterIC *r)
10412 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10413 return WERR_NOT_SUPPORTED;
10416 /****************************************************************
10417 _spoolss_PlayGDIScriptOnPrinterIC
10418 ****************************************************************/
10420 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10421 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10423 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10424 return WERR_NOT_SUPPORTED;
10427 /****************************************************************
10428 _spoolss_DeletePrinterIC
10429 ****************************************************************/
10431 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10432 struct spoolss_DeletePrinterIC *r)
10434 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10435 return WERR_NOT_SUPPORTED;
10438 /****************************************************************
10439 _spoolss_AddPrinterConnection
10440 ****************************************************************/
10442 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10443 struct spoolss_AddPrinterConnection *r)
10445 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10446 return WERR_NOT_SUPPORTED;
10449 /****************************************************************
10450 _spoolss_DeletePrinterConnection
10451 ****************************************************************/
10453 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10454 struct spoolss_DeletePrinterConnection *r)
10456 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10457 return WERR_NOT_SUPPORTED;
10460 /****************************************************************
10461 _spoolss_PrinterMessageBox
10462 ****************************************************************/
10464 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10465 struct spoolss_PrinterMessageBox *r)
10467 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10468 return WERR_NOT_SUPPORTED;
10471 /****************************************************************
10472 _spoolss_AddMonitor
10473 ****************************************************************/
10475 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10476 struct spoolss_AddMonitor *r)
10478 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10479 return WERR_NOT_SUPPORTED;
10482 /****************************************************************
10483 _spoolss_DeleteMonitor
10484 ****************************************************************/
10486 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10487 struct spoolss_DeleteMonitor *r)
10489 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10490 return WERR_NOT_SUPPORTED;
10493 /****************************************************************
10494 _spoolss_DeletePrintProcessor
10495 ****************************************************************/
10497 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10498 struct spoolss_DeletePrintProcessor *r)
10500 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10501 return WERR_NOT_SUPPORTED;
10504 /****************************************************************
10505 _spoolss_AddPrintProvidor
10506 ****************************************************************/
10508 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10509 struct spoolss_AddPrintProvidor *r)
10511 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10512 return WERR_NOT_SUPPORTED;
10515 /****************************************************************
10516 _spoolss_DeletePrintProvidor
10517 ****************************************************************/
10519 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10520 struct spoolss_DeletePrintProvidor *r)
10522 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10523 return WERR_NOT_SUPPORTED;
10526 /****************************************************************
10527 _spoolss_FindFirstPrinterChangeNotification
10528 ****************************************************************/
10530 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10531 struct spoolss_FindFirstPrinterChangeNotification *r)
10533 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10534 return WERR_NOT_SUPPORTED;
10537 /****************************************************************
10538 _spoolss_FindNextPrinterChangeNotification
10539 ****************************************************************/
10541 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10542 struct spoolss_FindNextPrinterChangeNotification *r)
10544 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10545 return WERR_NOT_SUPPORTED;
10548 /****************************************************************
10549 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10550 ****************************************************************/
10552 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10553 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10555 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10556 return WERR_NOT_SUPPORTED;
10559 /****************************************************************
10560 _spoolss_ReplyOpenPrinter
10561 ****************************************************************/
10563 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10564 struct spoolss_ReplyOpenPrinter *r)
10566 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10567 return WERR_NOT_SUPPORTED;
10570 /****************************************************************
10571 _spoolss_RouterReplyPrinter
10572 ****************************************************************/
10574 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10575 struct spoolss_RouterReplyPrinter *r)
10577 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10578 return WERR_NOT_SUPPORTED;
10581 /****************************************************************
10582 _spoolss_ReplyClosePrinter
10583 ****************************************************************/
10585 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10586 struct spoolss_ReplyClosePrinter *r)
10588 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10589 return WERR_NOT_SUPPORTED;
10592 /****************************************************************
10594 ****************************************************************/
10596 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10597 struct spoolss_AddPortEx *r)
10599 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10600 return WERR_NOT_SUPPORTED;
10603 /****************************************************************
10604 _spoolss_RouterFindFirstPrinterChangeNotification
10605 ****************************************************************/
10607 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10608 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10610 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10611 return WERR_NOT_SUPPORTED;
10614 /****************************************************************
10615 _spoolss_SpoolerInit
10616 ****************************************************************/
10618 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10619 struct spoolss_SpoolerInit *r)
10621 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10622 return WERR_NOT_SUPPORTED;
10625 /****************************************************************
10626 _spoolss_ResetPrinterEx
10627 ****************************************************************/
10629 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10630 struct spoolss_ResetPrinterEx *r)
10632 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10633 return WERR_NOT_SUPPORTED;
10636 /****************************************************************
10637 _spoolss_RouterReplyPrinterEx
10638 ****************************************************************/
10640 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10641 struct spoolss_RouterReplyPrinterEx *r)
10643 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10644 return WERR_NOT_SUPPORTED;
10647 /****************************************************************
10649 ****************************************************************/
10651 WERROR _spoolss_44(struct pipes_struct *p,
10652 struct spoolss_44 *r)
10654 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10655 return WERR_NOT_SUPPORTED;
10658 /****************************************************************
10660 ****************************************************************/
10662 WERROR _spoolss_SetPort(struct pipes_struct *p,
10663 struct spoolss_SetPort *r)
10665 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10666 return WERR_NOT_SUPPORTED;
10669 /****************************************************************
10671 ****************************************************************/
10673 WERROR _spoolss_4a(struct pipes_struct *p,
10674 struct spoolss_4a *r)
10676 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10677 return WERR_NOT_SUPPORTED;
10680 /****************************************************************
10682 ****************************************************************/
10684 WERROR _spoolss_4b(struct pipes_struct *p,
10685 struct spoolss_4b *r)
10687 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10688 return WERR_NOT_SUPPORTED;
10691 /****************************************************************
10693 ****************************************************************/
10695 WERROR _spoolss_4c(struct pipes_struct *p,
10696 struct spoolss_4c *r)
10698 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10699 return WERR_NOT_SUPPORTED;
10702 /****************************************************************
10704 ****************************************************************/
10706 WERROR _spoolss_53(struct pipes_struct *p,
10707 struct spoolss_53 *r)
10709 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10710 return WERR_NOT_SUPPORTED;
10713 /****************************************************************
10714 _spoolss_AddPerMachineConnection
10715 ****************************************************************/
10717 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10718 struct spoolss_AddPerMachineConnection *r)
10720 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10721 return WERR_NOT_SUPPORTED;
10724 /****************************************************************
10725 _spoolss_DeletePerMachineConnection
10726 ****************************************************************/
10728 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10729 struct spoolss_DeletePerMachineConnection *r)
10731 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10732 return WERR_NOT_SUPPORTED;
10735 /****************************************************************
10736 _spoolss_EnumPerMachineConnections
10737 ****************************************************************/
10739 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10740 struct spoolss_EnumPerMachineConnections *r)
10742 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10743 return WERR_NOT_SUPPORTED;
10746 /****************************************************************
10748 ****************************************************************/
10750 WERROR _spoolss_5a(struct pipes_struct *p,
10751 struct spoolss_5a *r)
10753 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10754 return WERR_NOT_SUPPORTED;
10757 /****************************************************************
10759 ****************************************************************/
10761 WERROR _spoolss_5b(struct pipes_struct *p,
10762 struct spoolss_5b *r)
10764 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10765 return WERR_NOT_SUPPORTED;
10768 /****************************************************************
10770 ****************************************************************/
10772 WERROR _spoolss_5c(struct pipes_struct *p,
10773 struct spoolss_5c *r)
10775 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10776 return WERR_NOT_SUPPORTED;
10779 /****************************************************************
10781 ****************************************************************/
10783 WERROR _spoolss_5d(struct pipes_struct *p,
10784 struct spoolss_5d *r)
10786 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10787 return WERR_NOT_SUPPORTED;
10790 /****************************************************************
10792 ****************************************************************/
10794 WERROR _spoolss_5e(struct pipes_struct *p,
10795 struct spoolss_5e *r)
10797 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10798 return WERR_NOT_SUPPORTED;
10801 /****************************************************************
10803 ****************************************************************/
10805 WERROR _spoolss_5f(struct pipes_struct *p,
10806 struct spoolss_5f *r)
10808 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10809 return WERR_NOT_SUPPORTED;
10812 /****************************************************************
10814 ****************************************************************/
10816 WERROR _spoolss_60(struct pipes_struct *p,
10817 struct spoolss_60 *r)
10819 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10820 return WERR_NOT_SUPPORTED;
10823 /****************************************************************
10825 ****************************************************************/
10827 WERROR _spoolss_61(struct pipes_struct *p,
10828 struct spoolss_61 *r)
10830 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10831 return WERR_NOT_SUPPORTED;
10834 /****************************************************************
10836 ****************************************************************/
10838 WERROR _spoolss_62(struct pipes_struct *p,
10839 struct spoolss_62 *r)
10841 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10842 return WERR_NOT_SUPPORTED;
10845 /****************************************************************
10847 ****************************************************************/
10849 WERROR _spoolss_63(struct pipes_struct *p,
10850 struct spoolss_63 *r)
10852 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10853 return WERR_NOT_SUPPORTED;
10856 /****************************************************************
10858 ****************************************************************/
10860 WERROR _spoolss_64(struct pipes_struct *p,
10861 struct spoolss_64 *r)
10863 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10864 return WERR_NOT_SUPPORTED;
10867 /****************************************************************
10869 ****************************************************************/
10871 WERROR _spoolss_65(struct pipes_struct *p,
10872 struct spoolss_65 *r)
10874 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10875 return WERR_NOT_SUPPORTED;
10878 /****************************************************************
10879 _spoolss_GetCorePrinterDrivers
10880 ****************************************************************/
10882 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10883 struct spoolss_GetCorePrinterDrivers *r)
10885 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10886 return WERR_NOT_SUPPORTED;
10889 /****************************************************************
10891 ****************************************************************/
10893 WERROR _spoolss_67(struct pipes_struct *p,
10894 struct spoolss_67 *r)
10896 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10897 return WERR_NOT_SUPPORTED;
10900 /****************************************************************
10901 _spoolss_GetPrinterDriverPackagePath
10902 ****************************************************************/
10904 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10905 struct spoolss_GetPrinterDriverPackagePath *r)
10907 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10908 return WERR_NOT_SUPPORTED;
10911 /****************************************************************
10913 ****************************************************************/
10915 WERROR _spoolss_69(struct pipes_struct *p,
10916 struct spoolss_69 *r)
10918 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10919 return WERR_NOT_SUPPORTED;
10922 /****************************************************************
10924 ****************************************************************/
10926 WERROR _spoolss_6a(struct pipes_struct *p,
10927 struct spoolss_6a *r)
10929 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10930 return WERR_NOT_SUPPORTED;
10933 /****************************************************************
10935 ****************************************************************/
10937 WERROR _spoolss_6b(struct pipes_struct *p,
10938 struct spoolss_6b *r)
10940 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10941 return WERR_NOT_SUPPORTED;
10944 /****************************************************************
10946 ****************************************************************/
10948 WERROR _spoolss_6c(struct pipes_struct *p,
10949 struct spoolss_6c *r)
10951 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10952 return WERR_NOT_SUPPORTED;
10955 /****************************************************************
10957 ****************************************************************/
10959 WERROR _spoolss_6d(struct pipes_struct *p,
10960 struct spoolss_6d *r)
10962 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10963 return WERR_NOT_SUPPORTED;
10966 /****************************************************************
10967 _spoolss_RpcGetJobNamedPropertyValue
10968 ****************************************************************/
10970 WERROR _spoolss_RpcGetJobNamedPropertyValue(struct pipes_struct *p,
10971 struct spoolss_RpcGetJobNamedPropertyValue *r)
10973 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10974 return WERR_NOT_SUPPORTED;
10977 /****************************************************************
10978 _spoolss_RpcSetJobNamedProperty
10979 ****************************************************************/
10981 WERROR _spoolss_RpcSetJobNamedProperty(struct pipes_struct *p,
10982 struct spoolss_RpcSetJobNamedProperty *r)
10984 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10985 return WERR_NOT_SUPPORTED;
10988 /****************************************************************
10989 _spoolss_RpcDeleteJobNamedProperty
10990 ****************************************************************/
10992 WERROR _spoolss_RpcDeleteJobNamedProperty(struct pipes_struct *p,
10993 struct spoolss_RpcDeleteJobNamedProperty *r)
10995 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
10996 return WERR_NOT_SUPPORTED;
10999 /****************************************************************
11000 _spoolss_RpcEnumJobNamedProperties
11001 ****************************************************************/
11003 WERROR _spoolss_RpcEnumJobNamedProperties(struct pipes_struct *p,
11004 struct spoolss_RpcEnumJobNamedProperties *r)
11006 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
11007 return WERR_NOT_SUPPORTED;