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 "registry/reg_objects.h"
42 #include "include/printing.h"
44 #include "../librpc/gen_ndr/netlogon.h"
46 #include "printing/notify.h"
48 #include "../libcli/registry/util_reg.h"
49 #include "smbd/smbd.h"
50 #include "smbd/globals.h"
53 #include "rpc_server/spoolss/srv_spoolss_nt.h"
55 #include "libsmb/libsmb.h"
56 #include "printing/printer_list.h"
57 #include "../lib/tsocket/tsocket.h"
58 #include "rpc_client/cli_winreg_spoolss.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 struct dcerpc_binding_handle *binding_handle;
142 uint32_t active_connections;
145 static struct notify_back_channel *back_channels;
147 /* Map generic permissions to printer object specific permissions */
149 const struct standard_mapping printer_std_mapping = {
156 /* Map generic permissions to print server object specific permissions */
158 const struct standard_mapping printserver_std_mapping = {
165 /* API table for Xcv Monitor functions */
167 struct xcv_api_table {
169 WERROR(*fn) (TALLOC_CTX *mem_ctx, struct security_token *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
172 static void prune_printername_cache(void);
174 /********************************************************************
175 * Canonicalize servername.
176 ********************************************************************/
178 static const char *canon_servername(const char *servername)
180 const char *pservername = servername;
181 while (*pservername == '\\') {
187 /* translate between internal status numbers and NT status numbers */
188 static int nt_printj_status(int v)
194 return JOB_STATUS_PAUSED;
196 return JOB_STATUS_SPOOLING;
198 return JOB_STATUS_PRINTING;
200 return JOB_STATUS_ERROR;
202 return JOB_STATUS_DELETING;
204 return JOB_STATUS_OFFLINE;
206 return JOB_STATUS_PAPEROUT;
208 return JOB_STATUS_PRINTED;
210 return JOB_STATUS_DELETED;
212 return JOB_STATUS_BLOCKED_DEVQ;
213 case LPQ_USER_INTERVENTION:
214 return JOB_STATUS_USER_INTERVENTION;
219 static int nt_printq_status(int v)
223 return PRINTER_STATUS_PAUSED;
232 /***************************************************************************
233 Disconnect from the client
234 ****************************************************************************/
236 static void srv_spoolss_replycloseprinter(int snum,
237 struct printer_handle *prn_hnd)
243 * Tell the specific printing tdb we no longer want messages for this printer
244 * by deregistering our PID.
247 if (!print_notify_deregister_pid(snum)) {
248 DEBUG(0, ("Failed to register our pid for printer %s\n",
249 lp_const_servicename(snum)));
252 /* weird if the test succeeds !!! */
253 if (prn_hnd->notify.cli_chan == NULL ||
254 prn_hnd->notify.cli_chan->active_connections == 0) {
255 DEBUG(0, ("Trying to close unexisting backchannel!\n"));
256 DLIST_REMOVE(back_channels, prn_hnd->notify.cli_chan);
257 TALLOC_FREE(prn_hnd->notify.cli_chan);
261 status = dcerpc_spoolss_ReplyClosePrinter(
262 prn_hnd->notify.cli_chan->binding_handle,
264 &prn_hnd->notify.cli_hnd,
266 if (!NT_STATUS_IS_OK(status)) {
267 DEBUG(0, ("dcerpc_spoolss_ReplyClosePrinter failed [%s].\n",
269 result = ntstatus_to_werror(status);
270 } else if (!W_ERROR_IS_OK(result)) {
271 DEBUG(0, ("reply_close_printer failed [%s].\n",
272 win_errstr(result)));
275 /* if it's the last connection, deconnect the IPC$ share */
276 if (prn_hnd->notify.cli_chan->active_connections == 1) {
278 prn_hnd->notify.cli_chan->binding_handle = NULL;
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);
288 * Tell the serverid.tdb we're no longer
289 * interested in printer notify messages.
292 serverid_register_msg_flags(
293 messaging_server_id(prn_hnd->notify.msg_ctx),
294 false, FLAG_MSG_PRINT_NOTIFY);
298 if (prn_hnd->notify.cli_chan) {
299 prn_hnd->notify.cli_chan->active_connections--;
303 /****************************************************************************
304 Functions to free a printer entry datastruct.
305 ****************************************************************************/
307 static int printer_entry_destructor(struct printer_handle *Printer)
309 if (Printer->notify.cli_chan != NULL &&
310 Printer->notify.cli_chan->active_connections > 0) {
313 switch(Printer->printer_type) {
315 srv_spoolss_replycloseprinter(snum, Printer);
319 snum = print_queue_snum(Printer->sharename);
321 srv_spoolss_replycloseprinter(snum, Printer);
329 Printer->notify.flags=0;
330 Printer->notify.options=0;
331 Printer->notify.localmachine[0]='\0';
332 Printer->notify.printerlocal=0;
333 TALLOC_FREE(Printer->notify.option);
334 TALLOC_FREE(Printer->devmode);
336 /* Remove from the internal list. */
337 DLIST_REMOVE(printers_list, Printer);
341 /****************************************************************************
342 find printer index by handle
343 ****************************************************************************/
345 static struct printer_handle *find_printer_index_by_hnd(struct pipes_struct *p,
346 struct policy_handle *hnd)
348 struct printer_handle *find_printer = NULL;
350 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
351 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
358 /****************************************************************************
359 Close printer index by handle.
360 ****************************************************************************/
362 static bool close_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
364 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
367 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
372 close_policy_hnd(p, hnd);
377 /****************************************************************************
378 Delete a printer given a handle.
379 ****************************************************************************/
381 static WERROR delete_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
382 const char *sharename,
383 struct messaging_context *msg_ctx)
385 char *cmd = lp_deleteprinter_cmd();
386 char *command = NULL;
388 bool is_print_op = false;
390 /* can't fail if we don't try */
395 command = talloc_asprintf(ctx,
402 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
404 DEBUG(10,("Running [%s]\n", command));
406 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
411 if ( (ret = smbrun(command, NULL)) == 0 ) {
412 /* Tell everyone we updated smb.conf. */
413 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
419 /********** END SePrintOperatorPrivlege BLOCK **********/
421 DEBUGADD(10,("returned [%d]\n", ret));
423 TALLOC_FREE(command);
426 return WERR_BADFID; /* What to return here? */
428 /* go ahead and re-read the services immediately */
430 reload_services(msg_ctx, -1, false);
433 if ( lp_servicenumber( sharename ) >= 0 )
434 return WERR_ACCESS_DENIED;
439 /****************************************************************************
440 Delete a printer given a handle.
441 ****************************************************************************/
443 static WERROR delete_printer_handle(struct pipes_struct *p, struct policy_handle *hnd)
445 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
449 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
455 * It turns out that Windows allows delete printer on a handle
456 * opened by an admin user, then used on a pipe handle created
457 * by an anonymous user..... but they're working on security.... riiight !
461 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
462 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
463 return WERR_ACCESS_DENIED;
466 /* this does not need a become root since the access check has been
467 done on the handle already */
469 result = winreg_delete_printer_key_internal(p->mem_ctx,
470 get_session_info_system(),
474 if (!W_ERROR_IS_OK(result)) {
475 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
479 result = delete_printer_hook(p->mem_ctx, p->session_info->security_token,
480 Printer->sharename, p->msg_ctx);
481 if (!W_ERROR_IS_OK(result)) {
484 prune_printername_cache();
488 /****************************************************************************
489 Return the snum of a printer corresponding to an handle.
490 ****************************************************************************/
492 static bool get_printer_snum(struct pipes_struct *p, struct policy_handle *hnd,
493 int *number, struct share_params **params)
495 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
498 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
503 switch (Printer->printer_type) {
505 DEBUG(4,("short name:%s\n", Printer->sharename));
506 *number = print_queue_snum(Printer->sharename);
507 return (*number != -1);
515 /****************************************************************************
516 Set printer handle type.
517 Check if it's \\server or \\server\printer
518 ****************************************************************************/
520 static bool set_printer_hnd_printertype(struct printer_handle *Printer, const char *handlename)
522 DEBUG(3,("Setting printer type=%s\n", handlename));
524 /* it's a print server */
525 if (handlename && *handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
526 DEBUGADD(4,("Printer is a print server\n"));
527 Printer->printer_type = SPLHND_SERVER;
529 /* it's a printer (set_printer_hnd_name() will handle port monitors */
531 DEBUGADD(4,("Printer is a printer\n"));
532 Printer->printer_type = SPLHND_PRINTER;
538 static void prune_printername_cache_fn(const char *key, const char *value,
539 time_t timeout, void *private_data)
544 static void prune_printername_cache(void)
546 gencache_iterate(prune_printername_cache_fn, NULL, "PRINTERNAME/*");
549 /****************************************************************************
550 Set printer handle name.. Accept names like \\server, \\server\printer,
551 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
552 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
553 XcvDataPort() interface.
554 ****************************************************************************/
556 static WERROR set_printer_hnd_name(TALLOC_CTX *mem_ctx,
557 const struct auth_session_info *session_info,
558 struct messaging_context *msg_ctx,
559 struct printer_handle *Printer,
560 const char *handlename)
563 int n_services=lp_numservices();
565 const char *printername;
566 const char *servername = NULL;
569 struct spoolss_PrinterInfo2 *info2 = NULL;
574 * Hopefully nobody names his printers like this. Maybe \ or ,
575 * are illegal in printer names even?
577 const char printer_not_found[] = "Printer \\, !@#$%^&*( not found";
581 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
582 (unsigned long)strlen(handlename)));
584 aprinter = discard_const_p(char, handlename);
585 if ( *handlename == '\\' ) {
586 servername = canon_servername(handlename);
587 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
591 if (!is_myname_or_ipaddr(servername)) {
592 return WERR_INVALID_PRINTER_NAME;
594 Printer->servername = talloc_asprintf(Printer, "\\\\%s", servername);
595 if (Printer->servername == NULL) {
600 if (Printer->printer_type == SPLHND_SERVER) {
604 if (Printer->printer_type != SPLHND_PRINTER) {
605 return WERR_INVALID_HANDLE;
608 DEBUGADD(5, ("searching for [%s]\n", aprinter));
610 p = strchr(aprinter, ',');
617 if (strncmp(p, "DrvConvert", strlen("DrvConvert")) == 0) {
619 } else if (strncmp(p, "LocalOnly", strlen("LocalOnly")) == 0) {
625 DEBUGADD(5, ("stripped handlename: [%s]\n", aprinter));
628 /* check for the Port Monitor Interface */
629 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
630 Printer->printer_type = SPLHND_PORTMON_TCP;
631 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
634 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
635 Printer->printer_type = SPLHND_PORTMON_LOCAL;
636 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
641 * With hundreds of printers, the "for" loop iterating all
642 * shares can be quite expensive, as it is done on every
643 * OpenPrinter. The loop maps "aprinter" to "sname", the
644 * result of which we cache in gencache.
647 cache_key = talloc_asprintf(talloc_tos(), "PRINTERNAME/%s",
649 if ((cache_key != NULL) && gencache_get(cache_key, &tmp, NULL)) {
651 found = (strcmp(tmp, printer_not_found) != 0);
653 DEBUG(4, ("Printer %s not found\n", aprinter));
655 return WERR_INVALID_PRINTER_NAME;
661 /* Search all sharenames first as this is easier than pulling
662 the printer_info_2 off of disk. Don't use find_service() since
663 that calls out to map_username() */
665 /* do another loop to look for printernames */
666 for (snum = 0; !found && snum < n_services; snum++) {
667 const char *printer = lp_const_servicename(snum);
669 /* no point going on if this is not a printer */
670 if (!(lp_snum_ok(snum) && lp_print_ok(snum))) {
674 /* ignore [printers] share */
675 if (strequal(printer, "printers")) {
679 fstrcpy(sname, printer);
680 if (strequal(aprinter, printer)) {
685 /* no point looking up the printer object if
686 we aren't allowing printername != sharename */
687 if (lp_force_printername(snum)) {
691 result = winreg_get_printer_internal(mem_ctx,
696 if ( !W_ERROR_IS_OK(result) ) {
697 DEBUG(2,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
698 sname, win_errstr(result)));
702 printername = strrchr(info2->printername, '\\');
703 if (printername == NULL) {
704 printername = info2->printername;
709 if (strequal(printername, aprinter)) {
714 DEBUGADD(10, ("printername: %s\n", printername));
720 if (cache_key != NULL) {
721 gencache_set(cache_key, printer_not_found,
723 TALLOC_FREE(cache_key);
725 DEBUGADD(4,("Printer not found\n"));
726 return WERR_INVALID_PRINTER_NAME;
729 if (cache_key != NULL) {
730 gencache_set(cache_key, sname, time(NULL)+300);
731 TALLOC_FREE(cache_key);
734 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
736 strlcpy(Printer->sharename, sname, sizeof(Printer->sharename));
741 /****************************************************************************
742 Find first available printer slot. creates a printer handle for you.
743 ****************************************************************************/
745 static WERROR open_printer_hnd(struct pipes_struct *p,
746 struct policy_handle *hnd,
748 uint32_t access_granted)
750 struct printer_handle *new_printer;
753 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
755 new_printer = talloc_zero(p->mem_ctx, struct printer_handle);
756 if (new_printer == NULL) {
759 talloc_set_destructor(new_printer, printer_entry_destructor);
761 /* This also steals the printer_handle on the policy_handle */
762 if (!create_policy_hnd(p, hnd, new_printer)) {
763 TALLOC_FREE(new_printer);
764 return WERR_INVALID_HANDLE;
767 /* Add to the internal list. */
768 DLIST_ADD(printers_list, new_printer);
770 new_printer->notify.option=NULL;
772 if (!set_printer_hnd_printertype(new_printer, name)) {
773 close_printer_handle(p, hnd);
774 return WERR_INVALID_HANDLE;
777 result = set_printer_hnd_name(p->mem_ctx,
778 get_session_info_system(),
781 if (!W_ERROR_IS_OK(result)) {
782 close_printer_handle(p, hnd);
786 new_printer->access_granted = access_granted;
788 DEBUG(5, ("%d printer handles active\n",
789 (int)num_pipe_handles(p)));
794 /***************************************************************************
795 check to see if the client motify handle is monitoring the notification
796 given by (notify_type, notify_field).
797 **************************************************************************/
799 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
800 uint16_t notify_field)
805 static bool is_monitoring_event(struct printer_handle *p, uint16_t notify_type,
806 uint16_t notify_field)
808 struct spoolss_NotifyOption *option = p->notify.option;
812 * Flags should always be zero when the change notify
813 * is registered by the client's spooler. A user Win32 app
814 * might use the flags though instead of the NOTIFY_OPTION_INFO
823 return is_monitoring_event_flags(
824 p->notify.flags, notify_type, notify_field);
826 for (i = 0; i < option->count; i++) {
828 /* Check match for notify_type */
830 if (option->types[i].type != notify_type)
833 /* Check match for field */
835 for (j = 0; j < option->types[i].count; j++) {
836 if (option->types[i].fields[j].field == notify_field) {
842 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
843 p->servername, p->sharename, notify_type, notify_field));
848 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
849 _data->data.integer[0] = _integer; \
850 _data->data.integer[1] = 0;
853 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
854 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
855 if (!_data->data.string.string) {\
856 _data->data.string.size = 0; \
858 _data->data.string.size = strlen_m_term(_p) * 2;
860 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
861 _data->data.devmode.devmode = _devmode;
863 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _sd) \
864 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
865 if (!_data->data.sd.sd) { \
866 _data->data.sd.sd_size = 0; \
868 _data->data.sd.sd_size = \
869 ndr_size_security_descriptor(_data->data.sd.sd, 0);
871 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
876 struct spoolss_Time st;
880 if (!init_systemtime(&st, t)) {
884 p = talloc_array(mem_ctx, char, len);
890 * Systemtime must be linearized as a set of UINT16's.
891 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
894 SSVAL(p, 0, st.year);
895 SSVAL(p, 2, st.month);
896 SSVAL(p, 4, st.day_of_week);
898 SSVAL(p, 8, st.hour);
899 SSVAL(p, 10, st.minute);
900 SSVAL(p, 12, st.second);
901 SSVAL(p, 14, st.millisecond);
907 /* Convert a notification message to a struct spoolss_Notify */
909 static void notify_one_value(struct spoolss_notify_msg *msg,
910 struct spoolss_Notify *data,
913 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
916 static void notify_string(struct spoolss_notify_msg *msg,
917 struct spoolss_Notify *data,
920 /* The length of the message includes the trailing \0 */
922 data->data.string.size = msg->len * 2;
923 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
924 if (!data->data.string.string) {
925 data->data.string.size = 0;
930 static void notify_system_time(struct spoolss_notify_msg *msg,
931 struct spoolss_Notify *data,
934 data->data.string.string = NULL;
935 data->data.string.size = 0;
937 if (msg->len != sizeof(time_t)) {
938 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
943 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
944 &data->data.string.string,
945 &data->data.string.size);
948 struct notify2_message_table {
950 void (*fn)(struct spoolss_notify_msg *msg,
951 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
954 static struct notify2_message_table printer_notify_table[] = {
955 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
956 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
957 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
958 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
959 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
960 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
961 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
962 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
963 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
964 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
965 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
966 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
967 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
968 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
969 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
970 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
971 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
972 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
973 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
976 static struct notify2_message_table job_notify_table[] = {
977 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
978 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
979 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
980 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
981 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
982 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
983 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
984 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
985 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
986 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
987 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
988 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
989 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
990 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
991 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
992 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
993 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
994 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
995 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
996 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
997 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
998 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
999 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
1000 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
1004 /***********************************************************************
1005 Allocate talloc context for container object
1006 **********************************************************************/
1008 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1013 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
1018 /***********************************************************************
1019 release all allocated memory and zero out structure
1020 **********************************************************************/
1022 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1028 talloc_destroy(ctr->ctx);
1035 /***********************************************************************
1036 **********************************************************************/
1038 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1046 /***********************************************************************
1047 **********************************************************************/
1049 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1051 if ( !ctr || !ctr->msg_groups )
1054 if ( idx >= ctr->num_groups )
1057 return &ctr->msg_groups[idx];
1061 /***********************************************************************
1062 How many groups of change messages do we have ?
1063 **********************************************************************/
1065 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
1070 return ctr->num_groups;
1073 /***********************************************************************
1074 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
1075 **********************************************************************/
1077 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
1079 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
1080 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
1081 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
1087 /* loop over all groups looking for a matching printer name */
1089 for ( i=0; i<ctr->num_groups; i++ ) {
1090 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
1094 /* add a new group? */
1096 if ( i == ctr->num_groups ) {
1099 if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
1100 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
1103 ctr->msg_groups = groups;
1105 /* clear the new entry and set the printer name */
1107 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
1108 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
1111 /* add the change messages; 'i' is the correct index now regardless */
1113 msg_grp = &ctr->msg_groups[i];
1115 msg_grp->num_msgs++;
1117 if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
1118 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
1121 msg_grp->msgs = msg_list;
1123 new_slot = msg_grp->num_msgs-1;
1124 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
1126 /* need to allocate own copy of data */
1128 if ( msg->len != 0 )
1129 msg_grp->msgs[new_slot].notify.data = (char *)
1130 talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
1132 return ctr->num_groups;
1135 static void construct_info_data(struct spoolss_Notify *info_data,
1136 enum spoolss_NotifyType type,
1137 uint16_t field, int id);
1139 /***********************************************************************
1140 Send a change notication message on all handles which have a call
1142 **********************************************************************/
1144 static int build_notify2_messages(TALLOC_CTX *mem_ctx,
1145 struct printer_handle *prn_hnd,
1146 SPOOLSS_NOTIFY_MSG *messages,
1148 struct spoolss_Notify **_notifies,
1151 struct spoolss_Notify *notifies;
1152 SPOOLSS_NOTIFY_MSG *msg;
1157 notifies = talloc_zero_array(mem_ctx,
1158 struct spoolss_Notify, num_msgs);
1163 for (i = 0; i < num_msgs; i++) {
1167 /* Are we monitoring this event? */
1169 if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) {
1173 DEBUG(10, ("Sending message type [0x%x] field [0x%2x] "
1174 "for printer [%s]\n",
1175 msg->type, msg->field, prn_hnd->sharename));
1178 * if the is a printer notification handle and not a job
1179 * notification type, then set the id to 0.
1180 * Otherwise just use what was specified in the message.
1182 * When registering change notification on a print server
1183 * handle we always need to send back the id (snum) matching
1184 * the printer for which the change took place.
1185 * For change notify registered on a printer handle,
1186 * this does not matter and the id should be 0.
1191 if ((msg->type == PRINTER_NOTIFY_TYPE) &&
1192 (prn_hnd->printer_type == SPLHND_PRINTER)) {
1198 /* Convert unix jobid to smb jobid */
1200 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1201 id = sysjob_to_jobid(msg->id);
1204 DEBUG(3, ("no such unix jobid %d\n",
1210 construct_info_data(¬ifies[count],
1211 msg->type, msg->field, id);
1214 case PRINTER_NOTIFY_TYPE:
1215 if (printer_notify_table[msg->field].fn) {
1216 printer_notify_table[msg->field].fn(msg,
1217 ¬ifies[count], mem_ctx);
1221 case JOB_NOTIFY_TYPE:
1222 if (job_notify_table[msg->field].fn) {
1223 job_notify_table[msg->field].fn(msg,
1224 ¬ifies[count], mem_ctx);
1229 DEBUG(5, ("Unknown notification type %d\n",
1237 *_notifies = notifies;
1243 static int send_notify2_printer(TALLOC_CTX *mem_ctx,
1244 struct printer_handle *prn_hnd,
1245 SPOOLSS_NOTIFY_MSG_GROUP *msg_group)
1247 struct spoolss_Notify *notifies;
1249 union spoolss_ReplyPrinterInfo info;
1250 struct spoolss_NotifyInfo info0;
1251 uint32_t reply_result;
1256 /* Is there notification on this handle? */
1257 if (prn_hnd->notify.cli_chan == NULL ||
1258 prn_hnd->notify.cli_chan->active_connections == 0) {
1262 DEBUG(10, ("Client connected! [\\\\%s\\%s]\n",
1263 prn_hnd->servername, prn_hnd->sharename));
1265 /* For this printer? Print servers always receive notifications. */
1266 if ((prn_hnd->printer_type == SPLHND_PRINTER) &&
1267 (!strequal(msg_group->printername, prn_hnd->sharename))) {
1271 DEBUG(10,("Our printer\n"));
1273 /* build the array of change notifications */
1274 ret = build_notify2_messages(mem_ctx, prn_hnd,
1276 msg_group->num_msgs,
1282 info0.version = 0x2;
1283 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1284 info0.count = count;
1285 info0.notifies = notifies;
1287 info.info0 = &info0;
1289 status = dcerpc_spoolss_RouterReplyPrinterEx(
1290 prn_hnd->notify.cli_chan->binding_handle,
1292 &prn_hnd->notify.cli_hnd,
1293 prn_hnd->notify.change, /* color */
1294 prn_hnd->notify.flags,
1296 0, /* reply_type, must be 0 */
1298 if (!NT_STATUS_IS_OK(status)) {
1299 DEBUG(1, ("dcerpc_spoolss_RouterReplyPrinterEx to client: %s "
1301 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1302 nt_errstr(status)));
1303 werr = ntstatus_to_werror(status);
1304 } else if (!W_ERROR_IS_OK(werr)) {
1305 DEBUG(1, ("RouterReplyPrinterEx to client: %s "
1307 prn_hnd->notify.cli_chan->cli_pipe->srv_name_slash,
1310 switch (reply_result) {
1313 case PRINTER_NOTIFY_INFO_DISCARDED:
1314 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1315 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1324 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
1326 struct printer_handle *p;
1327 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
1328 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
1332 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
1336 if (!msg_group->msgs) {
1337 DEBUG(5, ("send_notify2_changes() called with no messages!\n"));
1341 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
1343 /* loop over all printers */
1345 for (p = printers_list; p; p = p->next) {
1346 ret = send_notify2_printer(mem_ctx, p, msg_group);
1353 DEBUG(8,("send_notify2_changes: Exit...\n"));
1357 /***********************************************************************
1358 **********************************************************************/
1360 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1363 uint32_t tv_sec, tv_usec;
1366 /* Unpack message */
1368 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1371 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1373 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1376 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1377 &msg->notify.value[0], &msg->notify.value[1]);
1379 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1380 &msg->len, &msg->notify.data);
1382 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1383 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1385 tv->tv_sec = tv_sec;
1386 tv->tv_usec = tv_usec;
1389 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1390 msg->notify.value[1]));
1392 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1397 /********************************************************************
1398 Receive a notify2 message list
1399 ********************************************************************/
1401 static void receive_notify2_message_list(struct messaging_context *msg,
1404 struct server_id server_id,
1407 size_t msg_count, i;
1408 char *buf = (char *)data->data;
1411 SPOOLSS_NOTIFY_MSG notify;
1412 SPOOLSS_NOTIFY_MSG_CTR messages;
1415 if (data->length < 4) {
1416 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1420 msg_count = IVAL(buf, 0);
1423 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1425 if (msg_count == 0) {
1426 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1430 /* initialize the container */
1432 ZERO_STRUCT( messages );
1433 notify_msg_ctr_init( &messages );
1436 * build message groups for each printer identified
1437 * in a change_notify msg. Remember that a PCN message
1438 * includes the handle returned for the srv_spoolss_replyopenprinter()
1439 * call. Therefore messages are grouped according to printer handle.
1442 for ( i=0; i<msg_count; i++ ) {
1443 struct timeval msg_tv;
1445 if (msg_ptr + 4 - buf > data->length) {
1446 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1450 msg_len = IVAL(msg_ptr,0);
1453 if (msg_ptr + msg_len - buf > data->length) {
1454 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1458 /* unpack messages */
1460 ZERO_STRUCT( notify );
1461 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1464 /* add to correct list in container */
1466 notify_msg_ctr_addmsg( &messages, ¬ify );
1468 /* free memory that might have been allocated by notify2_unpack_msg() */
1470 if ( notify.len != 0 )
1471 SAFE_FREE( notify.notify.data );
1474 /* process each group of messages */
1476 num_groups = notify_msg_ctr_numgroups( &messages );
1477 for ( i=0; i<num_groups; i++ )
1478 send_notify2_changes( &messages, i );
1483 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1484 (uint32_t)msg_count ));
1486 notify_msg_ctr_destroy( &messages );
1491 /********************************************************************
1492 Send a message to ourself about new driver being installed
1493 so we can upgrade the information for each printer bound to this
1495 ********************************************************************/
1497 static bool srv_spoolss_drv_upgrade_printer(const char *drivername,
1498 struct messaging_context *msg_ctx)
1500 int len = strlen(drivername);
1505 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1508 messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
1509 MSG_PRINTER_DRVUPGRADE,
1510 (const uint8_t *)drivername, len+1);
1515 void srv_spoolss_cleanup(void)
1517 struct printer_session_counter *session_counter;
1519 for (session_counter = counter_list;
1520 session_counter != NULL;
1521 session_counter = counter_list) {
1522 DLIST_REMOVE(counter_list, session_counter);
1523 TALLOC_FREE(session_counter);
1527 /**********************************************************************
1528 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1529 over all printers, upgrading ones as necessary
1530 **********************************************************************/
1532 void do_drv_upgrade_printer(struct messaging_context *msg,
1535 struct server_id server_id,
1538 TALLOC_CTX *tmp_ctx;
1539 const struct auth_session_info *session_info = get_session_info_system();
1540 struct spoolss_PrinterInfo2 *pinfo2;
1542 const char *drivername;
1544 int n_services = lp_numservices();
1545 struct dcerpc_binding_handle *b = NULL;
1547 tmp_ctx = talloc_new(NULL);
1548 if (!tmp_ctx) return;
1550 drivername = talloc_strndup(tmp_ctx, (const char *)data->data, data->length);
1552 DEBUG(0, ("do_drv_upgrade_printer: Out of memoery ?!\n"));
1556 DEBUG(10, ("do_drv_upgrade_printer: "
1557 "Got message for new driver [%s]\n", drivername));
1559 /* Iterate the printer list */
1561 for (snum = 0; snum < n_services; snum++) {
1562 if (!lp_snum_ok(snum) || !lp_print_ok(snum)) {
1566 /* ignore [printers] share */
1567 if (strequal(lp_const_servicename(snum), "printers")) {
1572 result = winreg_printer_binding_handle(tmp_ctx,
1576 if (!W_ERROR_IS_OK(result)) {
1581 result = winreg_get_printer(tmp_ctx, b,
1582 lp_const_servicename(snum),
1585 if (!W_ERROR_IS_OK(result)) {
1589 if (!pinfo2->drivername) {
1593 if (strcmp(drivername, pinfo2->drivername) != 0) {
1597 DEBUG(6,("Updating printer [%s]\n", pinfo2->printername));
1599 /* all we care about currently is the change_id */
1600 result = winreg_printer_update_changeid(tmp_ctx, b,
1601 pinfo2->printername);
1603 if (!W_ERROR_IS_OK(result)) {
1604 DEBUG(3, ("do_drv_upgrade_printer: "
1605 "Failed to update changeid [%s]\n",
1606 win_errstr(result)));
1612 talloc_free(tmp_ctx);
1615 /********************************************************************
1616 Update the cache for all printq's with a registered client
1618 ********************************************************************/
1620 void update_monitored_printq_cache(struct messaging_context *msg_ctx)
1622 struct printer_handle *printer = printers_list;
1625 /* loop through all printers and update the cache where
1626 a client is connected */
1628 if ((printer->printer_type == SPLHND_PRINTER) &&
1629 ((printer->notify.cli_chan != NULL) &&
1630 (printer->notify.cli_chan->active_connections > 0))) {
1631 snum = print_queue_snum(printer->sharename);
1632 print_queue_status(msg_ctx, snum, NULL, NULL);
1635 printer = printer->next;
1641 /****************************************************************
1642 _spoolss_OpenPrinter
1643 ****************************************************************/
1645 WERROR _spoolss_OpenPrinter(struct pipes_struct *p,
1646 struct spoolss_OpenPrinter *r)
1648 struct spoolss_OpenPrinterEx e;
1651 ZERO_STRUCT(e.in.userlevel);
1653 e.in.printername = r->in.printername;
1654 e.in.datatype = r->in.datatype;
1655 e.in.devmode_ctr = r->in.devmode_ctr;
1656 e.in.access_mask = r->in.access_mask;
1659 e.out.handle = r->out.handle;
1661 werr = _spoolss_OpenPrinterEx(p, &e);
1663 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1664 /* OpenPrinterEx returns this for a bad
1665 * printer name. We must return WERR_INVALID_PRINTER_NAME
1668 werr = WERR_INVALID_PRINTER_NAME;
1674 static WERROR copy_devicemode(TALLOC_CTX *mem_ctx,
1675 struct spoolss_DeviceMode *orig,
1676 struct spoolss_DeviceMode **dest)
1678 struct spoolss_DeviceMode *dm;
1680 dm = talloc(mem_ctx, struct spoolss_DeviceMode);
1685 /* copy all values, then duplicate strings and structs */
1688 dm->devicename = talloc_strdup(dm, orig->devicename);
1689 if (!dm->devicename) {
1692 dm->formname = talloc_strdup(dm, orig->formname);
1693 if (!dm->formname) {
1696 if (orig->driverextra_data.data) {
1697 dm->driverextra_data.data =
1698 (uint8_t *) talloc_memdup(dm, orig->driverextra_data.data,
1699 orig->driverextra_data.length);
1700 if (!dm->driverextra_data.data) {
1709 /****************************************************************
1710 _spoolss_OpenPrinterEx
1711 ****************************************************************/
1713 WERROR _spoolss_OpenPrinterEx(struct pipes_struct *p,
1714 struct spoolss_OpenPrinterEx *r)
1719 struct printer_handle *Printer=NULL;
1723 if (!r->in.printername) {
1724 return WERR_INVALID_PARAM;
1727 if (r->in.level > 3) {
1728 return WERR_INVALID_PARAM;
1730 if ((r->in.level == 1 && !r->in.userlevel.level1) ||
1731 (r->in.level == 2 && !r->in.userlevel.level2) ||
1732 (r->in.level == 3 && !r->in.userlevel.level3)) {
1733 return WERR_INVALID_PARAM;
1736 /* some sanity check because you can open a printer or a print server */
1737 /* aka: \\server\printer or \\server */
1739 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1741 result = open_printer_hnd(p, r->out.handle, r->in.printername, 0);
1742 if (!W_ERROR_IS_OK(result)) {
1743 DEBUG(0,("_spoolss_OpenPrinterEx: Cannot open a printer handle "
1744 "for printer %s\n", r->in.printername));
1745 ZERO_STRUCTP(r->out.handle);
1749 Printer = find_printer_index_by_hnd(p, r->out.handle);
1751 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1752 "handle we created for printer %s\n", r->in.printername));
1753 close_printer_handle(p, r->out.handle);
1754 ZERO_STRUCTP(r->out.handle);
1755 return WERR_INVALID_PARAM;
1759 * First case: the user is opening the print server:
1761 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1762 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1764 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1765 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1766 * or if the user is listed in the smb.conf printer admin parameter.
1768 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1769 * client view printer folder, but does not show the MSAPW.
1771 * Note: this test needs code to check access rights here too. Jeremy
1772 * could you look at this?
1774 * Second case: the user is opening a printer:
1775 * NT doesn't let us connect to a printer if the connecting user
1776 * doesn't have print permission.
1778 * Third case: user is opening a Port Monitor
1779 * access checks same as opening a handle to the print server.
1782 switch (Printer->printer_type )
1785 case SPLHND_PORTMON_TCP:
1786 case SPLHND_PORTMON_LOCAL:
1787 /* Printserver handles use global struct... */
1791 /* Map standard access rights to object specific access rights */
1793 se_map_standard(&r->in.access_mask,
1794 &printserver_std_mapping);
1796 /* Deny any object specific bits that don't apply to print
1797 servers (i.e printer and job specific bits) */
1799 r->in.access_mask &= SEC_MASK_SPECIFIC;
1801 if (r->in.access_mask &
1802 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1803 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1804 close_printer_handle(p, r->out.handle);
1805 ZERO_STRUCTP(r->out.handle);
1806 return WERR_ACCESS_DENIED;
1809 /* Allow admin access */
1811 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1813 if (!lp_ms_add_printer_wizard()) {
1814 close_printer_handle(p, r->out.handle);
1815 ZERO_STRUCTP(r->out.handle);
1816 return WERR_ACCESS_DENIED;
1819 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1820 and not a printer admin, then fail */
1822 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
1823 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
1824 !nt_token_check_sid(&global_sid_Builtin_Print_Operators, p->session_info->security_token) &&
1825 !token_contains_name_in_list(
1826 uidtoname(p->session_info->unix_token->uid),
1827 p->session_info->info->domain_name,
1829 p->session_info->security_token,
1830 lp_printer_admin(snum))) {
1831 close_printer_handle(p, r->out.handle);
1832 ZERO_STRUCTP(r->out.handle);
1833 DEBUG(3,("access DENIED as user is not root, "
1834 "has no printoperator privilege, "
1835 "not a member of the printoperator builtin group and "
1836 "is not in printer admin list"));
1837 return WERR_ACCESS_DENIED;
1840 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1844 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1847 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1848 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1850 /* We fall through to return WERR_OK */
1853 case SPLHND_PRINTER:
1854 /* NT doesn't let us connect to a printer if the connecting user
1855 doesn't have print permission. */
1857 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1858 close_printer_handle(p, r->out.handle);
1859 ZERO_STRUCTP(r->out.handle);
1863 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1864 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1867 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1869 /* map an empty access mask to the minimum access mask */
1870 if (r->in.access_mask == 0x0)
1871 r->in.access_mask = PRINTER_ACCESS_USE;
1874 * If we are not serving the printer driver for this printer,
1875 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1876 * will keep NT clients happy --jerry
1879 if (lp_use_client_driver(snum)
1880 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1882 r->in.access_mask = PRINTER_ACCESS_USE;
1885 /* check smb.conf parameters and the the sec_desc */
1886 raddr = tsocket_address_inet_addr_string(p->remote_address,
1888 if (raddr == NULL) {
1892 rc = get_remote_hostname(p->remote_address,
1898 if (strequal(rhost, "UNKNOWN")) {
1902 if (!allow_access(lp_hostsdeny(snum), lp_hostsallow(snum),
1904 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1905 ZERO_STRUCTP(r->out.handle);
1906 return WERR_ACCESS_DENIED;
1909 if (!user_ok_token(uidtoname(p->session_info->unix_token->uid), NULL,
1910 p->session_info->security_token, snum) ||
1911 !print_access_check(p->session_info,
1914 r->in.access_mask)) {
1915 DEBUG(3, ("access DENIED for printer open\n"));
1916 close_printer_handle(p, r->out.handle);
1917 ZERO_STRUCTP(r->out.handle);
1918 return WERR_ACCESS_DENIED;
1921 if ((r->in.access_mask & SEC_MASK_SPECIFIC)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1922 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1923 close_printer_handle(p, r->out.handle);
1924 ZERO_STRUCTP(r->out.handle);
1925 return WERR_ACCESS_DENIED;
1928 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1929 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1931 r->in.access_mask = PRINTER_ACCESS_USE;
1933 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1934 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1936 winreg_create_printer_internal(p->mem_ctx,
1937 get_session_info_system(),
1939 lp_const_servicename(snum));
1944 /* sanity check to prevent programmer error */
1945 ZERO_STRUCTP(r->out.handle);
1949 Printer->access_granted = r->in.access_mask;
1952 * If the client sent a devmode in the OpenPrinter() call, then
1953 * save it here in case we get a job submission on this handle
1956 if ((Printer->printer_type != SPLHND_SERVER) &&
1957 r->in.devmode_ctr.devmode) {
1958 copy_devicemode(NULL, r->in.devmode_ctr.devmode,
1962 #if 0 /* JERRY -- I'm doubtful this is really effective */
1963 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1964 optimization in Windows 2000 clients --jerry */
1966 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1967 && (RA_WIN2K == get_remote_arch()) )
1969 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1970 sys_usleep( 500000 );
1977 /****************************************************************
1978 _spoolss_ClosePrinter
1979 ****************************************************************/
1981 WERROR _spoolss_ClosePrinter(struct pipes_struct *p,
1982 struct spoolss_ClosePrinter *r)
1984 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
1986 if (Printer && Printer->document_started) {
1987 struct spoolss_EndDocPrinter e;
1989 e.in.handle = r->in.handle;
1991 _spoolss_EndDocPrinter(p, &e);
1994 if (!close_printer_handle(p, r->in.handle))
1997 /* clear the returned printer handle. Observed behavior
1998 from Win2k server. Don't think this really matters.
1999 Previous code just copied the value of the closed
2002 ZERO_STRUCTP(r->out.handle);
2007 /****************************************************************
2008 _spoolss_DeletePrinter
2009 ****************************************************************/
2011 WERROR _spoolss_DeletePrinter(struct pipes_struct *p,
2012 struct spoolss_DeletePrinter *r)
2014 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2018 if (Printer && Printer->document_started) {
2019 struct spoolss_EndDocPrinter e;
2021 e.in.handle = r->in.handle;
2023 _spoolss_EndDocPrinter(p, &e);
2026 if (get_printer_snum(p, r->in.handle, &snum, NULL)) {
2027 winreg_delete_printer_key_internal(p->mem_ctx,
2028 get_session_info_system(),
2030 lp_const_servicename(snum),
2034 result = delete_printer_handle(p, r->in.handle);
2039 /*******************************************************************
2040 * static function to lookup the version id corresponding to an
2041 * long architecture string
2042 ******************************************************************/
2044 static const struct print_architecture_table_node archi_table[]= {
2046 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
2047 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
2048 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
2049 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
2050 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
2051 {"Windows IA64", SPL_ARCH_IA64, 3 },
2052 {"Windows x64", SPL_ARCH_X64, 3 },
2056 static int get_version_id(const char *arch)
2060 for (i=0; archi_table[i].long_archi != NULL; i++)
2062 if (strcmp(arch, archi_table[i].long_archi) == 0)
2063 return (archi_table[i].version);
2069 /****************************************************************
2070 _spoolss_DeletePrinterDriver
2071 ****************************************************************/
2073 WERROR _spoolss_DeletePrinterDriver(struct pipes_struct *p,
2074 struct spoolss_DeletePrinterDriver *r)
2077 struct spoolss_DriverInfo8 *info = NULL;
2078 struct spoolss_DriverInfo8 *info_win2k = NULL;
2081 struct dcerpc_binding_handle *b;
2082 TALLOC_CTX *tmp_ctx = NULL;
2084 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2085 and not a printer admin, then fail */
2087 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2088 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2089 && !token_contains_name_in_list(
2090 uidtoname(p->session_info->unix_token->uid),
2091 p->session_info->info->domain_name,
2093 p->session_info->security_token,
2094 lp_printer_admin(-1)) )
2096 return WERR_ACCESS_DENIED;
2099 /* check that we have a valid driver name first */
2101 if ((version = get_version_id(r->in.architecture)) == -1) {
2102 return WERR_INVALID_ENVIRONMENT;
2105 tmp_ctx = talloc_new(p->mem_ctx);
2110 status = winreg_printer_binding_handle(tmp_ctx,
2111 get_session_info_system(),
2114 if (!W_ERROR_IS_OK(status)) {
2118 status = winreg_get_driver(tmp_ctx, b,
2119 r->in.architecture, r->in.driver,
2121 if (!W_ERROR_IS_OK(status)) {
2122 /* try for Win2k driver if "Windows NT x86" */
2124 if ( version == 2 ) {
2127 status = winreg_get_driver(tmp_ctx, b,
2131 if (!W_ERROR_IS_OK(status)) {
2132 status = WERR_UNKNOWN_PRINTER_DRIVER;
2136 /* otherwise it was a failure */
2138 status = WERR_UNKNOWN_PRINTER_DRIVER;
2144 if (printer_driver_in_use(tmp_ctx,
2147 status = WERR_PRINTER_DRIVER_IN_USE;
2152 status = winreg_get_driver(tmp_ctx, b,
2154 r->in.driver, 3, &info_win2k);
2155 if (W_ERROR_IS_OK(status)) {
2156 /* if we get to here, we now have 2 driver info structures to remove */
2157 /* remove the Win2k driver first*/
2159 status = winreg_del_driver(tmp_ctx, b,
2161 talloc_free(info_win2k);
2163 /* this should not have failed---if it did, report to client */
2164 if (!W_ERROR_IS_OK(status)) {
2170 status = winreg_del_driver(tmp_ctx, b,
2174 talloc_free(tmp_ctx);
2179 /****************************************************************
2180 _spoolss_DeletePrinterDriverEx
2181 ****************************************************************/
2183 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2184 struct spoolss_DeletePrinterDriverEx *r)
2186 struct spoolss_DriverInfo8 *info = NULL;
2187 struct spoolss_DriverInfo8 *info_win2k = NULL;
2191 struct dcerpc_binding_handle *b;
2192 TALLOC_CTX *tmp_ctx = NULL;
2194 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2195 and not a printer admin, then fail */
2197 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2198 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2199 && !token_contains_name_in_list(
2200 uidtoname(p->session_info->unix_token->uid),
2201 p->session_info->info->domain_name,
2203 p->session_info->security_token, lp_printer_admin(-1)) )
2205 return WERR_ACCESS_DENIED;
2208 /* check that we have a valid driver name first */
2209 if ((version = get_version_id(r->in.architecture)) == -1) {
2210 /* this is what NT returns */
2211 return WERR_INVALID_ENVIRONMENT;
2214 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) {
2215 version = r->in.version;
2218 tmp_ctx = talloc_new(p->mem_ctx);
2223 status = winreg_printer_binding_handle(tmp_ctx,
2224 get_session_info_system(),
2227 if (!W_ERROR_IS_OK(status)) {
2231 status = winreg_get_driver(tmp_ctx, b,
2236 if (!W_ERROR_IS_OK(status)) {
2237 status = WERR_UNKNOWN_PRINTER_DRIVER;
2240 * if the client asked for a specific version,
2241 * or this is something other than Windows NT x86,
2245 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2248 /* try for Win2k driver if "Windows NT x86" */
2251 status = winreg_get_driver(tmp_ctx, b,
2255 if (!W_ERROR_IS_OK(status)) {
2256 status = WERR_UNKNOWN_PRINTER_DRIVER;
2261 if (printer_driver_in_use(tmp_ctx,
2264 status = WERR_PRINTER_DRIVER_IN_USE;
2269 * we have a couple of cases to consider.
2270 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2271 * then the delete should fail if **any** files overlap with
2273 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2274 * non-overlapping files
2275 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2276 * is set, the do not delete any files
2277 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2280 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2282 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2285 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2286 printer_driver_files_in_use(tmp_ctx,
2287 get_session_info_system(),
2290 /* no idea of the correct error here */
2291 status = WERR_ACCESS_DENIED;
2296 /* also check for W32X86/3 if necessary; maybe we already have? */
2298 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2299 status = winreg_get_driver(tmp_ctx, b,
2301 r->in.driver, 3, &info_win2k);
2302 if (W_ERROR_IS_OK(status)) {
2305 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2306 printer_driver_files_in_use(info,
2307 get_session_info_system(),
2310 /* no idea of the correct error here */
2311 talloc_free(info_win2k);
2312 status = WERR_ACCESS_DENIED;
2316 /* if we get to here, we now have 2 driver info structures to remove */
2317 /* remove the Win2k driver first*/
2319 status = winreg_del_driver(tmp_ctx, b,
2323 /* this should not have failed---if it did, report to client */
2325 if (!W_ERROR_IS_OK(status)) {
2330 * now delete any associated files if delete_files is
2331 * true. Even if this part failes, we return succes
2332 * because the driver doesn not exist any more
2335 delete_driver_files(get_session_info_system(),
2341 status = winreg_del_driver(tmp_ctx, b,
2344 if (!W_ERROR_IS_OK(status)) {
2349 * now delete any associated files if delete_files is
2350 * true. Even if this part failes, we return succes
2351 * because the driver doesn not exist any more
2354 delete_driver_files(get_session_info_system(), info);
2358 talloc_free(tmp_ctx);
2363 /********************************************************************
2364 GetPrinterData on a printer server Handle.
2365 ********************************************************************/
2367 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2369 enum winreg_Type *type,
2370 union spoolss_PrinterData *data)
2372 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2374 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2380 if (!strcasecmp_m(value, "BeepEnabled")) {
2386 if (!strcasecmp_m(value, "EventLog")) {
2388 /* formally was 0x1b */
2393 if (!strcasecmp_m(value, "NetPopup")) {
2399 if (!strcasecmp_m(value, "MajorVersion")) {
2402 /* Windows NT 4.0 seems to not allow uploading of drivers
2403 to a server that reports 0x3 as the MajorVersion.
2404 need to investigate more how Win2k gets around this .
2407 if (RA_WINNT == get_remote_arch()) {
2416 if (!strcasecmp_m(value, "MinorVersion")) {
2423 * uint32_t size = 0x114
2424 * uint32_t major = 5
2425 * uint32_t minor = [0|1]
2426 * uint32_t build = [2195|2600]
2427 * extra unicode string = e.g. "Service Pack 3"
2429 if (!strcasecmp_m(value, "OSVersion")) {
2431 enum ndr_err_code ndr_err;
2432 struct spoolss_OSVersion os;
2434 os.major = 5; /* Windows 2000 == 5.0 */
2436 os.build = 2195; /* build */
2437 os.extra_string = ""; /* leave extra string empty */
2439 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2440 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2441 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2442 return WERR_GENERAL_FAILURE;
2446 data->binary = blob;
2452 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2455 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2456 W_ERROR_HAVE_NO_MEMORY(data->string);
2461 if (!strcasecmp_m(value, "Architecture")) {
2463 data->string = talloc_strdup(mem_ctx,
2464 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2465 W_ERROR_HAVE_NO_MEMORY(data->string);
2470 if (!strcasecmp_m(value, "DsPresent")) {
2473 /* only show the publish check box if we are a
2474 member of a AD domain */
2476 if (lp_security() == SEC_ADS) {
2484 if (!strcasecmp_m(value, "DNSMachineName")) {
2485 const char *hostname = get_mydnsfullname();
2488 return WERR_BADFILE;
2492 data->string = talloc_strdup(mem_ctx, hostname);
2493 W_ERROR_HAVE_NO_MEMORY(data->string);
2500 return WERR_INVALID_PARAM;
2503 /****************************************************************
2504 _spoolss_GetPrinterData
2505 ****************************************************************/
2507 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2508 struct spoolss_GetPrinterData *r)
2510 struct spoolss_GetPrinterDataEx r2;
2512 r2.in.handle = r->in.handle;
2513 r2.in.key_name = "PrinterDriverData";
2514 r2.in.value_name = r->in.value_name;
2515 r2.in.offered = r->in.offered;
2516 r2.out.type = r->out.type;
2517 r2.out.data = r->out.data;
2518 r2.out.needed = r->out.needed;
2520 return _spoolss_GetPrinterDataEx(p, &r2);
2523 /*********************************************************
2524 Connect to the client machine.
2525 **********************************************************/
2527 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2528 struct sockaddr_storage *client_ss, const char *remote_machine)
2531 struct cli_state *the_cli;
2532 struct sockaddr_storage rm_addr;
2533 char addr[INET6_ADDRSTRLEN];
2535 if ( is_zero_addr(client_ss) ) {
2536 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2538 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2539 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2542 print_sockaddr(addr, sizeof(addr), &rm_addr);
2544 rm_addr = *client_ss;
2545 print_sockaddr(addr, sizeof(addr), &rm_addr);
2546 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2550 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2551 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2556 /* setup the connection */
2557 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2558 &rm_addr, 0, "IPC$", "IPC",
2562 0, lp_client_signing());
2564 if ( !NT_STATUS_IS_OK( ret ) ) {
2565 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2570 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2571 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2572 cli_shutdown(the_cli);
2577 * Ok - we have an anonymous connection to the IPC$ share.
2578 * Now start the NT Domain stuff :-).
2581 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2582 if (!NT_STATUS_IS_OK(ret)) {
2583 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2584 remote_machine, nt_errstr(ret)));
2585 cli_shutdown(the_cli);
2592 /***************************************************************************
2593 Connect to the client.
2594 ****************************************************************************/
2596 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2597 uint32_t localprinter,
2598 enum winreg_Type type,
2599 struct policy_handle *handle,
2600 struct notify_back_channel **_chan,
2601 struct sockaddr_storage *client_ss,
2602 struct messaging_context *msg_ctx)
2606 struct notify_back_channel *chan;
2608 for (chan = back_channels; chan; chan = chan->next) {
2609 if (memcmp(&chan->client_address, client_ss,
2610 sizeof(struct sockaddr_storage)) == 0) {
2616 * If it's the first connection, contact the client
2617 * and connect to the IPC$ share anonymously
2620 fstring unix_printer;
2622 /* the +2 is to strip the leading 2 backslashs */
2623 fstrcpy(unix_printer, printer + 2);
2625 chan = talloc_zero(back_channels, struct notify_back_channel);
2629 chan->client_address = *client_ss;
2631 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2635 chan->binding_handle = chan->cli_pipe->binding_handle;
2637 DLIST_ADD(back_channels, chan);
2639 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2640 receive_notify2_message_list);
2641 /* Tell the connections db we're now interested in printer
2642 * notify messages. */
2643 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2644 true, FLAG_MSG_PRINT_NOTIFY);
2648 * Tell the specific printing tdb we want messages for this printer
2649 * by registering our PID.
2652 if (!print_notify_register_pid(snum)) {
2653 DEBUG(0, ("Failed to register our pid for printer %s\n",
2657 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2666 if (!NT_STATUS_IS_OK(status)) {
2667 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2668 result = ntstatus_to_werror(status);
2669 } else if (!W_ERROR_IS_OK(result)) {
2670 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2673 chan->active_connections++;
2676 return (W_ERROR_IS_OK(result));
2679 /****************************************************************
2680 ****************************************************************/
2682 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2683 const struct spoolss_NotifyOption *r)
2685 struct spoolss_NotifyOption *option;
2692 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2699 if (!option->count) {
2703 option->types = talloc_zero_array(option,
2704 struct spoolss_NotifyOptionType, option->count);
2705 if (!option->types) {
2706 talloc_free(option);
2710 for (i=0; i < option->count; i++) {
2711 option->types[i] = r->types[i];
2713 if (option->types[i].count) {
2714 option->types[i].fields = talloc_zero_array(option,
2715 union spoolss_Field, option->types[i].count);
2716 if (!option->types[i].fields) {
2717 talloc_free(option);
2720 for (k=0; k<option->types[i].count; k++) {
2721 option->types[i].fields[k] =
2722 r->types[i].fields[k];
2730 /****************************************************************
2731 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2733 * before replying OK: status=0 a rpc call is made to the workstation
2734 * asking ReplyOpenPrinter
2736 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2737 * called from api_spoolss_rffpcnex
2738 ****************************************************************/
2740 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2741 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2744 struct spoolss_NotifyOption *option = r->in.notify_options;
2745 struct sockaddr_storage client_ss;
2746 socklen_t client_len;
2748 /* store the notify value in the printer struct */
2750 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2753 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2754 "Invalid handle (%s:%u:%u).\n",
2755 OUR_HANDLE(r->in.handle)));
2759 Printer->notify.flags = r->in.flags;
2760 Printer->notify.options = r->in.options;
2761 Printer->notify.printerlocal = r->in.printer_local;
2762 Printer->notify.msg_ctx = p->msg_ctx;
2764 TALLOC_FREE(Printer->notify.option);
2765 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2767 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2769 /* Connect to the client machine and send a ReplyOpenPrinter */
2771 if ( Printer->printer_type == SPLHND_SERVER)
2773 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2774 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2777 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2778 "remote_address is %s\n",
2779 tsocket_address_string(p->remote_address, p->mem_ctx)));
2781 if (!lp_print_notify_backchannel(snum)) {
2782 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2783 "backchannel disabled\n"));
2784 return WERR_SERVER_UNAVAILABLE;
2787 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2788 (struct sockaddr *) &client_ss,
2789 sizeof(struct sockaddr_storage));
2790 if (client_len < 0) {
2794 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2795 Printer->notify.printerlocal, REG_SZ,
2796 &Printer->notify.cli_hnd,
2797 &Printer->notify.cli_chan,
2798 &client_ss, p->msg_ctx)) {
2799 return WERR_SERVER_UNAVAILABLE;
2805 /*******************************************************************
2806 * fill a notify_info_data with the servername
2807 ********************************************************************/
2809 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2811 struct spoolss_Notify *data,
2812 print_queue_struct *queue,
2813 struct spoolss_PrinterInfo2 *pinfo2,
2814 TALLOC_CTX *mem_ctx)
2816 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2819 /*******************************************************************
2820 * fill a notify_info_data with the printername (not including the servername).
2821 ********************************************************************/
2823 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2825 struct spoolss_Notify *data,
2826 print_queue_struct *queue,
2827 struct spoolss_PrinterInfo2 *pinfo2,
2828 TALLOC_CTX *mem_ctx)
2830 /* the notify name should not contain the \\server\ part */
2831 const char *p = strrchr(pinfo2->printername, '\\');
2834 p = pinfo2->printername;
2839 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2842 /*******************************************************************
2843 * fill a notify_info_data with the servicename
2844 ********************************************************************/
2846 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2848 struct spoolss_Notify *data,
2849 print_queue_struct *queue,
2850 struct spoolss_PrinterInfo2 *pinfo2,
2851 TALLOC_CTX *mem_ctx)
2853 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2856 /*******************************************************************
2857 * fill a notify_info_data with the port name
2858 ********************************************************************/
2860 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2862 struct spoolss_Notify *data,
2863 print_queue_struct *queue,
2864 struct spoolss_PrinterInfo2 *pinfo2,
2865 TALLOC_CTX *mem_ctx)
2867 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2870 /*******************************************************************
2871 * fill a notify_info_data with the printername
2872 * but it doesn't exist, have to see what to do
2873 ********************************************************************/
2875 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2877 struct spoolss_Notify *data,
2878 print_queue_struct *queue,
2879 struct spoolss_PrinterInfo2 *pinfo2,
2880 TALLOC_CTX *mem_ctx)
2882 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2885 /*******************************************************************
2886 * fill a notify_info_data with the comment
2887 ********************************************************************/
2889 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2891 struct spoolss_Notify *data,
2892 print_queue_struct *queue,
2893 struct spoolss_PrinterInfo2 *pinfo2,
2894 TALLOC_CTX *mem_ctx)
2898 if (*pinfo2->comment == '\0') {
2899 p = lp_comment(snum);
2901 p = pinfo2->comment;
2904 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2907 /*******************************************************************
2908 * fill a notify_info_data with the comment
2909 * location = "Room 1, floor 2, building 3"
2910 ********************************************************************/
2912 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2914 struct spoolss_Notify *data,
2915 print_queue_struct *queue,
2916 struct spoolss_PrinterInfo2 *pinfo2,
2917 TALLOC_CTX *mem_ctx)
2919 const char *loc = pinfo2->location;
2922 status = printer_list_get_printer(mem_ctx,
2927 if (NT_STATUS_IS_OK(status)) {
2929 loc = pinfo2->location;
2933 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2936 /*******************************************************************
2937 * fill a notify_info_data with the device mode
2938 * jfm:xxxx don't to it for know but that's a real problem !!!
2939 ********************************************************************/
2941 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2943 struct spoolss_Notify *data,
2944 print_queue_struct *queue,
2945 struct spoolss_PrinterInfo2 *pinfo2,
2946 TALLOC_CTX *mem_ctx)
2948 /* for a dummy implementation we have to zero the fields */
2949 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2952 /*******************************************************************
2953 * fill a notify_info_data with the separator file name
2954 ********************************************************************/
2956 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2958 struct spoolss_Notify *data,
2959 print_queue_struct *queue,
2960 struct spoolss_PrinterInfo2 *pinfo2,
2961 TALLOC_CTX *mem_ctx)
2963 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2966 /*******************************************************************
2967 * fill a notify_info_data with the print processor
2968 * jfm:xxxx return always winprint to indicate we don't do anything to it
2969 ********************************************************************/
2971 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2973 struct spoolss_Notify *data,
2974 print_queue_struct *queue,
2975 struct spoolss_PrinterInfo2 *pinfo2,
2976 TALLOC_CTX *mem_ctx)
2978 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2981 /*******************************************************************
2982 * fill a notify_info_data with the print processor options
2983 * jfm:xxxx send an empty string
2984 ********************************************************************/
2986 static void spoolss_notify_parameters(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_STRING(data, pinfo2->parameters);
2996 /*******************************************************************
2997 * fill a notify_info_data with the data type
2998 * jfm:xxxx always send RAW as data type
2999 ********************************************************************/
3001 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
3003 struct spoolss_Notify *data,
3004 print_queue_struct *queue,
3005 struct spoolss_PrinterInfo2 *pinfo2,
3006 TALLOC_CTX *mem_ctx)
3008 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
3011 /*******************************************************************
3012 * fill a notify_info_data with the security descriptor
3013 * jfm:xxxx send an null pointer to say no security desc
3014 * have to implement security before !
3015 ********************************************************************/
3017 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
3019 struct spoolss_Notify *data,
3020 print_queue_struct *queue,
3021 struct spoolss_PrinterInfo2 *pinfo2,
3022 TALLOC_CTX *mem_ctx)
3024 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
3027 /*******************************************************************
3028 * fill a notify_info_data with the attributes
3029 * jfm:xxxx a samba printer is always shared
3030 ********************************************************************/
3032 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3034 struct spoolss_Notify *data,
3035 print_queue_struct *queue,
3036 struct spoolss_PrinterInfo2 *pinfo2,
3037 TALLOC_CTX *mem_ctx)
3039 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3042 /*******************************************************************
3043 * fill a notify_info_data with the priority
3044 ********************************************************************/
3046 static void spoolss_notify_priority(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 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3056 /*******************************************************************
3057 * fill a notify_info_data with the default priority
3058 ********************************************************************/
3060 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3062 struct spoolss_Notify *data,
3063 print_queue_struct *queue,
3064 struct spoolss_PrinterInfo2 *pinfo2,
3065 TALLOC_CTX *mem_ctx)
3067 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3070 /*******************************************************************
3071 * fill a notify_info_data with the start time
3072 ********************************************************************/
3074 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3076 struct spoolss_Notify *data,
3077 print_queue_struct *queue,
3078 struct spoolss_PrinterInfo2 *pinfo2,
3079 TALLOC_CTX *mem_ctx)
3081 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3084 /*******************************************************************
3085 * fill a notify_info_data with the until time
3086 ********************************************************************/
3088 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3090 struct spoolss_Notify *data,
3091 print_queue_struct *queue,
3092 struct spoolss_PrinterInfo2 *pinfo2,
3093 TALLOC_CTX *mem_ctx)
3095 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3098 /*******************************************************************
3099 * fill a notify_info_data with the status
3100 ********************************************************************/
3102 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3104 struct spoolss_Notify *data,
3105 print_queue_struct *queue,
3106 struct spoolss_PrinterInfo2 *pinfo2,
3107 TALLOC_CTX *mem_ctx)
3109 print_status_struct status;
3111 print_queue_length(msg_ctx, snum, &status);
3112 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3115 /*******************************************************************
3116 * fill a notify_info_data with the number of jobs queued
3117 ********************************************************************/
3119 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3121 struct spoolss_Notify *data,
3122 print_queue_struct *queue,
3123 struct spoolss_PrinterInfo2 *pinfo2,
3124 TALLOC_CTX *mem_ctx)
3126 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3127 data, print_queue_length(msg_ctx, snum, NULL));
3130 /*******************************************************************
3131 * fill a notify_info_data with the average ppm
3132 ********************************************************************/
3134 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3136 struct spoolss_Notify *data,
3137 print_queue_struct *queue,
3138 struct spoolss_PrinterInfo2 *pinfo2,
3139 TALLOC_CTX *mem_ctx)
3141 /* always respond 8 pages per minutes */
3142 /* a little hard ! */
3143 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3146 /*******************************************************************
3147 * fill a notify_info_data with username
3148 ********************************************************************/
3150 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3152 struct spoolss_Notify *data,
3153 print_queue_struct *queue,
3154 struct spoolss_PrinterInfo2 *pinfo2,
3155 TALLOC_CTX *mem_ctx)
3157 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3160 /*******************************************************************
3161 * fill a notify_info_data with job status
3162 ********************************************************************/
3164 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3166 struct spoolss_Notify *data,
3167 print_queue_struct *queue,
3168 struct spoolss_PrinterInfo2 *pinfo2,
3169 TALLOC_CTX *mem_ctx)
3171 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3174 /*******************************************************************
3175 * fill a notify_info_data with job name
3176 ********************************************************************/
3178 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3180 struct spoolss_Notify *data,
3181 print_queue_struct *queue,
3182 struct spoolss_PrinterInfo2 *pinfo2,
3183 TALLOC_CTX *mem_ctx)
3185 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3188 /*******************************************************************
3189 * fill a notify_info_data with job status
3190 ********************************************************************/
3192 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3194 struct spoolss_Notify *data,
3195 print_queue_struct *queue,
3196 struct spoolss_PrinterInfo2 *pinfo2,
3197 TALLOC_CTX *mem_ctx)
3200 * Now we're returning job status codes we just return a "" here. JRA.
3205 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3208 switch (queue->status) {
3213 p = ""; /* NT provides the paused string */
3222 #endif /* NO LONGER NEEDED. */
3224 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3227 /*******************************************************************
3228 * fill a notify_info_data with job time
3229 ********************************************************************/
3231 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3233 struct spoolss_Notify *data,
3234 print_queue_struct *queue,
3235 struct spoolss_PrinterInfo2 *pinfo2,
3236 TALLOC_CTX *mem_ctx)
3238 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3241 /*******************************************************************
3242 * fill a notify_info_data with job size
3243 ********************************************************************/
3245 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3247 struct spoolss_Notify *data,
3248 print_queue_struct *queue,
3249 struct spoolss_PrinterInfo2 *pinfo2,
3250 TALLOC_CTX *mem_ctx)
3252 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3255 /*******************************************************************
3256 * fill a notify_info_data with page info
3257 ********************************************************************/
3258 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3260 struct spoolss_Notify *data,
3261 print_queue_struct *queue,
3262 struct spoolss_PrinterInfo2 *pinfo2,
3263 TALLOC_CTX *mem_ctx)
3265 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3268 /*******************************************************************
3269 * fill a notify_info_data with pages printed info.
3270 ********************************************************************/
3271 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3273 struct spoolss_Notify *data,
3274 print_queue_struct *queue,
3275 struct spoolss_PrinterInfo2 *pinfo2,
3276 TALLOC_CTX *mem_ctx)
3278 /* Add code when back-end tracks this */
3279 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3282 /*******************************************************************
3283 Fill a notify_info_data with job position.
3284 ********************************************************************/
3286 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3288 struct spoolss_Notify *data,
3289 print_queue_struct *queue,
3290 struct spoolss_PrinterInfo2 *pinfo2,
3291 TALLOC_CTX *mem_ctx)
3293 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3296 /*******************************************************************
3297 Fill a notify_info_data with submitted time.
3298 ********************************************************************/
3300 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3302 struct spoolss_Notify *data,
3303 print_queue_struct *queue,
3304 struct spoolss_PrinterInfo2 *pinfo2,
3305 TALLOC_CTX *mem_ctx)
3307 data->data.string.string = NULL;
3308 data->data.string.size = 0;
3310 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3311 &data->data.string.string,
3312 &data->data.string.size);
3316 struct s_notify_info_data_table
3318 enum spoolss_NotifyType type;
3321 enum spoolss_NotifyTable variable_type;
3322 void (*fn) (struct messaging_context *msg_ctx,
3323 int snum, struct spoolss_Notify *data,
3324 print_queue_struct *queue,
3325 struct spoolss_PrinterInfo2 *pinfo2,
3326 TALLOC_CTX *mem_ctx);
3329 /* A table describing the various print notification constants and
3330 whether the notification data is a pointer to a variable sized
3331 buffer, a one value uint32_t or a two value uint32_t. */
3333 static const struct s_notify_info_data_table notify_info_data_table[] =
3335 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3336 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3337 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3338 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3339 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3340 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3341 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3342 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3343 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3344 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3345 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3346 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3347 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3348 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3349 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3350 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3351 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3352 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3353 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3354 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3355 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3356 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3357 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3358 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3359 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3360 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3361 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3362 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3363 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3364 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3365 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3366 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3367 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3368 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3369 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3370 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3371 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3372 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3373 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3374 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3375 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3376 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3377 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3378 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3379 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3380 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3381 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3382 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3383 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3386 /*******************************************************************
3387 Return the variable_type of info_data structure.
3388 ********************************************************************/
3390 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3395 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3396 if ( (notify_info_data_table[i].type == type) &&
3397 (notify_info_data_table[i].field == field) ) {
3398 return notify_info_data_table[i].variable_type;
3402 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3404 return (enum spoolss_NotifyTable) 0;
3407 /****************************************************************************
3408 ****************************************************************************/
3410 static bool search_notify(enum spoolss_NotifyType type,
3416 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3417 if (notify_info_data_table[i].type == type &&
3418 notify_info_data_table[i].field == field &&
3419 notify_info_data_table[i].fn != NULL) {
3428 /****************************************************************************
3429 ****************************************************************************/
3431 static void construct_info_data(struct spoolss_Notify *info_data,
3432 enum spoolss_NotifyType type,
3433 uint16_t field, int id)
3435 info_data->type = type;
3436 info_data->field.field = field;
3437 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3438 info_data->job_id = id;
3441 /*******************************************************************
3443 * fill a notify_info struct with info asked
3445 ********************************************************************/
3447 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3448 struct printer_handle *print_hnd,
3449 struct spoolss_NotifyInfo *info,
3450 struct spoolss_PrinterInfo2 *pinfo2,
3452 const struct spoolss_NotifyOptionType *option_type,
3454 TALLOC_CTX *mem_ctx)
3457 enum spoolss_NotifyType type;
3460 struct spoolss_Notify *current_data;
3462 type = option_type->type;
3464 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3465 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3466 option_type->count, lp_servicename(snum)));
3468 for(field_num=0; field_num < option_type->count; field_num++) {
3469 field = option_type->fields[field_num].field;
3471 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3473 if (!search_notify(type, field, &j) )
3476 info->notifies = talloc_realloc(info, info->notifies,
3477 struct spoolss_Notify,
3479 if (info->notifies == NULL) {
3480 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3484 current_data = &info->notifies[info->count];
3486 construct_info_data(current_data, type, field, id);
3488 DEBUG(10, ("construct_notify_printer_info: "
3489 "calling [%s] snum=%d printername=[%s])\n",
3490 notify_info_data_table[j].name, snum,
3491 pinfo2->printername));
3493 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3494 NULL, pinfo2, mem_ctx);
3502 /*******************************************************************
3504 * fill a notify_info struct with info asked
3506 ********************************************************************/
3508 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3509 print_queue_struct *queue,
3510 struct spoolss_NotifyInfo *info,
3511 struct spoolss_PrinterInfo2 *pinfo2,
3513 const struct spoolss_NotifyOptionType *option_type,
3515 TALLOC_CTX *mem_ctx)
3518 enum spoolss_NotifyType type;
3520 struct spoolss_Notify *current_data;
3522 DEBUG(4,("construct_notify_jobs_info\n"));
3524 type = option_type->type;
3526 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3527 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3528 option_type->count));
3530 for(field_num=0; field_num<option_type->count; field_num++) {
3531 field = option_type->fields[field_num].field;
3533 if (!search_notify(type, field, &j) )
3536 info->notifies = talloc_realloc(info, info->notifies,
3537 struct spoolss_Notify,
3539 if (info->notifies == NULL) {
3540 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3544 current_data=&(info->notifies[info->count]);
3546 construct_info_data(current_data, type, field, id);
3547 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3548 queue, pinfo2, mem_ctx);
3556 * JFM: The enumeration is not that simple, it's even non obvious.
3558 * let's take an example: I want to monitor the PRINTER SERVER for
3559 * the printer's name and the number of jobs currently queued.
3560 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3561 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3563 * I have 3 printers on the back of my server.
3565 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3568 * 1 printer 1 name 1
3569 * 2 printer 1 cjob 1
3570 * 3 printer 2 name 2
3571 * 4 printer 2 cjob 2
3572 * 5 printer 3 name 3
3573 * 6 printer 3 name 3
3575 * that's the print server case, the printer case is even worse.
3578 /*******************************************************************
3580 * enumerate all printers on the printserver
3581 * fill a notify_info struct with info asked
3583 ********************************************************************/
3585 static WERROR printserver_notify_info(struct pipes_struct *p,
3586 struct policy_handle *hnd,
3587 struct spoolss_NotifyInfo *info,
3588 TALLOC_CTX *mem_ctx)
3591 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3592 int n_services=lp_numservices();
3594 struct spoolss_NotifyOption *option;
3595 struct spoolss_NotifyOptionType option_type;
3596 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3599 DEBUG(4,("printserver_notify_info\n"));
3604 option = Printer->notify.option;
3607 info->notifies = NULL;
3610 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3611 sending a ffpcn() request first */
3616 for (i=0; i<option->count; i++) {
3617 option_type = option->types[i];
3619 if (option_type.type != PRINTER_NOTIFY_TYPE)
3622 for (snum = 0; snum < n_services; snum++) {
3623 if (!lp_browseable(snum) ||
3624 !lp_snum_ok(snum) ||
3625 !lp_print_ok(snum)) {
3626 continue; /* skip */
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(snum),
3635 if (!W_ERROR_IS_OK(result)) {
3636 DEBUG(4, ("printserver_notify_info: "
3637 "Failed to get printer [%s]\n",
3638 lp_servicename(snum)));
3643 construct_notify_printer_info(p->msg_ctx,
3649 TALLOC_FREE(pinfo2);
3655 * Debugging information, don't delete.
3658 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3659 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3660 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3662 for (i=0; i<info->count; i++) {
3663 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3664 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3665 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3672 /*******************************************************************
3674 * fill a notify_info struct with info asked
3676 ********************************************************************/
3678 static WERROR printer_notify_info(struct pipes_struct *p,
3679 struct policy_handle *hnd,
3680 struct spoolss_NotifyInfo *info,
3681 TALLOC_CTX *mem_ctx)
3684 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3687 struct spoolss_NotifyOption *option;
3688 struct spoolss_NotifyOptionType option_type;
3690 print_queue_struct *queue=NULL;
3691 print_status_struct status;
3692 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3695 DEBUG(4,("printer_notify_info\n"));
3700 option = Printer->notify.option;
3704 info->notifies = NULL;
3707 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3708 sending a ffpcn() request first */
3713 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3717 /* Maybe we should use the SYSTEM session_info here... */
3718 result = winreg_get_printer_internal(mem_ctx,
3719 get_session_info_system(),
3721 lp_servicename(snum), &pinfo2);
3722 if (!W_ERROR_IS_OK(result)) {
3726 for (i=0; i<option->count; i++) {
3727 option_type = option->types[i];
3729 switch (option_type.type) {
3730 case PRINTER_NOTIFY_TYPE:
3731 if (construct_notify_printer_info(p->msg_ctx,
3740 case JOB_NOTIFY_TYPE:
3742 count = print_queue_status(p->msg_ctx, snum, &queue,
3745 for (j=0; j<count; j++) {
3746 construct_notify_jobs_info(p->msg_ctx,
3760 * Debugging information, don't delete.
3763 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3764 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3765 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3767 for (i=0; i<info->count; i++) {
3768 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3769 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3770 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3774 talloc_free(pinfo2);
3778 /****************************************************************
3779 _spoolss_RouterRefreshPrinterChangeNotify
3780 ****************************************************************/
3782 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3783 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3785 struct spoolss_NotifyInfo *info;
3787 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3788 WERROR result = WERR_BADFID;
3790 /* we always have a spoolss_NotifyInfo struct */
3791 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3793 result = WERR_NOMEM;
3797 *r->out.info = info;
3800 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3801 "Invalid handle (%s:%u:%u).\n",
3802 OUR_HANDLE(r->in.handle)));
3806 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3809 * We are now using the change value, and
3810 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3811 * I don't have a global notification system, I'm sending back all the
3812 * information even when _NOTHING_ has changed.
3815 /* We need to keep track of the change value to send back in
3816 RRPCN replies otherwise our updates are ignored. */
3818 Printer->notify.fnpcn = true;
3820 if (Printer->notify.cli_chan != NULL &&
3821 Printer->notify.cli_chan->active_connections > 0) {
3822 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3823 "Saving change value in request [%x]\n",
3825 Printer->notify.change = r->in.change_low;
3828 /* just ignore the spoolss_NotifyOption */
3830 switch (Printer->printer_type) {
3832 result = printserver_notify_info(p, r->in.handle,
3836 case SPLHND_PRINTER:
3837 result = printer_notify_info(p, r->in.handle,
3842 Printer->notify.fnpcn = false;
3848 /********************************************************************
3849 ********************************************************************/
3851 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3852 const char *servername,
3853 const char *printername,
3854 const char **printername_p)
3856 /* FIXME: add lp_force_printername() */
3858 if (servername == NULL) {
3859 *printername_p = talloc_strdup(mem_ctx, printername);
3860 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3864 if (servername[0] == '\\' && servername[1] == '\\') {
3868 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3869 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3874 /********************************************************************
3875 ********************************************************************/
3877 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3878 const char *printername)
3884 dm->devicename = talloc_strndup(dm, printername,
3885 MIN(strlen(printername), 31));
3888 /********************************************************************
3889 * construct_printer_info_0
3890 * fill a printer_info_0 struct
3891 ********************************************************************/
3893 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3894 const struct auth_session_info *session_info,
3895 struct messaging_context *msg_ctx,
3896 struct spoolss_PrinterInfo2 *info2,
3897 const char *servername,
3898 struct spoolss_PrinterInfo0 *r,
3902 struct printer_session_counter *session_counter;
3903 struct timeval setuptime;
3904 print_status_struct status;
3907 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3908 if (!W_ERROR_IS_OK(result)) {
3913 r->servername = talloc_strdup(mem_ctx, servername);
3914 W_ERROR_HAVE_NO_MEMORY(r->servername);
3916 r->servername = NULL;
3919 count = print_queue_length(msg_ctx, snum, &status);
3921 /* check if we already have a counter for this printer */
3922 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3923 if (session_counter->snum == snum)
3927 /* it's the first time, add it to the list */
3928 if (session_counter == NULL) {
3929 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3930 W_ERROR_HAVE_NO_MEMORY(session_counter);
3931 session_counter->snum = snum;
3932 session_counter->counter = 0;
3933 DLIST_ADD(counter_list, session_counter);
3937 session_counter->counter++;
3943 get_startup_time(&setuptime);
3944 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3947 * the global_counter should be stored in a TDB as it's common to all the clients
3948 * and should be zeroed on samba startup
3950 r->global_counter = session_counter->counter;
3952 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3953 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3954 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3955 r->free_build = SPOOLSS_RELEASE_BUILD;
3957 r->max_spooling = 0;
3958 r->session_counter = session_counter->counter;
3959 r->num_error_out_of_paper = 0x0;
3960 r->num_error_not_ready = 0x0; /* number of print failure */
3962 r->number_of_processors = 0x1;
3963 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3964 r->high_part_total_bytes = 0x0;
3966 /* ChangeID in milliseconds*/
3967 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3968 info2->sharename, &r->change_id);
3970 r->last_error = WERR_OK;
3971 r->status = nt_printq_status(status.status);
3972 r->enumerate_network_printers = 0x0;
3973 r->c_setprinter = 0x0;
3974 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3975 r->processor_level = 0x6; /* 6 ???*/
3984 /********************************************************************
3985 * construct_printer_info1
3986 * fill a spoolss_PrinterInfo1 struct
3987 ********************************************************************/
3989 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3990 const struct spoolss_PrinterInfo2 *info2,
3992 const char *servername,
3993 struct spoolss_PrinterInfo1 *r,
4000 if (info2->comment == NULL || info2->comment[0] == '\0') {
4001 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4003 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4005 W_ERROR_HAVE_NO_MEMORY(r->comment);
4007 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4008 if (!W_ERROR_IS_OK(result)) {
4012 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4016 W_ERROR_HAVE_NO_MEMORY(r->description);
4021 /********************************************************************
4022 * construct_printer_info2
4023 * fill a spoolss_PrinterInfo2 struct
4024 ********************************************************************/
4026 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4027 struct messaging_context *msg_ctx,
4028 const struct spoolss_PrinterInfo2 *info2,
4029 const char *servername,
4030 struct spoolss_PrinterInfo2 *r,
4034 print_status_struct status;
4037 count = print_queue_length(msg_ctx, snum, &status);
4040 r->servername = talloc_strdup(mem_ctx, servername);
4041 W_ERROR_HAVE_NO_MEMORY(r->servername);
4043 r->servername = NULL;
4046 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4047 if (!W_ERROR_IS_OK(result)) {
4051 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4052 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4053 r->portname = talloc_strdup(mem_ctx, info2->portname);
4054 W_ERROR_HAVE_NO_MEMORY(r->portname);
4055 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4056 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4058 if (info2->comment[0] == '\0') {
4059 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4061 r->comment = talloc_strdup(mem_ctx, info2->comment);
4063 W_ERROR_HAVE_NO_MEMORY(r->comment);
4065 r->location = talloc_strdup(mem_ctx, info2->location);
4066 if (info2->location[0] == '\0') {
4067 const char *loc = NULL;
4070 nt_status = printer_list_get_printer(mem_ctx,
4075 if (NT_STATUS_IS_OK(nt_status)) {
4077 r->location = talloc_strdup(mem_ctx, loc);
4081 W_ERROR_HAVE_NO_MEMORY(r->location);
4083 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4084 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4085 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4086 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4087 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4088 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4089 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4090 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4092 r->attributes = info2->attributes;
4094 r->priority = info2->priority;
4095 r->defaultpriority = info2->defaultpriority;
4096 r->starttime = info2->starttime;
4097 r->untiltime = info2->untiltime;
4098 r->status = nt_printq_status(status.status);
4100 r->averageppm = info2->averageppm;
4102 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4104 DEBUG(8,("Returning NULL Devicemode!\n"));
4107 compose_devicemode_devicename(r->devmode, r->printername);
4111 if (info2->secdesc != NULL) {
4112 /* don't use talloc_steal() here unless you do a deep steal of all
4113 the SEC_DESC members */
4115 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4121 /********************************************************************
4122 * construct_printer_info3
4123 * fill a spoolss_PrinterInfo3 struct
4124 ********************************************************************/
4126 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4127 const struct spoolss_PrinterInfo2 *info2,
4128 const char *servername,
4129 struct spoolss_PrinterInfo3 *r,
4132 /* These are the components of the SD we are returning. */
4134 if (info2->secdesc != NULL) {
4135 /* don't use talloc_steal() here unless you do a deep steal of all
4136 the SEC_DESC members */
4138 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4139 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4145 /********************************************************************
4146 * construct_printer_info4
4147 * fill a spoolss_PrinterInfo4 struct
4148 ********************************************************************/
4150 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4151 const struct spoolss_PrinterInfo2 *info2,
4152 const char *servername,
4153 struct spoolss_PrinterInfo4 *r,
4158 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4159 if (!W_ERROR_IS_OK(result)) {
4164 r->servername = talloc_strdup(mem_ctx, servername);
4165 W_ERROR_HAVE_NO_MEMORY(r->servername);
4167 r->servername = NULL;
4170 r->attributes = info2->attributes;
4175 /********************************************************************
4176 * construct_printer_info5
4177 * fill a spoolss_PrinterInfo5 struct
4178 ********************************************************************/
4180 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4181 const struct spoolss_PrinterInfo2 *info2,
4182 const char *servername,
4183 struct spoolss_PrinterInfo5 *r,
4188 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4189 if (!W_ERROR_IS_OK(result)) {
4193 r->portname = talloc_strdup(mem_ctx, info2->portname);
4194 W_ERROR_HAVE_NO_MEMORY(r->portname);
4196 r->attributes = info2->attributes;
4198 /* these two are not used by NT+ according to MSDN */
4199 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4200 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4205 /********************************************************************
4206 * construct_printer_info_6
4207 * fill a spoolss_PrinterInfo6 struct
4208 ********************************************************************/
4210 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4211 struct messaging_context *msg_ctx,
4212 const struct spoolss_PrinterInfo2 *info2,
4213 const char *servername,
4214 struct spoolss_PrinterInfo6 *r,
4217 print_status_struct status;
4219 print_queue_length(msg_ctx, snum, &status);
4221 r->status = nt_printq_status(status.status);
4226 /********************************************************************
4227 * construct_printer_info7
4228 * fill a spoolss_PrinterInfo7 struct
4229 ********************************************************************/
4231 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4232 struct messaging_context *msg_ctx,
4233 const char *servername,
4234 struct spoolss_PrinterInfo7 *r,
4237 const struct auth_session_info *session_info = get_session_info_system();
4240 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4242 lp_servicename(snum), &guid, NULL)) {
4243 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4244 r->action = DSPRINT_PUBLISH;
4246 r->guid = talloc_strdup(mem_ctx, "");
4247 r->action = DSPRINT_UNPUBLISH;
4249 W_ERROR_HAVE_NO_MEMORY(r->guid);
4254 /********************************************************************
4255 * construct_printer_info8
4256 * fill a spoolss_PrinterInfo8 struct
4257 ********************************************************************/
4259 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4260 const struct spoolss_PrinterInfo2 *info2,
4261 const char *servername,
4262 struct spoolss_DeviceModeInfo *r,
4266 const char *printername;
4268 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4269 if (!W_ERROR_IS_OK(result)) {
4273 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4275 DEBUG(8,("Returning NULL Devicemode!\n"));
4278 compose_devicemode_devicename(r->devmode, printername);
4284 /********************************************************************
4285 ********************************************************************/
4287 static bool snum_is_shared_printer(int snum)
4289 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4292 /********************************************************************
4293 Spoolss_enumprinters.
4294 ********************************************************************/
4296 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4297 const struct auth_session_info *session_info,
4298 struct messaging_context *msg_ctx,
4299 const char *servername,
4302 union spoolss_PrinterInfo **info_p,
4306 int n_services = lp_numservices();
4307 union spoolss_PrinterInfo *info = NULL;
4309 WERROR result = WERR_OK;
4310 struct dcerpc_binding_handle *b = NULL;
4311 TALLOC_CTX *tmp_ctx = NULL;
4313 tmp_ctx = talloc_new(mem_ctx);
4321 for (snum = 0; snum < n_services; snum++) {
4323 const char *printer;
4324 struct spoolss_PrinterInfo2 *info2;
4326 if (!snum_is_shared_printer(snum)) {
4330 printer = lp_const_servicename(snum);
4332 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4336 result = winreg_printer_binding_handle(tmp_ctx,
4340 if (!W_ERROR_IS_OK(result)) {
4345 result = winreg_create_printer(tmp_ctx, b,
4347 if (!W_ERROR_IS_OK(result)) {
4351 info = talloc_realloc(tmp_ctx, info,
4352 union spoolss_PrinterInfo,
4355 result = WERR_NOMEM;
4359 result = winreg_get_printer(tmp_ctx, b,
4361 if (!W_ERROR_IS_OK(result)) {
4367 result = construct_printer_info0(info, session_info,
4370 &info[count].info0, snum);
4373 result = construct_printer_info1(info, info2, flags,
4375 &info[count].info1, snum);
4378 result = construct_printer_info2(info, msg_ctx, info2,
4380 &info[count].info2, snum);
4383 result = construct_printer_info4(info, info2,
4385 &info[count].info4, snum);
4388 result = construct_printer_info5(info, info2,
4390 &info[count].info5, snum);
4394 result = WERR_UNKNOWN_LEVEL;
4398 if (!W_ERROR_IS_OK(result)) {
4406 if (W_ERROR_IS_OK(result)) {
4407 *info_p = talloc_move(mem_ctx, &info);
4411 talloc_free(tmp_ctx);
4416 /********************************************************************
4417 * handle enumeration of printers at level 0
4418 ********************************************************************/
4420 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4421 const struct auth_session_info *session_info,
4422 struct messaging_context *msg_ctx,
4424 const char *servername,
4425 union spoolss_PrinterInfo **info,
4428 DEBUG(4,("enum_all_printers_info_0\n"));
4430 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4431 servername, 0, flags, info, count);
4435 /********************************************************************
4436 ********************************************************************/
4438 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4439 const struct auth_session_info *session_info,
4440 struct messaging_context *msg_ctx,
4441 const char *servername,
4443 union spoolss_PrinterInfo **info,
4446 DEBUG(4,("enum_all_printers_info_1\n"));
4448 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4449 servername, 1, flags, info, count);
4452 /********************************************************************
4453 enum_all_printers_info_1_local.
4454 *********************************************************************/
4456 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4457 const struct auth_session_info *session_info,
4458 struct messaging_context *msg_ctx,
4459 const char *servername,
4460 union spoolss_PrinterInfo **info,
4463 DEBUG(4,("enum_all_printers_info_1_local\n"));
4465 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4466 servername, PRINTER_ENUM_ICON8, info, count);
4469 /********************************************************************
4470 enum_all_printers_info_1_name.
4471 *********************************************************************/
4473 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4474 const struct auth_session_info *session_info,
4475 struct messaging_context *msg_ctx,
4476 const char *servername,
4477 union spoolss_PrinterInfo **info,
4480 const char *s = servername;
4482 DEBUG(4,("enum_all_printers_info_1_name\n"));
4484 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4488 if (!is_myname_or_ipaddr(s)) {
4489 return WERR_INVALID_NAME;
4492 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4493 servername, PRINTER_ENUM_ICON8, info, count);
4496 /********************************************************************
4497 enum_all_printers_info_1_network.
4498 *********************************************************************/
4500 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4501 const struct auth_session_info *session_info,
4502 struct messaging_context *msg_ctx,
4503 const char *servername,
4504 union spoolss_PrinterInfo **info,
4507 const char *s = servername;
4509 DEBUG(4,("enum_all_printers_info_1_network\n"));
4511 /* If we respond to a enum_printers level 1 on our name with flags
4512 set to PRINTER_ENUM_REMOTE with a list of printers then these
4513 printers incorrectly appear in the APW browse list.
4514 Specifically the printers for the server appear at the workgroup
4515 level where all the other servers in the domain are
4516 listed. Windows responds to this call with a
4517 WERR_CAN_NOT_COMPLETE so we should do the same. */
4519 if (servername[0] == '\\' && servername[1] == '\\') {
4523 if (is_myname_or_ipaddr(s)) {
4524 return WERR_CAN_NOT_COMPLETE;
4527 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4528 servername, PRINTER_ENUM_NAME, info, count);
4531 /********************************************************************
4532 * api_spoolss_enumprinters
4534 * called from api_spoolss_enumprinters (see this to understand)
4535 ********************************************************************/
4537 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4538 const struct auth_session_info *session_info,
4539 struct messaging_context *msg_ctx,
4540 const char *servername,
4541 union spoolss_PrinterInfo **info,
4544 DEBUG(4,("enum_all_printers_info_2\n"));
4546 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4547 servername, 2, 0, info, count);
4550 /********************************************************************
4551 * handle enumeration of printers at level 1
4552 ********************************************************************/
4554 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4555 const struct auth_session_info *session_info,
4556 struct messaging_context *msg_ctx,
4558 const char *servername,
4559 union spoolss_PrinterInfo **info,
4562 /* Not all the flags are equals */
4564 if (flags & PRINTER_ENUM_LOCAL) {
4565 return enum_all_printers_info_1_local(mem_ctx, session_info,
4566 msg_ctx, servername, info, count);
4569 if (flags & PRINTER_ENUM_NAME) {
4570 return enum_all_printers_info_1_name(mem_ctx, session_info,
4571 msg_ctx, servername, info,
4575 if (flags & PRINTER_ENUM_NETWORK) {
4576 return enum_all_printers_info_1_network(mem_ctx, session_info,
4577 msg_ctx, servername, info,
4581 return WERR_OK; /* NT4sp5 does that */
4584 /********************************************************************
4585 * handle enumeration of printers at level 2
4586 ********************************************************************/
4588 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4589 const struct auth_session_info *session_info,
4590 struct messaging_context *msg_ctx,
4592 const char *servername,
4593 union spoolss_PrinterInfo **info,
4596 if (flags & PRINTER_ENUM_LOCAL) {
4598 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4603 if (flags & PRINTER_ENUM_NAME) {
4604 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4605 return WERR_INVALID_NAME;
4608 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4613 if (flags & PRINTER_ENUM_REMOTE) {
4614 return WERR_UNKNOWN_LEVEL;
4620 /********************************************************************
4621 * handle enumeration of printers at level 4
4622 ********************************************************************/
4624 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4625 const struct auth_session_info *session_info,
4626 struct messaging_context *msg_ctx,
4628 const char *servername,
4629 union spoolss_PrinterInfo **info,
4632 DEBUG(4,("enum_all_printers_info_4\n"));
4634 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4635 servername, 4, flags, info, count);
4639 /********************************************************************
4640 * handle enumeration of printers at level 5
4641 ********************************************************************/
4643 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4644 const struct auth_session_info *session_info,
4645 struct messaging_context *msg_ctx,
4647 const char *servername,
4648 union spoolss_PrinterInfo **info,
4651 DEBUG(4,("enum_all_printers_info_5\n"));
4653 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4654 servername, 5, flags, info, count);
4657 /****************************************************************
4658 _spoolss_EnumPrinters
4659 ****************************************************************/
4661 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4662 struct spoolss_EnumPrinters *r)
4664 const struct auth_session_info *session_info = get_session_info_system();
4667 /* that's an [in out] buffer */
4669 if (!r->in.buffer && (r->in.offered != 0)) {
4670 return WERR_INVALID_PARAM;
4673 DEBUG(4,("_spoolss_EnumPrinters\n"));
4677 *r->out.info = NULL;
4681 * flags==PRINTER_ENUM_NAME
4682 * if name=="" then enumerates all printers
4683 * if name!="" then enumerate the printer
4684 * flags==PRINTER_ENUM_REMOTE
4685 * name is NULL, enumerate printers
4686 * Level 2: name!="" enumerates printers, name can't be NULL
4687 * Level 3: doesn't exist
4688 * Level 4: does a local registry lookup
4689 * Level 5: same as Level 2
4692 if (r->in.server && r->in.server[0] == '\0') {
4693 r->in.server = NULL;
4696 switch (r->in.level) {
4698 result = enumprinters_level0(p->mem_ctx, session_info,
4699 p->msg_ctx, r->in.flags,
4701 r->out.info, r->out.count);
4704 result = enumprinters_level1(p->mem_ctx, session_info,
4705 p->msg_ctx, r->in.flags,
4707 r->out.info, r->out.count);
4710 result = enumprinters_level2(p->mem_ctx, session_info,
4711 p->msg_ctx, r->in.flags,
4713 r->out.info, r->out.count);
4716 result = enumprinters_level4(p->mem_ctx, session_info,
4717 p->msg_ctx, r->in.flags,
4719 r->out.info, r->out.count);
4722 result = enumprinters_level5(p->mem_ctx, session_info,
4723 p->msg_ctx, r->in.flags,
4725 r->out.info, r->out.count);
4728 return WERR_UNKNOWN_LEVEL;
4731 if (!W_ERROR_IS_OK(result)) {
4735 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4736 spoolss_EnumPrinters,
4737 *r->out.info, r->in.level,
4739 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4740 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4742 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4745 /****************************************************************
4747 ****************************************************************/
4749 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4750 struct spoolss_GetPrinter *r)
4752 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4753 struct spoolss_PrinterInfo2 *info2 = NULL;
4754 WERROR result = WERR_OK;
4757 /* that's an [in out] buffer */
4759 if (!r->in.buffer && (r->in.offered != 0)) {
4760 return WERR_INVALID_PARAM;
4765 if (Printer == NULL) {
4769 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4773 result = winreg_get_printer_internal(p->mem_ctx,
4774 get_session_info_system(),
4776 lp_const_servicename(snum),
4778 if (!W_ERROR_IS_OK(result)) {
4782 switch (r->in.level) {
4784 result = construct_printer_info0(p->mem_ctx,
4785 get_session_info_system(),
4788 Printer->servername,
4789 &r->out.info->info0,
4793 result = construct_printer_info1(p->mem_ctx, info2,
4795 Printer->servername,
4796 &r->out.info->info1, snum);
4799 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4800 Printer->servername,
4801 &r->out.info->info2, snum);
4804 result = construct_printer_info3(p->mem_ctx, info2,
4805 Printer->servername,
4806 &r->out.info->info3, snum);
4809 result = construct_printer_info4(p->mem_ctx, info2,
4810 Printer->servername,
4811 &r->out.info->info4, snum);
4814 result = construct_printer_info5(p->mem_ctx, info2,
4815 Printer->servername,
4816 &r->out.info->info5, snum);
4819 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4820 Printer->servername,
4821 &r->out.info->info6, snum);
4824 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4825 Printer->servername,
4826 &r->out.info->info7, snum);
4829 result = construct_printer_info8(p->mem_ctx, info2,
4830 Printer->servername,
4831 &r->out.info->info8, snum);
4834 result = WERR_UNKNOWN_LEVEL;
4840 if (!W_ERROR_IS_OK(result)) {
4841 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4842 r->in.level, win_errstr(result)));
4843 TALLOC_FREE(r->out.info);
4847 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4848 r->out.info, r->in.level);
4849 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4851 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4854 /********************************************************************
4855 ********************************************************************/
4857 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4859 if (in && strlen(in)) { \
4860 out = talloc_strdup(mem_ctx, in); \
4862 out = talloc_strdup(mem_ctx, ""); \
4864 W_ERROR_HAVE_NO_MEMORY(out); \
4867 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4869 if (in && strlen(in)) { \
4870 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4872 out = talloc_strdup(mem_ctx, ""); \
4874 W_ERROR_HAVE_NO_MEMORY(out); \
4877 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4878 const char **string_array,
4879 const char ***presult,
4880 const char *cservername,
4884 int i, num_strings = 0;
4885 const char **array = NULL;
4887 if (string_array == NULL) {
4888 return WERR_INVALID_PARAMETER;
4891 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4892 const char *str = NULL;
4894 if (cservername == NULL || arch == NULL) {
4895 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4897 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4900 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4907 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4908 &array, &num_strings);
4918 /********************************************************************
4919 * fill a spoolss_DriverInfo1 struct
4920 ********************************************************************/
4922 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4923 struct spoolss_DriverInfo1 *r,
4924 const struct spoolss_DriverInfo8 *driver,
4925 const char *servername)
4927 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4928 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4933 /********************************************************************
4934 * fill a spoolss_DriverInfo2 struct
4935 ********************************************************************/
4937 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4938 struct spoolss_DriverInfo2 *r,
4939 const struct spoolss_DriverInfo8 *driver,
4940 const char *servername)
4943 const char *cservername = canon_servername(servername);
4945 r->version = driver->version;
4947 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4948 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4949 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4950 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4952 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4953 driver->architecture,
4955 driver->driver_path,
4958 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4959 driver->architecture,
4964 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4965 driver->architecture,
4967 driver->config_file,
4973 /********************************************************************
4974 * fill a spoolss_DriverInfo3 struct
4975 ********************************************************************/
4977 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4978 struct spoolss_DriverInfo3 *r,
4979 const struct spoolss_DriverInfo8 *driver,
4980 const char *servername)
4982 const char *cservername = canon_servername(servername);
4984 r->version = driver->version;
4986 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4987 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4988 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4989 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4991 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4992 driver->architecture,
4994 driver->driver_path,
4997 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4998 driver->architecture,
5003 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5004 driver->architecture,
5006 driver->config_file,
5009 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5010 driver->architecture,
5015 FILL_DRIVER_STRING(mem_ctx,
5016 driver->monitor_name,
5019 FILL_DRIVER_STRING(mem_ctx,
5020 driver->default_datatype,
5021 r->default_datatype);
5023 return string_array_from_driver_info(mem_ctx,
5024 driver->dependent_files,
5025 &r->dependent_files,
5027 driver->architecture,
5031 /********************************************************************
5032 * fill a spoolss_DriverInfo4 struct
5033 ********************************************************************/
5035 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5036 struct spoolss_DriverInfo4 *r,
5037 const struct spoolss_DriverInfo8 *driver,
5038 const char *servername)
5040 const char *cservername = canon_servername(servername);
5043 r->version = driver->version;
5045 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5046 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5047 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5048 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5050 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5051 driver->architecture,
5053 driver->driver_path,
5056 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5057 driver->architecture,
5062 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5063 driver->architecture,
5065 driver->config_file,
5068 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5069 driver->architecture,
5074 result = string_array_from_driver_info(mem_ctx,
5075 driver->dependent_files,
5076 &r->dependent_files,
5078 driver->architecture,
5080 if (!W_ERROR_IS_OK(result)) {
5084 FILL_DRIVER_STRING(mem_ctx,
5085 driver->monitor_name,
5088 FILL_DRIVER_STRING(mem_ctx,
5089 driver->default_datatype,
5090 r->default_datatype);
5093 result = string_array_from_driver_info(mem_ctx,
5094 driver->previous_names,
5101 /********************************************************************
5102 * fill a spoolss_DriverInfo5 struct
5103 ********************************************************************/
5105 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5106 struct spoolss_DriverInfo5 *r,
5107 const struct spoolss_DriverInfo8 *driver,
5108 const char *servername)
5110 const char *cservername = canon_servername(servername);
5112 r->version = driver->version;
5114 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5115 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5116 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5117 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5119 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5120 driver->architecture,
5122 driver->driver_path,
5125 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5126 driver->architecture,
5131 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5132 driver->architecture,
5134 driver->config_file,
5137 r->driver_attributes = 0;
5138 r->config_version = 0;
5139 r->driver_version = 0;
5143 /********************************************************************
5144 * fill a spoolss_DriverInfo6 struct
5145 ********************************************************************/
5147 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5148 struct spoolss_DriverInfo6 *r,
5149 const struct spoolss_DriverInfo8 *driver,
5150 const char *servername)
5152 const char *cservername = canon_servername(servername);
5155 r->version = driver->version;
5157 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5158 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5159 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5160 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5162 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5163 driver->architecture,
5165 driver->driver_path,
5168 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5169 driver->architecture,
5174 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5175 driver->architecture,
5177 driver->config_file,
5180 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5181 driver->architecture,
5186 FILL_DRIVER_STRING(mem_ctx,
5187 driver->monitor_name,
5190 FILL_DRIVER_STRING(mem_ctx,
5191 driver->default_datatype,
5192 r->default_datatype);
5194 result = string_array_from_driver_info(mem_ctx,
5195 driver->dependent_files,
5196 &r->dependent_files,
5198 driver->architecture,
5200 if (!W_ERROR_IS_OK(result)) {
5204 result = string_array_from_driver_info(mem_ctx,
5205 driver->previous_names,
5208 if (!W_ERROR_IS_OK(result)) {
5212 r->driver_date = driver->driver_date;
5213 r->driver_version = driver->driver_version;
5215 FILL_DRIVER_STRING(mem_ctx,
5216 driver->manufacturer_name,
5217 r->manufacturer_name);
5218 FILL_DRIVER_STRING(mem_ctx,
5219 driver->manufacturer_url,
5220 r->manufacturer_url);
5221 FILL_DRIVER_STRING(mem_ctx,
5222 driver->hardware_id,
5224 FILL_DRIVER_STRING(mem_ctx,
5231 /********************************************************************
5232 * fill a spoolss_DriverInfo8 struct
5233 ********************************************************************/
5235 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5236 struct spoolss_DriverInfo8 *r,
5237 const struct spoolss_DriverInfo8 *driver,
5238 const char *servername)
5240 const char *cservername = canon_servername(servername);
5243 r->version = driver->version;
5245 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5246 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5247 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5248 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5250 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5251 driver->architecture,
5253 driver->driver_path,
5256 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5257 driver->architecture,
5262 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5263 driver->architecture,
5265 driver->config_file,
5268 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5269 driver->architecture,
5274 FILL_DRIVER_STRING(mem_ctx,
5275 driver->monitor_name,
5278 FILL_DRIVER_STRING(mem_ctx,
5279 driver->default_datatype,
5280 r->default_datatype);
5282 result = string_array_from_driver_info(mem_ctx,
5283 driver->dependent_files,
5284 &r->dependent_files,
5286 driver->architecture,
5288 if (!W_ERROR_IS_OK(result)) {
5292 result = string_array_from_driver_info(mem_ctx,
5293 driver->previous_names,
5296 if (!W_ERROR_IS_OK(result)) {
5300 r->driver_date = driver->driver_date;
5301 r->driver_version = driver->driver_version;
5303 FILL_DRIVER_STRING(mem_ctx,
5304 driver->manufacturer_name,
5305 r->manufacturer_name);
5306 FILL_DRIVER_STRING(mem_ctx,
5307 driver->manufacturer_url,
5308 r->manufacturer_url);
5309 FILL_DRIVER_STRING(mem_ctx,
5310 driver->hardware_id,
5312 FILL_DRIVER_STRING(mem_ctx,
5316 FILL_DRIVER_STRING(mem_ctx,
5317 driver->print_processor,
5318 r->print_processor);
5319 FILL_DRIVER_STRING(mem_ctx,
5320 driver->vendor_setup,
5323 result = string_array_from_driver_info(mem_ctx,
5324 driver->color_profiles,
5327 if (!W_ERROR_IS_OK(result)) {
5331 FILL_DRIVER_STRING(mem_ctx,
5335 r->printer_driver_attributes = driver->printer_driver_attributes;
5337 result = string_array_from_driver_info(mem_ctx,
5338 driver->core_driver_dependencies,
5339 &r->core_driver_dependencies,
5341 if (!W_ERROR_IS_OK(result)) {
5345 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5346 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5351 #if 0 /* disabled until marshalling issues are resolved - gd */
5352 /********************************************************************
5353 ********************************************************************/
5355 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5356 struct spoolss_DriverFileInfo *r,
5357 const char *cservername,
5358 const char *file_name,
5359 enum spoolss_DriverFileType file_type,
5360 uint32_t file_version)
5362 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5363 cservername, file_name);
5364 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5365 r->file_type = file_type;
5366 r->file_version = file_version;
5371 /********************************************************************
5372 ********************************************************************/
5374 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5375 const struct spoolss_DriverInfo8 *driver,
5376 const char *cservername,
5377 struct spoolss_DriverFileInfo **info_p,
5380 struct spoolss_DriverFileInfo *info = NULL;
5388 if (strlen(driver->driver_path)) {
5389 info = talloc_realloc(mem_ctx, info,
5390 struct spoolss_DriverFileInfo,
5392 W_ERROR_HAVE_NO_MEMORY(info);
5393 result = fill_spoolss_DriverFileInfo(info,
5396 driver->driver_path,
5397 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5399 W_ERROR_NOT_OK_RETURN(result);
5403 if (strlen(driver->config_file)) {
5404 info = talloc_realloc(mem_ctx, info,
5405 struct spoolss_DriverFileInfo,
5407 W_ERROR_HAVE_NO_MEMORY(info);
5408 result = fill_spoolss_DriverFileInfo(info,
5411 driver->config_file,
5412 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5414 W_ERROR_NOT_OK_RETURN(result);
5418 if (strlen(driver->data_file)) {
5419 info = talloc_realloc(mem_ctx, info,
5420 struct spoolss_DriverFileInfo,
5422 W_ERROR_HAVE_NO_MEMORY(info);
5423 result = fill_spoolss_DriverFileInfo(info,
5427 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5429 W_ERROR_NOT_OK_RETURN(result);
5433 if (strlen(driver->help_file)) {
5434 info = talloc_realloc(mem_ctx, info,
5435 struct spoolss_DriverFileInfo,
5437 W_ERROR_HAVE_NO_MEMORY(info);
5438 result = fill_spoolss_DriverFileInfo(info,
5442 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5444 W_ERROR_NOT_OK_RETURN(result);
5448 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5449 info = talloc_realloc(mem_ctx, info,
5450 struct spoolss_DriverFileInfo,
5452 W_ERROR_HAVE_NO_MEMORY(info);
5453 result = fill_spoolss_DriverFileInfo(info,
5456 driver->dependent_files[i],
5457 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5459 W_ERROR_NOT_OK_RETURN(result);
5469 /********************************************************************
5470 * fill a spoolss_DriverInfo101 struct
5471 ********************************************************************/
5473 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5474 struct spoolss_DriverInfo101 *r,
5475 const struct spoolss_DriverInfo8 *driver,
5476 const char *servername)
5478 const char *cservername = canon_servername(servername);
5481 r->version = driver->version;
5483 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5484 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5485 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5486 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5488 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5492 if (!W_ERROR_IS_OK(result)) {
5496 FILL_DRIVER_STRING(mem_ctx,
5497 driver->monitor_name,
5500 FILL_DRIVER_STRING(mem_ctx,
5501 driver->default_datatype,
5502 r->default_datatype);
5504 result = string_array_from_driver_info(mem_ctx,
5505 driver->previous_names,
5508 if (!W_ERROR_IS_OK(result)) {
5512 r->driver_date = driver->driver_date;
5513 r->driver_version = driver->driver_version;
5515 FILL_DRIVER_STRING(mem_ctx,
5516 driver->manufacturer_name,
5517 r->manufacturer_name);
5518 FILL_DRIVER_STRING(mem_ctx,
5519 driver->manufacturer_url,
5520 r->manufacturer_url);
5521 FILL_DRIVER_STRING(mem_ctx,
5522 driver->hardware_id,
5524 FILL_DRIVER_STRING(mem_ctx,
5531 /********************************************************************
5532 ********************************************************************/
5534 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5535 const struct auth_session_info *session_info,
5536 struct messaging_context *msg_ctx,
5538 union spoolss_DriverInfo *r,
5540 const char *servername,
5541 const char *architecture,
5544 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5545 struct spoolss_DriverInfo8 *driver;
5547 struct dcerpc_binding_handle *b;
5548 TALLOC_CTX *tmp_ctx = NULL;
5551 return WERR_UNKNOWN_LEVEL;
5554 tmp_ctx = talloc_new(mem_ctx);
5559 result = winreg_printer_binding_handle(tmp_ctx,
5563 if (!W_ERROR_IS_OK(result)) {
5567 result = winreg_get_printer(tmp_ctx, b,
5568 lp_const_servicename(snum),
5571 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5572 win_errstr(result)));
5574 if (!W_ERROR_IS_OK(result)) {
5575 result = WERR_INVALID_PRINTER_NAME;
5579 result = winreg_get_driver(tmp_ctx, b,
5581 pinfo2->drivername, version, &driver);
5583 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5584 win_errstr(result)));
5586 if (!W_ERROR_IS_OK(result)) {
5588 * Is this a W2k client ?
5592 result = WERR_UNKNOWN_PRINTER_DRIVER;
5596 /* Yes - try again with a WinNT driver. */
5598 result = winreg_get_driver(tmp_ctx, b,
5602 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5603 win_errstr(result)));
5604 if (!W_ERROR_IS_OK(result)) {
5605 result = WERR_UNKNOWN_PRINTER_DRIVER;
5610 /* these are allocated on mem_ctx and not tmp_ctx because they are
5611 * the 'return value' and need to utlive this call */
5614 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5617 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5620 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5623 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5626 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5629 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5632 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5634 #if 0 /* disabled until marshalling issues are resolved - gd */
5636 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5640 result = WERR_UNKNOWN_LEVEL;
5645 talloc_free(tmp_ctx);
5649 /****************************************************************
5650 _spoolss_GetPrinterDriver2
5651 ****************************************************************/
5653 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5654 struct spoolss_GetPrinterDriver2 *r)
5656 struct printer_handle *printer;
5661 /* that's an [in out] buffer */
5663 if (!r->in.buffer && (r->in.offered != 0)) {
5664 return WERR_INVALID_PARAM;
5667 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5669 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5670 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5671 return WERR_INVALID_PRINTER_NAME;
5675 *r->out.server_major_version = 0;
5676 *r->out.server_minor_version = 0;
5678 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5682 result = construct_printer_driver_info_level(p->mem_ctx,
5683 get_session_info_system(),
5685 r->in.level, r->out.info,
5686 snum, printer->servername,
5688 r->in.client_major_version);
5689 if (!W_ERROR_IS_OK(result)) {
5690 TALLOC_FREE(r->out.info);
5694 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5695 r->out.info, r->in.level);
5696 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5698 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5702 /****************************************************************
5703 _spoolss_StartPagePrinter
5704 ****************************************************************/
5706 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5707 struct spoolss_StartPagePrinter *r)
5709 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5712 DEBUG(3,("_spoolss_StartPagePrinter: "
5713 "Error in startpageprinter printer handle\n"));
5717 Printer->page_started = true;
5721 /****************************************************************
5722 _spoolss_EndPagePrinter
5723 ****************************************************************/
5725 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5726 struct spoolss_EndPagePrinter *r)
5730 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5733 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5734 OUR_HANDLE(r->in.handle)));
5738 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5741 Printer->page_started = false;
5742 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5747 /****************************************************************
5748 _spoolss_StartDocPrinter
5749 ****************************************************************/
5751 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5752 struct spoolss_StartDocPrinter *r)
5754 struct spoolss_DocumentInfo1 *info_1;
5756 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5762 DEBUG(2,("_spoolss_StartDocPrinter: "
5763 "Invalid handle (%s:%u:%u)\n",
5764 OUR_HANDLE(r->in.handle)));
5768 if (Printer->jobid) {
5769 DEBUG(2, ("_spoolss_StartDocPrinter: "
5770 "StartDocPrinter called twice! "
5771 "(existing jobid = %d)\n", Printer->jobid));
5772 return WERR_INVALID_HANDLE;
5775 if (r->in.level != 1) {
5776 return WERR_UNKNOWN_LEVEL;
5779 info_1 = r->in.info.info1;
5782 * a nice thing with NT is it doesn't listen to what you tell it.
5783 * when asked to send _only_ RAW datas, it tries to send datas
5786 * So I add checks like in NT Server ...
5789 if (info_1->datatype) {
5790 if (strcmp(info_1->datatype, "RAW") != 0) {
5792 return WERR_INVALID_DATATYPE;
5796 /* get the share number of the printer */
5797 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5801 rc = get_remote_hostname(p->remote_address,
5807 if (strequal(rhost,"UNKNOWN")) {
5808 rhost = tsocket_address_inet_addr_string(p->remote_address,
5810 if (rhost == NULL) {
5815 werr = print_job_start(p->session_info,
5819 info_1->document_name,
5820 info_1->output_file,
5824 /* An error occured in print_job_start() so return an appropriate
5827 if (!W_ERROR_IS_OK(werr)) {
5831 Printer->document_started = true;
5832 *r->out.job_id = Printer->jobid;
5837 /****************************************************************
5838 _spoolss_EndDocPrinter
5839 ****************************************************************/
5841 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5842 struct spoolss_EndDocPrinter *r)
5844 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5849 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5850 OUR_HANDLE(r->in.handle)));
5854 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5858 Printer->document_started = false;
5859 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5860 if (!NT_STATUS_IS_OK(status)) {
5861 DEBUG(2, ("_spoolss_EndDocPrinter: "
5862 "print_job_end failed [%s]\n",
5863 nt_errstr(status)));
5867 return ntstatus_to_werror(status);
5870 /****************************************************************
5871 _spoolss_WritePrinter
5872 ****************************************************************/
5874 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5875 struct spoolss_WritePrinter *r)
5877 ssize_t buffer_written;
5879 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5882 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5883 OUR_HANDLE(r->in.handle)));
5884 *r->out.num_written = r->in._data_size;
5888 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5891 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5892 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5893 snum, Printer->jobid,
5894 (const char *)r->in.data.data,
5895 (size_t)r->in._data_size);
5896 if (buffer_written == (ssize_t)-1) {
5897 *r->out.num_written = 0;
5898 if (errno == ENOSPC)
5899 return WERR_NO_SPOOL_SPACE;
5901 return WERR_ACCESS_DENIED;
5904 *r->out.num_written = r->in._data_size;
5909 /********************************************************************
5910 * api_spoolss_getprinter
5911 * called from the spoolss dispatcher
5913 ********************************************************************/
5915 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5916 struct pipes_struct *p)
5918 const struct auth_session_info *session_info = p->session_info;
5920 WERROR errcode = WERR_BADFUNC;
5921 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5924 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5925 OUR_HANDLE(handle)));
5929 if (!get_printer_snum(p, handle, &snum, NULL))
5933 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5934 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5936 case SPOOLSS_PRINTER_CONTROL_RESUME:
5937 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5938 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5940 case SPOOLSS_PRINTER_CONTROL_PURGE:
5941 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5944 return WERR_UNKNOWN_LEVEL;
5951 /****************************************************************
5952 _spoolss_AbortPrinter
5953 * From MSDN: "Deletes printer's spool file if printer is configured
5955 ****************************************************************/
5957 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5958 struct spoolss_AbortPrinter *r)
5960 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5962 WERROR errcode = WERR_OK;
5965 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5966 OUR_HANDLE(r->in.handle)));
5970 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5973 if (!Printer->document_started) {
5974 return WERR_SPL_NO_STARTDOC;
5977 errcode = print_job_delete(p->session_info,
5985 /********************************************************************
5986 * called by spoolss_api_setprinter
5987 * when updating a printer description
5988 ********************************************************************/
5990 static WERROR update_printer_sec(struct policy_handle *handle,
5991 struct pipes_struct *p,
5992 struct sec_desc_buf *secdesc_ctr)
5994 struct spoolss_security_descriptor *new_secdesc = NULL;
5995 struct spoolss_security_descriptor *old_secdesc = NULL;
5996 const char *printer;
5999 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6000 struct dcerpc_binding_handle *b;
6001 TALLOC_CTX *tmp_ctx = NULL;
6003 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6004 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6005 OUR_HANDLE(handle)));
6007 result = WERR_BADFID;
6011 if (secdesc_ctr == NULL) {
6012 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6013 result = WERR_INVALID_PARAM;
6016 printer = lp_const_servicename(snum);
6018 /* Check the user has permissions to change the security
6019 descriptor. By experimentation with two NT machines, the user
6020 requires Full Access to the printer to change security
6023 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6024 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6025 result = WERR_ACCESS_DENIED;
6029 tmp_ctx = talloc_new(p->mem_ctx);
6034 result = winreg_printer_binding_handle(tmp_ctx,
6035 get_session_info_system(),
6038 if (!W_ERROR_IS_OK(result)) {
6042 /* NT seems to like setting the security descriptor even though
6043 nothing may have actually changed. */
6044 result = winreg_get_printer_secdesc(tmp_ctx, b,
6047 if (!W_ERROR_IS_OK(result)) {
6048 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6049 result = WERR_BADFID;
6053 if (DEBUGLEVEL >= 10) {
6054 struct security_acl *the_acl;
6057 the_acl = old_secdesc->dacl;
6058 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6059 printer, the_acl->num_aces));
6061 for (i = 0; i < the_acl->num_aces; i++) {
6062 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6063 &the_acl->aces[i].trustee),
6064 the_acl->aces[i].access_mask));
6067 the_acl = secdesc_ctr->sd->dacl;
6070 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6071 printer, the_acl->num_aces));
6073 for (i = 0; i < the_acl->num_aces; i++) {
6074 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6075 &the_acl->aces[i].trustee),
6076 the_acl->aces[i].access_mask));
6079 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6083 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6084 if (new_secdesc == NULL) {
6085 result = WERR_NOMEM;
6089 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6094 result = winreg_set_printer_secdesc(tmp_ctx, b,
6099 talloc_free(tmp_ctx);
6103 /********************************************************************
6104 Canonicalize printer info from a client
6105 ********************************************************************/
6107 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6108 struct spoolss_SetPrinterInfo2 *info2,
6111 fstring printername;
6114 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6115 "portname=%s drivername=%s comment=%s location=%s\n",
6116 info2->servername, info2->printername, info2->sharename,
6117 info2->portname, info2->drivername, info2->comment,
6120 /* we force some elements to "correct" values */
6121 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6122 if (info2->servername == NULL) {
6125 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6126 if (info2->sharename == NULL) {
6130 /* check to see if we allow printername != sharename */
6131 if (lp_force_printername(snum)) {
6132 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6133 lp_netbios_name(), info2->sharename);
6135 /* make sure printername is in \\server\printername format */
6136 fstrcpy(printername, info2->printername);
6138 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6139 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6143 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6144 lp_netbios_name(), p);
6146 if (info2->printername == NULL) {
6150 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6151 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6156 /****************************************************************************
6157 ****************************************************************************/
6159 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6161 char *cmd = lp_addport_cmd();
6162 char *command = NULL;
6164 bool is_print_op = false;
6167 return WERR_ACCESS_DENIED;
6170 command = talloc_asprintf(ctx,
6171 "%s \"%s\" \"%s\"", cmd, portname, uri );
6177 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6179 DEBUG(10,("Running [%s]\n", command));
6181 /********* BEGIN SePrintOperatorPrivilege **********/
6186 ret = smbrun(command, NULL);
6191 /********* END SePrintOperatorPrivilege **********/
6193 DEBUGADD(10,("returned [%d]\n", ret));
6195 TALLOC_FREE(command);
6198 return WERR_ACCESS_DENIED;
6204 /****************************************************************************
6205 ****************************************************************************/
6207 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6208 struct spoolss_SetPrinterInfo2 *info2,
6209 const char *remote_machine,
6210 struct messaging_context *msg_ctx)
6212 char *cmd = lp_addprinter_cmd();
6214 char *command = NULL;
6218 bool is_print_op = false;
6220 if (!remote_machine) {
6224 command = talloc_asprintf(ctx,
6225 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6226 cmd, info2->printername, info2->sharename,
6227 info2->portname, info2->drivername,
6228 info2->location, info2->comment, remote_machine);
6234 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6236 DEBUG(10,("Running [%s]\n", command));
6238 /********* BEGIN SePrintOperatorPrivilege **********/
6243 if ( (ret = smbrun(command, &fd)) == 0 ) {
6244 /* Tell everyone we updated smb.conf. */
6245 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6251 /********* END SePrintOperatorPrivilege **********/
6253 DEBUGADD(10,("returned [%d]\n", ret));
6255 TALLOC_FREE(command);
6263 /* reload our services immediately */
6265 reload_services(msg_ctx, -1, false);
6269 /* Get lines and convert them back to dos-codepage */
6270 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6271 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6274 /* Set the portname to what the script says the portname should be. */
6275 /* but don't require anything to be return from the script exit a good error code */
6278 /* Set the portname to what the script says the portname should be. */
6279 info2->portname = talloc_strdup(ctx, qlines[0]);
6280 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6283 TALLOC_FREE(qlines);
6287 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6288 const struct auth_session_info *session_info,
6289 struct messaging_context *msg_ctx,
6291 struct spoolss_SetPrinterInfo2 *printer,
6292 struct spoolss_PrinterInfo2 *old_printer)
6294 bool force_update = (old_printer == NULL);
6295 const char *dnsdomname;
6296 const char *longname;
6297 const char *uncname;
6298 const char *spooling;
6300 WERROR result = WERR_OK;
6301 struct dcerpc_binding_handle *b;
6302 TALLOC_CTX *tmp_ctx;
6304 tmp_ctx = talloc_new(mem_ctx);
6309 result = winreg_printer_binding_handle(tmp_ctx,
6313 if (!W_ERROR_IS_OK(result)) {
6317 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6318 push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6319 winreg_set_printer_dataex(tmp_ctx, b,
6321 SPOOL_DSSPOOLER_KEY,
6322 SPOOL_REG_DRIVERNAME,
6327 if (!force_update) {
6328 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6329 printer->drivername));
6331 notify_printer_driver(server_event_context(), msg_ctx,
6332 snum, printer->drivername ?
6333 printer->drivername : "");
6337 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6338 push_reg_sz(tmp_ctx, &buffer, printer->comment);
6339 winreg_set_printer_dataex(tmp_ctx, b,
6341 SPOOL_DSSPOOLER_KEY,
6342 SPOOL_REG_DESCRIPTION,
6347 if (!force_update) {
6348 notify_printer_comment(server_event_context(), msg_ctx,
6349 snum, printer->comment ?
6350 printer->comment : "");
6354 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6355 push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6356 winreg_set_printer_dataex(tmp_ctx, b,
6358 SPOOL_DSSPOOLER_KEY,
6359 SPOOL_REG_PRINTSHARENAME,
6364 if (!force_update) {
6365 notify_printer_sharename(server_event_context(),
6367 snum, printer->sharename ?
6368 printer->sharename : "");
6372 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6375 p = strrchr(printer->printername, '\\' );
6379 p = printer->printername;
6382 push_reg_sz(tmp_ctx, &buffer, p);
6383 winreg_set_printer_dataex(tmp_ctx, b,
6385 SPOOL_DSSPOOLER_KEY,
6386 SPOOL_REG_PRINTERNAME,
6391 if (!force_update) {
6392 notify_printer_printername(server_event_context(),
6393 msg_ctx, snum, p ? p : "");
6397 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6398 push_reg_sz(tmp_ctx, &buffer, printer->portname);
6399 winreg_set_printer_dataex(tmp_ctx, b,
6401 SPOOL_DSSPOOLER_KEY,
6407 if (!force_update) {
6408 notify_printer_port(server_event_context(),
6409 msg_ctx, snum, printer->portname ?
6410 printer->portname : "");
6414 if (force_update || !strequal(printer->location, old_printer->location)) {
6415 push_reg_sz(tmp_ctx, &buffer, printer->location);
6416 winreg_set_printer_dataex(tmp_ctx, b,
6418 SPOOL_DSSPOOLER_KEY,
6424 if (!force_update) {
6425 notify_printer_location(server_event_context(),
6428 printer->location : "");
6432 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6433 push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6434 winreg_set_printer_dataex(tmp_ctx, b,
6436 SPOOL_DSSPOOLER_KEY,
6437 SPOOL_REG_PRINTSEPARATORFILE,
6442 if (!force_update) {
6443 notify_printer_sepfile(server_event_context(),
6446 printer->sepfile : "");
6450 if (force_update || printer->starttime != old_printer->starttime) {
6451 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6452 SIVAL(buffer.data, 0, printer->starttime);
6453 winreg_set_printer_dataex(tmp_ctx, b,
6455 SPOOL_DSSPOOLER_KEY,
6456 SPOOL_REG_PRINTSTARTTIME,
6462 if (force_update || printer->untiltime != old_printer->untiltime) {
6463 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6464 SIVAL(buffer.data, 0, printer->untiltime);
6465 winreg_set_printer_dataex(tmp_ctx, b,
6467 SPOOL_DSSPOOLER_KEY,
6468 SPOOL_REG_PRINTENDTIME,
6474 if (force_update || printer->priority != old_printer->priority) {
6475 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6476 SIVAL(buffer.data, 0, printer->priority);
6477 winreg_set_printer_dataex(tmp_ctx, b,
6479 SPOOL_DSSPOOLER_KEY,
6486 if (force_update || printer->attributes != old_printer->attributes) {
6487 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6488 SIVAL(buffer.data, 0, (printer->attributes &
6489 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6490 winreg_set_printer_dataex(tmp_ctx, b,
6492 SPOOL_DSSPOOLER_KEY,
6493 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6498 switch (printer->attributes & 0x3) {
6500 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6503 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6506 spooling = SPOOL_REGVAL_PRINTDIRECT;
6509 spooling = "unknown";
6511 push_reg_sz(tmp_ctx, &buffer, spooling);
6512 winreg_set_printer_dataex(tmp_ctx, b,
6514 SPOOL_DSSPOOLER_KEY,
6515 SPOOL_REG_PRINTSPOOLING,
6521 push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6522 winreg_set_printer_dataex(tmp_ctx, b,
6524 SPOOL_DSSPOOLER_KEY,
6525 SPOOL_REG_SHORTSERVERNAME,
6530 dnsdomname = get_mydnsfullname();
6531 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6532 longname = talloc_strdup(tmp_ctx, dnsdomname);
6534 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6536 if (longname == NULL) {
6537 result = WERR_NOMEM;
6541 push_reg_sz(tmp_ctx, &buffer, longname);
6542 winreg_set_printer_dataex(tmp_ctx, b,
6544 SPOOL_DSSPOOLER_KEY,
6545 SPOOL_REG_SERVERNAME,
6550 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6551 lp_netbios_name(), printer->sharename);
6552 push_reg_sz(tmp_ctx, &buffer, uncname);
6553 winreg_set_printer_dataex(tmp_ctx, b,
6555 SPOOL_DSSPOOLER_KEY,
6562 talloc_free(tmp_ctx);
6566 /********************************************************************
6567 * Called by spoolss_api_setprinter
6568 * when updating a printer description.
6569 ********************************************************************/
6571 static WERROR update_printer(struct pipes_struct *p,
6572 struct policy_handle *handle,
6573 struct spoolss_SetPrinterInfoCtr *info_ctr,
6574 struct spoolss_DeviceMode *devmode)
6576 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6577 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6578 struct spoolss_PrinterInfo2 *old_printer;
6579 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6581 WERROR result = WERR_OK;
6582 TALLOC_CTX *tmp_ctx;
6583 struct dcerpc_binding_handle *b;
6585 DEBUG(8,("update_printer\n"));
6587 tmp_ctx = talloc_new(p->mem_ctx);
6588 if (tmp_ctx == NULL) {
6593 result = WERR_BADFID;
6597 if (!get_printer_snum(p, handle, &snum, NULL)) {
6598 result = WERR_BADFID;
6602 result = winreg_printer_binding_handle(tmp_ctx,
6603 get_session_info_system(),
6606 if (!W_ERROR_IS_OK(result)) {
6610 result = winreg_get_printer(tmp_ctx, b,
6611 lp_const_servicename(snum),
6613 if (!W_ERROR_IS_OK(result)) {
6614 result = WERR_BADFID;
6618 /* Do sanity check on the requested changes for Samba */
6619 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6620 result = WERR_INVALID_PARAM;
6624 /* FIXME!!! If the driver has changed we really should verify that
6625 it is installed before doing much else --jerry */
6627 /* Check calling user has permission to update printer description */
6628 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6629 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6630 result = WERR_ACCESS_DENIED;
6634 /* Call addprinter hook */
6635 /* Check changes to see if this is really needed */
6637 if (*lp_addprinter_cmd() &&
6638 (!strequal(printer->drivername, old_printer->drivername) ||
6639 !strequal(printer->comment, old_printer->comment) ||
6640 !strequal(printer->portname, old_printer->portname) ||
6641 !strequal(printer->location, old_printer->location)) )
6645 raddr = tsocket_address_inet_addr_string(p->remote_address,
6647 if (raddr == NULL) {
6651 /* add_printer_hook() will call reload_services() */
6652 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6655 result = WERR_ACCESS_DENIED;
6660 update_dsspooler(tmp_ctx,
6661 get_session_info_system(),
6667 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6669 if (devmode == NULL) {
6670 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6672 result = winreg_update_printer(tmp_ctx, b,
6680 talloc_free(tmp_ctx);
6685 /****************************************************************************
6686 ****************************************************************************/
6687 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6688 struct policy_handle *handle,
6689 struct spoolss_SetPrinterInfo7 *info7)
6692 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6695 struct printer_handle *Printer;
6697 if ( lp_security() != SEC_ADS ) {
6698 return WERR_UNKNOWN_LEVEL;
6701 Printer = find_printer_index_by_hnd(p, handle);
6703 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6708 if (!get_printer_snum(p, handle, &snum, NULL))
6711 result = winreg_get_printer_internal(p->mem_ctx,
6712 get_session_info_system(),
6714 lp_servicename(snum),
6716 if (!W_ERROR_IS_OK(result)) {
6720 nt_printer_publish(pinfo2,
6721 get_session_info_system(),
6726 TALLOC_FREE(pinfo2);
6729 return WERR_UNKNOWN_LEVEL;
6733 /********************************************************************
6734 ********************************************************************/
6736 static WERROR update_printer_devmode(struct pipes_struct *p,
6737 struct policy_handle *handle,
6738 struct spoolss_DeviceMode *devmode)
6741 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6742 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6744 DEBUG(8,("update_printer_devmode\n"));
6750 if (!get_printer_snum(p, handle, &snum, NULL)) {
6754 /* Check calling user has permission to update printer description */
6755 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6756 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6757 return WERR_ACCESS_DENIED;
6760 return winreg_update_printer_internal(p->mem_ctx,
6761 get_session_info_system(),
6763 lp_const_servicename(snum),
6771 /****************************************************************
6773 ****************************************************************/
6775 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6776 struct spoolss_SetPrinter *r)
6780 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6783 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6784 OUR_HANDLE(r->in.handle)));
6788 /* check the level */
6789 switch (r->in.info_ctr->level) {
6791 return control_printer(r->in.handle, r->in.command, p);
6793 result = update_printer(p, r->in.handle,
6795 r->in.devmode_ctr->devmode);
6796 if (!W_ERROR_IS_OK(result))
6798 if (r->in.secdesc_ctr->sd)
6799 result = update_printer_sec(r->in.handle, p,
6803 return update_printer_sec(r->in.handle, p,
6806 return publish_or_unpublish_printer(p, r->in.handle,
6807 r->in.info_ctr->info.info7);
6809 return update_printer_devmode(p, r->in.handle,
6810 r->in.devmode_ctr->devmode);
6812 return WERR_UNKNOWN_LEVEL;
6816 /****************************************************************
6817 _spoolss_FindClosePrinterNotify
6818 ****************************************************************/
6820 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6821 struct spoolss_FindClosePrinterNotify *r)
6823 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6826 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6827 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6831 if (Printer->notify.cli_chan != NULL &&
6832 Printer->notify.cli_chan->active_connections > 0) {
6835 if (Printer->printer_type == SPLHND_PRINTER) {
6836 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6841 srv_spoolss_replycloseprinter(snum, Printer);
6844 Printer->notify.flags=0;
6845 Printer->notify.options=0;
6846 Printer->notify.localmachine[0]='\0';
6847 Printer->notify.printerlocal=0;
6848 TALLOC_FREE(Printer->notify.option);
6853 /****************************************************************
6855 ****************************************************************/
6857 WERROR _spoolss_AddJob(struct pipes_struct *p,
6858 struct spoolss_AddJob *r)
6860 if (!r->in.buffer && (r->in.offered != 0)) {
6861 return WERR_INVALID_PARAM;
6864 /* this is what a NT server returns for AddJob. AddJob must fail on
6865 * non-local printers */
6867 if (r->in.level != 1) {
6868 return WERR_UNKNOWN_LEVEL;
6871 return WERR_INVALID_PARAM;
6874 /****************************************************************************
6876 ****************************************************************************/
6878 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6879 struct spoolss_JobInfo1 *r,
6880 const print_queue_struct *queue,
6881 int position, int snum,
6882 struct spoolss_PrinterInfo2 *pinfo2)
6886 t = gmtime(&queue->time);
6888 r->job_id = queue->job;
6890 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6891 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6892 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6893 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6894 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6895 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6896 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6897 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6898 r->data_type = talloc_strdup(mem_ctx, "RAW");
6899 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6900 r->text_status = talloc_strdup(mem_ctx, "");
6901 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6903 r->status = nt_printj_status(queue->status);
6904 r->priority = queue->priority;
6905 r->position = position;
6906 r->total_pages = queue->page_count;
6907 r->pages_printed = 0; /* ??? */
6909 init_systemtime(&r->submitted, t);
6914 /****************************************************************************
6916 ****************************************************************************/
6918 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6919 struct spoolss_JobInfo2 *r,
6920 const print_queue_struct *queue,
6921 int position, int snum,
6922 struct spoolss_PrinterInfo2 *pinfo2,
6923 struct spoolss_DeviceMode *devmode)
6927 t = gmtime(&queue->time);
6929 r->job_id = queue->job;
6931 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6932 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6933 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6934 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6935 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6936 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6937 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6938 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6939 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6940 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6941 r->data_type = talloc_strdup(mem_ctx, "RAW");
6942 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6943 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6944 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6945 r->parameters = talloc_strdup(mem_ctx, "");
6946 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6947 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6948 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6950 r->devmode = devmode;
6952 r->text_status = talloc_strdup(mem_ctx, "");
6953 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6957 r->status = nt_printj_status(queue->status);
6958 r->priority = queue->priority;
6959 r->position = position;
6962 r->total_pages = queue->page_count;
6963 r->size = queue->size;
6964 init_systemtime(&r->submitted, t);
6966 r->pages_printed = 0; /* ??? */
6971 /****************************************************************************
6973 ****************************************************************************/
6975 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6976 struct spoolss_JobInfo3 *r,
6977 const print_queue_struct *queue,
6978 const print_queue_struct *next_queue,
6979 int position, int snum,
6980 struct spoolss_PrinterInfo2 *pinfo2)
6982 r->job_id = queue->job;
6985 r->next_job_id = next_queue->job;
6992 /****************************************************************************
6993 Enumjobs at level 1.
6994 ****************************************************************************/
6996 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6997 const print_queue_struct *queue,
6998 uint32_t num_queues, int snum,
6999 struct spoolss_PrinterInfo2 *pinfo2,
7000 union spoolss_JobInfo **info_p,
7003 union spoolss_JobInfo *info;
7005 WERROR result = WERR_OK;
7007 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7008 W_ERROR_HAVE_NO_MEMORY(info);
7010 *count = num_queues;
7012 for (i=0; i<*count; i++) {
7013 result = fill_job_info1(info,
7019 if (!W_ERROR_IS_OK(result)) {
7025 if (!W_ERROR_IS_OK(result)) {
7036 /****************************************************************************
7037 Enumjobs at level 2.
7038 ****************************************************************************/
7040 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7041 const print_queue_struct *queue,
7042 uint32_t num_queues, int snum,
7043 struct spoolss_PrinterInfo2 *pinfo2,
7044 union spoolss_JobInfo **info_p,
7047 union spoolss_JobInfo *info;
7049 WERROR result = WERR_OK;
7051 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7052 W_ERROR_HAVE_NO_MEMORY(info);
7054 *count = num_queues;
7056 for (i=0; i<*count; i++) {
7057 struct spoolss_DeviceMode *devmode;
7059 result = spoolss_create_default_devmode(info,
7060 pinfo2->printername,
7062 if (!W_ERROR_IS_OK(result)) {
7063 DEBUG(3, ("Can't proceed w/o a devmode!"));
7067 result = fill_job_info2(info,
7074 if (!W_ERROR_IS_OK(result)) {
7080 if (!W_ERROR_IS_OK(result)) {
7091 /****************************************************************************
7092 Enumjobs at level 3.
7093 ****************************************************************************/
7095 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7096 const print_queue_struct *queue,
7097 uint32_t num_queues, int snum,
7098 struct spoolss_PrinterInfo2 *pinfo2,
7099 union spoolss_JobInfo **info_p,
7102 union spoolss_JobInfo *info;
7104 WERROR result = WERR_OK;
7106 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7107 W_ERROR_HAVE_NO_MEMORY(info);
7109 *count = num_queues;
7111 for (i=0; i<*count; i++) {
7112 const print_queue_struct *next_queue = NULL;
7115 next_queue = &queue[i+1];
7118 result = fill_job_info3(info,
7125 if (!W_ERROR_IS_OK(result)) {
7131 if (!W_ERROR_IS_OK(result)) {
7142 /****************************************************************
7144 ****************************************************************/
7146 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7147 struct spoolss_EnumJobs *r)
7150 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7152 print_status_struct prt_status;
7153 print_queue_struct *queue = NULL;
7156 /* that's an [in out] buffer */
7158 if (!r->in.buffer && (r->in.offered != 0)) {
7159 return WERR_INVALID_PARAM;
7162 DEBUG(4,("_spoolss_EnumJobs\n"));
7166 *r->out.info = NULL;
7168 /* lookup the printer snum and tdb entry */
7170 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7174 result = winreg_get_printer_internal(p->mem_ctx,
7175 get_session_info_system(),
7177 lp_const_servicename(snum),
7179 if (!W_ERROR_IS_OK(result)) {
7183 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7184 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7185 count, prt_status.status, prt_status.message));
7189 TALLOC_FREE(pinfo2);
7193 switch (r->in.level) {
7195 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7196 pinfo2, r->out.info, r->out.count);
7199 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7200 pinfo2, r->out.info, r->out.count);
7203 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7204 pinfo2, r->out.info, r->out.count);
7207 result = WERR_UNKNOWN_LEVEL;
7212 TALLOC_FREE(pinfo2);
7214 if (!W_ERROR_IS_OK(result)) {
7218 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7220 *r->out.info, r->in.level,
7222 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7223 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7225 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7228 /****************************************************************
7229 _spoolss_ScheduleJob
7230 ****************************************************************/
7232 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7233 struct spoolss_ScheduleJob *r)
7238 /****************************************************************
7239 ****************************************************************/
7241 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7242 struct messaging_context *msg_ctx,
7243 const char *printer_name,
7245 struct spoolss_SetJobInfo1 *r)
7249 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7253 if (strequal(old_doc_name, r->document_name)) {
7257 if (!print_job_set_name(server_event_context(), msg_ctx,
7258 printer_name, job_id, r->document_name)) {
7265 /****************************************************************
7267 ****************************************************************/
7269 WERROR _spoolss_SetJob(struct pipes_struct *p,
7270 struct spoolss_SetJob *r)
7272 const struct auth_session_info *session_info = p->session_info;
7274 WERROR errcode = WERR_BADFUNC;
7276 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7280 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7281 return WERR_INVALID_PRINTER_NAME;
7284 switch (r->in.command) {
7285 case SPOOLSS_JOB_CONTROL_CANCEL:
7286 case SPOOLSS_JOB_CONTROL_DELETE:
7287 errcode = print_job_delete(session_info, p->msg_ctx,
7288 snum, r->in.job_id);
7289 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7293 case SPOOLSS_JOB_CONTROL_PAUSE:
7294 if (print_job_pause(session_info, p->msg_ctx,
7295 snum, r->in.job_id, &errcode)) {
7299 case SPOOLSS_JOB_CONTROL_RESTART:
7300 case SPOOLSS_JOB_CONTROL_RESUME:
7301 if (print_job_resume(session_info, p->msg_ctx,
7302 snum, r->in.job_id, &errcode)) {
7310 return WERR_UNKNOWN_LEVEL;
7313 if (!W_ERROR_IS_OK(errcode)) {
7317 if (r->in.ctr == NULL) {
7321 switch (r->in.ctr->level) {
7323 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7324 lp_const_servicename(snum),
7326 r->in.ctr->info.info1);
7332 return WERR_UNKNOWN_LEVEL;
7338 /****************************************************************************
7339 Enumerates all printer drivers by level and architecture.
7340 ****************************************************************************/
7342 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7343 const struct auth_session_info *session_info,
7344 struct messaging_context *msg_ctx,
7345 const char *servername,
7346 const char *architecture,
7348 union spoolss_DriverInfo **info_p,
7353 struct spoolss_DriverInfo8 *driver;
7354 union spoolss_DriverInfo *info = NULL;
7356 WERROR result = WERR_OK;
7357 uint32_t num_drivers;
7358 const char **drivers;
7359 struct dcerpc_binding_handle *b;
7360 TALLOC_CTX *tmp_ctx = NULL;
7365 tmp_ctx = talloc_new(mem_ctx);
7370 result = winreg_printer_binding_handle(tmp_ctx,
7374 if (!W_ERROR_IS_OK(result)) {
7378 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7379 result = winreg_get_driver_list(tmp_ctx, b,
7380 architecture, version,
7381 &num_drivers, &drivers);
7382 if (!W_ERROR_IS_OK(result)) {
7385 DEBUG(4, ("we have:[%d] drivers in environment"
7386 " [%s] and version [%d]\n",
7387 num_drivers, architecture, version));
7389 if (num_drivers != 0) {
7390 info = talloc_realloc(tmp_ctx, info,
7391 union spoolss_DriverInfo,
7392 count + num_drivers);
7394 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7395 "failed to enlarge driver info buffer!\n"));
7396 result = WERR_NOMEM;
7401 for (i = 0; i < num_drivers; i++) {
7402 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7404 result = winreg_get_driver(tmp_ctx, b,
7405 architecture, drivers[i],
7407 if (!W_ERROR_IS_OK(result)) {
7413 result = fill_printer_driver_info1(info, &info[count+i].info1,
7414 driver, servername);
7417 result = fill_printer_driver_info2(info, &info[count+i].info2,
7418 driver, servername);
7421 result = fill_printer_driver_info3(info, &info[count+i].info3,
7422 driver, servername);
7425 result = fill_printer_driver_info4(info, &info[count+i].info4,
7426 driver, servername);
7429 result = fill_printer_driver_info5(info, &info[count+i].info5,
7430 driver, servername);
7433 result = fill_printer_driver_info6(info, &info[count+i].info6,
7434 driver, servername);
7437 result = fill_printer_driver_info8(info, &info[count+i].info8,
7438 driver, servername);
7441 result = WERR_UNKNOWN_LEVEL;
7445 TALLOC_FREE(driver);
7447 if (!W_ERROR_IS_OK(result)) {
7452 count += num_drivers;
7453 TALLOC_FREE(drivers);
7457 if (W_ERROR_IS_OK(result)) {
7458 *info_p = talloc_move(mem_ctx, &info);
7462 talloc_free(tmp_ctx);
7466 /****************************************************************************
7467 Enumerates all printer drivers by level.
7468 ****************************************************************************/
7470 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7471 const struct auth_session_info *session_info,
7472 struct messaging_context *msg_ctx,
7473 const char *servername,
7474 const char *architecture,
7476 union spoolss_DriverInfo **info_p,
7480 WERROR result = WERR_OK;
7482 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7484 for (a=0; archi_table[a].long_archi != NULL; a++) {
7486 union spoolss_DriverInfo *info = NULL;
7489 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7493 archi_table[a].long_archi,
7497 if (!W_ERROR_IS_OK(result)) {
7501 for (i=0; i < count; i++) {
7502 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7503 info[i], info_p, count_p);
7510 return enumprinterdrivers_level_by_architecture(mem_ctx,
7520 /****************************************************************
7521 _spoolss_EnumPrinterDrivers
7522 ****************************************************************/
7524 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7525 struct spoolss_EnumPrinterDrivers *r)
7527 const char *cservername;
7530 /* that's an [in out] buffer */
7532 if (!r->in.buffer && (r->in.offered != 0)) {
7533 return WERR_INVALID_PARAM;
7536 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7540 *r->out.info = NULL;
7542 cservername = canon_servername(r->in.server);
7544 if (!is_myname_or_ipaddr(cservername)) {
7545 return WERR_UNKNOWN_PRINTER_DRIVER;
7548 result = enumprinterdrivers_level(p->mem_ctx,
7549 get_session_info_system(),
7556 if (!W_ERROR_IS_OK(result)) {
7560 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7561 spoolss_EnumPrinterDrivers,
7562 *r->out.info, r->in.level,
7564 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7565 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7567 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7570 /****************************************************************
7572 ****************************************************************/
7574 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7575 struct spoolss_EnumForms *r)
7581 *r->out.info = NULL;
7583 /* that's an [in out] buffer */
7585 if (!r->in.buffer && (r->in.offered != 0) ) {
7586 return WERR_INVALID_PARAM;
7589 DEBUG(4,("_spoolss_EnumForms\n"));
7590 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7591 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7593 switch (r->in.level) {
7595 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7596 get_session_info_system(),
7602 result = WERR_UNKNOWN_LEVEL;
7606 if (!W_ERROR_IS_OK(result)) {
7610 if (*r->out.count == 0) {
7611 return WERR_NO_MORE_ITEMS;
7614 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7616 *r->out.info, r->in.level,
7618 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7619 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7621 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7624 /****************************************************************
7626 ****************************************************************/
7628 WERROR _spoolss_GetForm(struct pipes_struct *p,
7629 struct spoolss_GetForm *r)
7633 /* that's an [in out] buffer */
7635 if (!r->in.buffer && (r->in.offered != 0)) {
7636 return WERR_INVALID_PARAM;
7639 DEBUG(4,("_spoolss_GetForm\n"));
7640 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7641 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7643 switch (r->in.level) {
7645 result = winreg_printer_getform1_internal(p->mem_ctx,
7646 get_session_info_system(),
7649 &r->out.info->info1);
7652 result = WERR_UNKNOWN_LEVEL;
7656 if (!W_ERROR_IS_OK(result)) {
7657 TALLOC_FREE(r->out.info);
7661 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7662 r->out.info, r->in.level);
7663 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7665 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7668 /****************************************************************************
7669 ****************************************************************************/
7671 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7672 struct spoolss_PortInfo1 *r,
7675 r->port_name = talloc_strdup(mem_ctx, name);
7676 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7681 /****************************************************************************
7682 TODO: This probably needs distinguish between TCP/IP and Local ports
7684 ****************************************************************************/
7686 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7687 struct spoolss_PortInfo2 *r,
7690 r->port_name = talloc_strdup(mem_ctx, name);
7691 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7693 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7694 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7696 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7697 W_ERROR_HAVE_NO_MEMORY(r->description);
7699 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7706 /****************************************************************************
7707 wrapper around the enumer ports command
7708 ****************************************************************************/
7710 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7712 char *cmd = lp_enumports_cmd();
7713 char **qlines = NULL;
7714 char *command = NULL;
7722 /* if no hook then just fill in the default port */
7725 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7728 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7729 TALLOC_FREE(qlines);
7736 /* we have a valid enumport command */
7738 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7743 DEBUG(10,("Running [%s]\n", command));
7744 ret = smbrun(command, &fd);
7745 DEBUG(10,("Returned [%d]\n", ret));
7746 TALLOC_FREE(command);
7751 return WERR_ACCESS_DENIED;
7755 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7756 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7766 /****************************************************************************
7768 ****************************************************************************/
7770 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7771 union spoolss_PortInfo **info_p,
7774 union spoolss_PortInfo *info = NULL;
7776 WERROR result = WERR_OK;
7777 char **qlines = NULL;
7780 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7781 if (!W_ERROR_IS_OK(result)) {
7786 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7788 DEBUG(10,("Returning WERR_NOMEM\n"));
7789 result = WERR_NOMEM;
7793 for (i=0; i<numlines; i++) {
7794 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7795 result = fill_port_1(info, &info[i].info1, qlines[i]);
7796 if (!W_ERROR_IS_OK(result)) {
7801 TALLOC_FREE(qlines);
7804 if (!W_ERROR_IS_OK(result)) {
7806 TALLOC_FREE(qlines);
7818 /****************************************************************************
7820 ****************************************************************************/
7822 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7823 union spoolss_PortInfo **info_p,
7826 union spoolss_PortInfo *info = NULL;
7828 WERROR result = WERR_OK;
7829 char **qlines = NULL;
7832 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7833 if (!W_ERROR_IS_OK(result)) {
7838 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7840 DEBUG(10,("Returning WERR_NOMEM\n"));
7841 result = WERR_NOMEM;
7845 for (i=0; i<numlines; i++) {
7846 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7847 result = fill_port_2(info, &info[i].info2, qlines[i]);
7848 if (!W_ERROR_IS_OK(result)) {
7853 TALLOC_FREE(qlines);
7856 if (!W_ERROR_IS_OK(result)) {
7858 TALLOC_FREE(qlines);
7870 /****************************************************************
7872 ****************************************************************/
7874 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7875 struct spoolss_EnumPorts *r)
7879 /* that's an [in out] buffer */
7881 if (!r->in.buffer && (r->in.offered != 0)) {
7882 return WERR_INVALID_PARAM;
7885 DEBUG(4,("_spoolss_EnumPorts\n"));
7889 *r->out.info = NULL;
7891 switch (r->in.level) {
7893 result = enumports_level_1(p->mem_ctx, r->out.info,
7897 result = enumports_level_2(p->mem_ctx, r->out.info,
7901 return WERR_UNKNOWN_LEVEL;
7904 if (!W_ERROR_IS_OK(result)) {
7908 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7910 *r->out.info, r->in.level,
7912 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7913 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7915 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7918 /****************************************************************************
7919 ****************************************************************************/
7921 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7923 struct spoolss_SetPrinterInfoCtr *info_ctr,
7924 struct spoolss_DeviceMode *devmode,
7925 struct security_descriptor *secdesc,
7926 struct spoolss_UserLevelCtr *user_ctr,
7927 struct policy_handle *handle)
7929 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7930 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7932 WERROR err = WERR_OK;
7934 /* samba does not have a concept of local, non-shared printers yet, so
7935 * make sure we always setup sharename - gd */
7936 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7937 (info2->printername != NULL && info2->printername[0] != '\0')) {
7938 DEBUG(5, ("spoolss_addprinterex_level_2: "
7939 "no sharename has been set, setting printername %s as sharename\n",
7940 info2->printername));
7941 info2->sharename = info2->printername;
7944 /* check to see if the printer already exists */
7945 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7946 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7948 return WERR_PRINTER_ALREADY_EXISTS;
7951 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7952 if ((snum = print_queue_snum(info2->printername)) != -1) {
7953 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7954 info2->printername));
7955 return WERR_PRINTER_ALREADY_EXISTS;
7959 /* validate printer info struct */
7960 if (!info2->printername || strlen(info2->printername) == 0) {
7961 return WERR_INVALID_PRINTER_NAME;
7963 if (!info2->portname || strlen(info2->portname) == 0) {
7964 return WERR_UNKNOWN_PORT;
7966 if (!info2->drivername || strlen(info2->drivername) == 0) {
7967 return WERR_UNKNOWN_PRINTER_DRIVER;
7969 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7970 return WERR_UNKNOWN_PRINTPROCESSOR;
7973 /* FIXME!!! smbd should check to see if the driver is installed before
7974 trying to add a printer like this --jerry */
7976 if (*lp_addprinter_cmd() ) {
7979 raddr = tsocket_address_inet_addr_string(p->remote_address,
7981 if (raddr == NULL) {
7985 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7988 return WERR_ACCESS_DENIED;
7991 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7992 "smb.conf parameter \"addprinter command\" is defined. This "
7993 "parameter must exist for this call to succeed\n",
7994 info2->sharename ));
7997 if ((snum = print_queue_snum(info2->sharename)) == -1) {
7998 return WERR_ACCESS_DENIED;
8001 /* you must be a printer admin to add a new printer */
8002 if (!print_access_check(p->session_info,
8005 PRINTER_ACCESS_ADMINISTER)) {
8006 return WERR_ACCESS_DENIED;
8010 * Do sanity check on the requested changes for Samba.
8013 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8014 return WERR_INVALID_PARAM;
8017 if (devmode == NULL) {
8018 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8021 update_dsspooler(p->mem_ctx,
8022 get_session_info_system(),
8028 err = winreg_update_printer_internal(p->mem_ctx,
8029 get_session_info_system(),
8036 if (!W_ERROR_IS_OK(err)) {
8040 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8041 if (!W_ERROR_IS_OK(err)) {
8042 /* Handle open failed - remove addition. */
8043 ZERO_STRUCTP(handle);
8050 /****************************************************************
8051 _spoolss_AddPrinterEx
8052 ****************************************************************/
8054 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8055 struct spoolss_AddPrinterEx *r)
8057 switch (r->in.info_ctr->level) {
8059 /* we don't handle yet */
8060 /* but I know what to do ... */
8061 return WERR_UNKNOWN_LEVEL;
8063 return spoolss_addprinterex_level_2(p, r->in.server,
8065 r->in.devmode_ctr->devmode,
8066 r->in.secdesc_ctr->sd,
8067 r->in.userlevel_ctr,
8070 return WERR_UNKNOWN_LEVEL;
8074 /****************************************************************
8076 ****************************************************************/
8078 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8079 struct spoolss_AddPrinter *r)
8081 struct spoolss_AddPrinterEx a;
8082 struct spoolss_UserLevelCtr userlevel_ctr;
8084 ZERO_STRUCT(userlevel_ctr);
8086 userlevel_ctr.level = 1;
8088 a.in.server = r->in.server;
8089 a.in.info_ctr = r->in.info_ctr;
8090 a.in.devmode_ctr = r->in.devmode_ctr;
8091 a.in.secdesc_ctr = r->in.secdesc_ctr;
8092 a.in.userlevel_ctr = &userlevel_ctr;
8093 a.out.handle = r->out.handle;
8095 return _spoolss_AddPrinterEx(p, &a);
8098 /****************************************************************
8099 _spoolss_AddPrinterDriverEx
8100 ****************************************************************/
8102 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8103 struct spoolss_AddPrinterDriverEx *r)
8105 WERROR err = WERR_OK;
8106 const char *driver_name = NULL;
8111 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8112 fn = "_spoolss_AddPrinterDriver";
8114 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8115 fn = "_spoolss_AddPrinterDriverEx";
8118 return WERR_INVALID_PARAM;
8122 * we only support the semantics of AddPrinterDriver()
8123 * i.e. only copy files that are newer than existing ones
8126 if (r->in.flags == 0) {
8127 return WERR_INVALID_PARAM;
8130 if (r->in.flags != APD_COPY_NEW_FILES) {
8131 return WERR_ACCESS_DENIED;
8135 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8136 /* Clever hack from Martin Zielinski <mz@seh.de>
8137 * to allow downgrade from level 8 (Vista).
8139 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8140 r->in.info_ctr->level));
8141 return WERR_UNKNOWN_LEVEL;
8144 DEBUG(5,("Cleaning driver's information\n"));
8145 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8146 if (!W_ERROR_IS_OK(err))
8149 DEBUG(5,("Moving driver to final destination\n"));
8150 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8151 if (!W_ERROR_IS_OK(err)) {
8155 err = winreg_add_driver_internal(p->mem_ctx,
8156 get_session_info_system(),
8161 if (!W_ERROR_IS_OK(err)) {
8166 * I think this is where he DrvUpgradePrinter() hook would be
8167 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8168 * server. Right now, we just need to send ourselves a message
8169 * to update each printer bound to this driver. --jerry
8172 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8173 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8181 /****************************************************************
8182 _spoolss_AddPrinterDriver
8183 ****************************************************************/
8185 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8186 struct spoolss_AddPrinterDriver *r)
8188 struct spoolss_AddPrinterDriverEx a;
8190 switch (r->in.info_ctr->level) {
8197 return WERR_UNKNOWN_LEVEL;
8200 a.in.servername = r->in.servername;
8201 a.in.info_ctr = r->in.info_ctr;
8202 a.in.flags = APD_COPY_NEW_FILES;
8204 return _spoolss_AddPrinterDriverEx(p, &a);
8207 /****************************************************************************
8208 ****************************************************************************/
8210 struct _spoolss_paths {
8216 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8218 static const struct _spoolss_paths spoolss_paths[]= {
8219 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8220 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8223 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8224 const char *servername,
8225 const char *environment,
8229 const char *pservername = NULL;
8230 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8231 const char *short_archi;
8235 /* environment may be empty */
8236 if (environment && strlen(environment)) {
8237 long_archi = environment;
8240 /* servername may be empty */
8241 if (servername && strlen(servername)) {
8242 pservername = canon_servername(servername);
8244 if (!is_myname_or_ipaddr(pservername)) {
8245 return WERR_INVALID_PARAM;
8249 if (!(short_archi = get_short_archi(long_archi))) {
8250 return WERR_INVALID_ENVIRONMENT;
8253 switch (component) {
8254 case SPOOLSS_PRTPROCS_PATH:
8255 case SPOOLSS_DRIVER_PATH:
8257 *path = talloc_asprintf(mem_ctx,
8260 spoolss_paths[component].share,
8263 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8264 SPOOLSS_DEFAULT_SERVER_PATH,
8265 spoolss_paths[component].dir,
8270 return WERR_INVALID_PARAM;
8280 /****************************************************************************
8281 ****************************************************************************/
8283 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8284 const char *servername,
8285 const char *environment,
8286 struct spoolss_DriverDirectoryInfo1 *r)
8291 werr = compose_spoolss_server_path(mem_ctx,
8294 SPOOLSS_DRIVER_PATH,
8296 if (!W_ERROR_IS_OK(werr)) {
8300 DEBUG(4,("printer driver directory: [%s]\n", path));
8302 r->directory_name = path;
8307 /****************************************************************
8308 _spoolss_GetPrinterDriverDirectory
8309 ****************************************************************/
8311 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8312 struct spoolss_GetPrinterDriverDirectory *r)
8316 /* that's an [in out] buffer */
8318 if (!r->in.buffer && (r->in.offered != 0)) {
8319 return WERR_INVALID_PARAM;
8322 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8327 /* r->in.level is ignored */
8329 werror = getprinterdriverdir_level_1(p->mem_ctx,
8332 &r->out.info->info1);
8333 if (!W_ERROR_IS_OK(werror)) {
8334 TALLOC_FREE(r->out.info);
8338 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8339 r->out.info, r->in.level);
8340 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8342 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8345 /****************************************************************
8346 _spoolss_EnumPrinterData
8347 ****************************************************************/
8349 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8350 struct spoolss_EnumPrinterData *r)
8353 struct spoolss_EnumPrinterDataEx r2;
8355 struct spoolss_PrinterEnumValues *info, *val = NULL;
8358 r2.in.handle = r->in.handle;
8359 r2.in.key_name = "PrinterDriverData";
8361 r2.out.count = &count;
8362 r2.out.info = &info;
8363 r2.out.needed = &needed;
8365 result = _spoolss_EnumPrinterDataEx(p, &r2);
8366 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8367 r2.in.offered = needed;
8368 result = _spoolss_EnumPrinterDataEx(p, &r2);
8370 if (!W_ERROR_IS_OK(result)) {
8375 * The NT machine wants to know the biggest size of value and data
8377 * cf: MSDN EnumPrinterData remark section
8380 if (!r->in.value_offered && !r->in.data_offered) {
8381 uint32_t biggest_valuesize = 0;
8382 uint32_t biggest_datasize = 0;
8385 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8387 for (i=0; i<count; i++) {
8389 name_length = strlen(info[i].value_name);
8390 if (strlen(info[i].value_name) > biggest_valuesize) {
8391 biggest_valuesize = name_length;
8394 if (info[i].data_length > biggest_datasize) {
8395 biggest_datasize = info[i].data_length;
8398 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8402 /* the value is an UNICODE string but real_value_size is the length
8403 in bytes including the trailing 0 */
8405 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8406 *r->out.data_needed = biggest_datasize;
8408 DEBUG(6,("final values: [%d], [%d]\n",
8409 *r->out.value_needed, *r->out.data_needed));
8414 if (r->in.enum_index < count) {
8415 val = &info[r->in.enum_index];
8419 /* out_value should default to "" or else NT4 has
8420 problems unmarshalling the response */
8422 if (r->in.value_offered) {
8423 *r->out.value_needed = 1;
8424 r->out.value_name = talloc_strdup(r, "");
8425 if (!r->out.value_name) {
8429 r->out.value_name = NULL;
8430 *r->out.value_needed = 0;
8433 /* the data is counted in bytes */
8435 *r->out.data_needed = r->in.data_offered;
8437 result = WERR_NO_MORE_ITEMS;
8441 * - counted in bytes in the request
8442 * - counted in UNICODE chars in the max reply
8443 * - counted in bytes in the real size
8445 * take a pause *before* coding not *during* coding
8449 if (r->in.value_offered) {
8450 r->out.value_name = talloc_strdup(r, val->value_name);
8451 if (!r->out.value_name) {
8454 *r->out.value_needed = val->value_name_len;
8456 r->out.value_name = NULL;
8457 *r->out.value_needed = 0;
8462 *r->out.type = val->type;
8464 /* data - counted in bytes */
8467 * See the section "Dynamically Typed Query Parameters"
8471 if (r->out.data && val->data && val->data->data &&
8472 val->data_length && r->in.data_offered) {
8473 memcpy(r->out.data, val->data->data,
8474 MIN(val->data_length,r->in.data_offered));
8477 *r->out.data_needed = val->data_length;
8485 /****************************************************************
8486 _spoolss_SetPrinterData
8487 ****************************************************************/
8489 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8490 struct spoolss_SetPrinterData *r)
8492 struct spoolss_SetPrinterDataEx r2;
8494 r2.in.handle = r->in.handle;
8495 r2.in.key_name = "PrinterDriverData";
8496 r2.in.value_name = r->in.value_name;
8497 r2.in.type = r->in.type;
8498 r2.in.data = r->in.data;
8499 r2.in.offered = r->in.offered;
8501 return _spoolss_SetPrinterDataEx(p, &r2);
8504 /****************************************************************
8505 _spoolss_ResetPrinter
8506 ****************************************************************/
8508 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8509 struct spoolss_ResetPrinter *r)
8511 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8514 DEBUG(5,("_spoolss_ResetPrinter\n"));
8517 * All we do is to check to see if the handle and queue is valid.
8518 * This call really doesn't mean anything to us because we only
8519 * support RAW printing. --jerry
8523 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8524 OUR_HANDLE(r->in.handle)));
8528 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8532 /* blindly return success */
8536 /****************************************************************
8537 _spoolss_DeletePrinterData
8538 ****************************************************************/
8540 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8541 struct spoolss_DeletePrinterData *r)
8543 struct spoolss_DeletePrinterDataEx r2;
8545 r2.in.handle = r->in.handle;
8546 r2.in.key_name = "PrinterDriverData";
8547 r2.in.value_name = r->in.value_name;
8549 return _spoolss_DeletePrinterDataEx(p, &r2);
8552 /****************************************************************
8554 ****************************************************************/
8556 WERROR _spoolss_AddForm(struct pipes_struct *p,
8557 struct spoolss_AddForm *r)
8559 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8561 WERROR status = WERR_OK;
8562 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8563 struct dcerpc_binding_handle *b;
8564 TALLOC_CTX *tmp_ctx = NULL;
8566 DEBUG(5,("_spoolss_AddForm\n"));
8569 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8570 OUR_HANDLE(r->in.handle)));
8574 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8575 and not a printer admin, then fail */
8577 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8578 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8579 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8580 p->session_info->info->domain_name,
8582 p->session_info->security_token,
8583 lp_printer_admin(snum))) {
8584 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8585 return WERR_ACCESS_DENIED;
8588 switch (form->flags) {
8589 case SPOOLSS_FORM_USER:
8590 case SPOOLSS_FORM_BUILTIN:
8591 case SPOOLSS_FORM_PRINTER:
8594 return WERR_INVALID_PARAM;
8597 tmp_ctx = talloc_new(p->mem_ctx);
8602 status = winreg_printer_binding_handle(tmp_ctx,
8603 get_session_info_system(),
8606 if (!W_ERROR_IS_OK(status)) {
8610 status = winreg_printer_addform1(tmp_ctx, b, form);
8611 if (!W_ERROR_IS_OK(status)) {
8616 * ChangeID must always be set if this is a printer
8618 if (Printer->printer_type == SPLHND_PRINTER) {
8619 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8620 status = WERR_BADFID;
8624 status = winreg_printer_update_changeid(tmp_ctx, b,
8625 lp_const_servicename(snum));
8629 talloc_free(tmp_ctx);
8633 /****************************************************************
8635 ****************************************************************/
8637 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8638 struct spoolss_DeleteForm *r)
8640 const char *form_name = r->in.form_name;
8641 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8643 WERROR status = WERR_OK;
8644 struct dcerpc_binding_handle *b;
8645 TALLOC_CTX *tmp_ctx = NULL;
8647 DEBUG(5,("_spoolss_DeleteForm\n"));
8650 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8651 OUR_HANDLE(r->in.handle)));
8655 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8656 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8657 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8658 p->session_info->info->domain_name,
8660 p->session_info->security_token,
8661 lp_printer_admin(snum))) {
8662 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8663 return WERR_ACCESS_DENIED;
8666 tmp_ctx = talloc_new(p->mem_ctx);
8671 status = winreg_printer_binding_handle(tmp_ctx,
8672 get_session_info_system(),
8675 if (!W_ERROR_IS_OK(status)) {
8679 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8680 if (!W_ERROR_IS_OK(status)) {
8685 * ChangeID must always be set if this is a printer
8687 if (Printer->printer_type == SPLHND_PRINTER) {
8688 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8689 status = WERR_BADFID;
8693 status = winreg_printer_update_changeid(tmp_ctx, b,
8694 lp_const_servicename(snum));
8698 talloc_free(tmp_ctx);
8702 /****************************************************************
8704 ****************************************************************/
8706 WERROR _spoolss_SetForm(struct pipes_struct *p,
8707 struct spoolss_SetForm *r)
8709 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8710 const char *form_name = r->in.form_name;
8712 WERROR status = WERR_OK;
8713 struct dcerpc_binding_handle *b;
8714 TALLOC_CTX *tmp_ctx = NULL;
8716 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8718 DEBUG(5,("_spoolss_SetForm\n"));
8721 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8722 OUR_HANDLE(r->in.handle)));
8726 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8727 and not a printer admin, then fail */
8729 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8730 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8731 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8732 p->session_info->info->domain_name,
8734 p->session_info->security_token,
8735 lp_printer_admin(snum))) {
8736 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8737 return WERR_ACCESS_DENIED;
8740 tmp_ctx = talloc_new(p->mem_ctx);
8745 status = winreg_printer_binding_handle(tmp_ctx,
8746 get_session_info_system(),
8749 if (!W_ERROR_IS_OK(status)) {
8753 status = winreg_printer_setform1(tmp_ctx, b,
8756 if (!W_ERROR_IS_OK(status)) {
8761 * ChangeID must always be set if this is a printer
8763 if (Printer->printer_type == SPLHND_PRINTER) {
8764 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8765 status = WERR_BADFID;
8769 status = winreg_printer_update_changeid(tmp_ctx, b,
8770 lp_const_servicename(snum));
8774 talloc_free(tmp_ctx);
8778 /****************************************************************************
8779 fill_print_processor1
8780 ****************************************************************************/
8782 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8783 struct spoolss_PrintProcessorInfo1 *r,
8784 const char *print_processor_name)
8786 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8787 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8792 /****************************************************************************
8793 enumprintprocessors level 1.
8794 ****************************************************************************/
8796 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8797 union spoolss_PrintProcessorInfo **info_p,
8800 union spoolss_PrintProcessorInfo *info;
8803 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8804 W_ERROR_HAVE_NO_MEMORY(info);
8808 result = fill_print_processor1(info, &info[0].info1, "winprint");
8809 if (!W_ERROR_IS_OK(result)) {
8814 if (!W_ERROR_IS_OK(result)) {
8825 /****************************************************************
8826 _spoolss_EnumPrintProcessors
8827 ****************************************************************/
8829 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8830 struct spoolss_EnumPrintProcessors *r)
8834 /* that's an [in out] buffer */
8836 if (!r->in.buffer && (r->in.offered != 0)) {
8837 return WERR_INVALID_PARAM;
8840 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8843 * Enumerate the print processors ...
8845 * Just reply with "winprint", to keep NT happy
8846 * and I can use my nice printer checker.
8851 *r->out.info = NULL;
8853 if (!get_short_archi(r->in.environment)) {
8854 return WERR_INVALID_ENVIRONMENT;
8857 switch (r->in.level) {
8859 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8863 return WERR_UNKNOWN_LEVEL;
8866 if (!W_ERROR_IS_OK(result)) {
8870 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8871 spoolss_EnumPrintProcessors,
8872 *r->out.info, r->in.level,
8874 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8875 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8877 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8880 /****************************************************************************
8881 fill_printprocdatatype1
8882 ****************************************************************************/
8884 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8885 struct spoolss_PrintProcDataTypesInfo1 *r,
8886 const char *name_array)
8888 r->name_array = talloc_strdup(mem_ctx, name_array);
8889 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8894 /****************************************************************************
8895 enumprintprocdatatypes level 1.
8896 ****************************************************************************/
8898 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8899 union spoolss_PrintProcDataTypesInfo **info_p,
8903 union spoolss_PrintProcDataTypesInfo *info;
8905 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8906 W_ERROR_HAVE_NO_MEMORY(info);
8910 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8911 if (!W_ERROR_IS_OK(result)) {
8916 if (!W_ERROR_IS_OK(result)) {
8927 /****************************************************************
8928 _spoolss_EnumPrintProcDataTypes
8929 ****************************************************************/
8931 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8932 struct spoolss_EnumPrintProcDataTypes *r)
8936 /* that's an [in out] buffer */
8938 if (!r->in.buffer && (r->in.offered != 0)) {
8939 return WERR_INVALID_PARAM;
8942 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8946 *r->out.info = NULL;
8948 if (r->in.print_processor_name == NULL ||
8949 !strequal(r->in.print_processor_name, "winprint")) {
8950 return WERR_UNKNOWN_PRINTPROCESSOR;
8953 switch (r->in.level) {
8955 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8959 return WERR_UNKNOWN_LEVEL;
8962 if (!W_ERROR_IS_OK(result)) {
8966 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8967 spoolss_EnumPrintProcDataTypes,
8968 *r->out.info, r->in.level,
8970 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8971 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8973 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8976 /****************************************************************************
8978 ****************************************************************************/
8980 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8981 struct spoolss_MonitorInfo1 *r,
8982 const char *monitor_name)
8984 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8985 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8990 /****************************************************************************
8992 ****************************************************************************/
8994 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8995 struct spoolss_MonitorInfo2 *r,
8996 const char *monitor_name,
8997 const char *environment,
8998 const char *dll_name)
9000 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9001 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9002 r->environment = talloc_strdup(mem_ctx, environment);
9003 W_ERROR_HAVE_NO_MEMORY(r->environment);
9004 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9005 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9010 /****************************************************************************
9011 enumprintmonitors level 1.
9012 ****************************************************************************/
9014 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9015 union spoolss_MonitorInfo **info_p,
9018 union spoolss_MonitorInfo *info;
9019 WERROR result = WERR_OK;
9021 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9022 W_ERROR_HAVE_NO_MEMORY(info);
9026 result = fill_monitor_1(info, &info[0].info1,
9028 if (!W_ERROR_IS_OK(result)) {
9032 result = fill_monitor_1(info, &info[1].info1,
9034 if (!W_ERROR_IS_OK(result)) {
9039 if (!W_ERROR_IS_OK(result)) {
9050 /****************************************************************************
9051 enumprintmonitors level 2.
9052 ****************************************************************************/
9054 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9055 union spoolss_MonitorInfo **info_p,
9058 union spoolss_MonitorInfo *info;
9059 WERROR result = WERR_OK;
9061 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9062 W_ERROR_HAVE_NO_MEMORY(info);
9066 result = fill_monitor_2(info, &info[0].info2,
9068 "Windows NT X86", /* FIXME */
9070 if (!W_ERROR_IS_OK(result)) {
9074 result = fill_monitor_2(info, &info[1].info2,
9076 "Windows NT X86", /* FIXME */
9078 if (!W_ERROR_IS_OK(result)) {
9083 if (!W_ERROR_IS_OK(result)) {
9094 /****************************************************************
9095 _spoolss_EnumMonitors
9096 ****************************************************************/
9098 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9099 struct spoolss_EnumMonitors *r)
9103 /* that's an [in out] buffer */
9105 if (!r->in.buffer && (r->in.offered != 0)) {
9106 return WERR_INVALID_PARAM;
9109 DEBUG(5,("_spoolss_EnumMonitors\n"));
9112 * Enumerate the print monitors ...
9114 * Just reply with "Local Port", to keep NT happy
9115 * and I can use my nice printer checker.
9120 *r->out.info = NULL;
9122 switch (r->in.level) {
9124 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9128 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9132 return WERR_UNKNOWN_LEVEL;
9135 if (!W_ERROR_IS_OK(result)) {
9139 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9140 spoolss_EnumMonitors,
9141 *r->out.info, r->in.level,
9143 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9144 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9146 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9149 /****************************************************************************
9150 ****************************************************************************/
9152 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9153 const print_queue_struct *queue,
9154 int count, int snum,
9155 struct spoolss_PrinterInfo2 *pinfo2,
9157 struct spoolss_JobInfo1 *r)
9162 for (i=0; i<count; i++) {
9163 if (queue[i].job == (int)jobid) {
9169 if (found == false) {
9170 /* NT treats not found as bad param... yet another bad choice */
9171 return WERR_INVALID_PARAM;
9174 return fill_job_info1(mem_ctx,
9182 /****************************************************************************
9183 ****************************************************************************/
9185 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9186 const print_queue_struct *queue,
9187 int count, int snum,
9188 struct spoolss_PrinterInfo2 *pinfo2,
9190 struct spoolss_JobInfo2 *r)
9194 struct spoolss_DeviceMode *devmode;
9197 for (i=0; i<count; i++) {
9198 if (queue[i].job == (int)jobid) {
9204 if (found == false) {
9205 /* NT treats not found as bad param... yet another bad
9207 return WERR_INVALID_PARAM;
9211 * if the print job does not have a DEVMODE associated with it,
9212 * just use the one for the printer. A NULL devicemode is not
9213 * a failure condition
9216 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9218 result = spoolss_create_default_devmode(mem_ctx,
9219 pinfo2->printername,
9221 if (!W_ERROR_IS_OK(result)) {
9222 DEBUG(3, ("Can't proceed w/o a devmode!"));
9227 return fill_job_info2(mem_ctx,
9236 /****************************************************************
9238 ****************************************************************/
9240 WERROR _spoolss_GetJob(struct pipes_struct *p,
9241 struct spoolss_GetJob *r)
9243 WERROR result = WERR_OK;
9244 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9247 print_queue_struct *queue = NULL;
9248 print_status_struct prt_status;
9250 /* that's an [in out] buffer */
9252 if (!r->in.buffer && (r->in.offered != 0)) {
9253 return WERR_INVALID_PARAM;
9256 DEBUG(5,("_spoolss_GetJob\n"));
9260 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9264 result = winreg_get_printer_internal(p->mem_ctx,
9265 get_session_info_system(),
9267 lp_const_servicename(snum),
9269 if (!W_ERROR_IS_OK(result)) {
9273 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9275 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9276 count, prt_status.status, prt_status.message));
9278 switch (r->in.level) {
9280 result = getjob_level_1(p->mem_ctx,
9281 queue, count, snum, pinfo2,
9282 r->in.job_id, &r->out.info->info1);
9285 result = getjob_level_2(p->mem_ctx,
9286 queue, count, snum, pinfo2,
9287 r->in.job_id, &r->out.info->info2);
9290 result = WERR_UNKNOWN_LEVEL;
9295 TALLOC_FREE(pinfo2);
9297 if (!W_ERROR_IS_OK(result)) {
9298 TALLOC_FREE(r->out.info);
9302 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9304 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9306 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9309 /****************************************************************
9310 _spoolss_GetPrinterDataEx
9311 ****************************************************************/
9313 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9314 struct spoolss_GetPrinterDataEx *r)
9317 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9318 const char *printer;
9320 WERROR result = WERR_OK;
9322 enum winreg_Type val_type = REG_NONE;
9323 uint8_t *val_data = NULL;
9324 uint32_t val_size = 0;
9325 struct dcerpc_binding_handle *b;
9326 TALLOC_CTX *tmp_ctx;
9328 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9330 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9331 r->in.key_name, r->in.value_name));
9333 /* in case of problem, return some default values */
9336 *r->out.type = REG_NONE;
9338 tmp_ctx = talloc_new(p->mem_ctx);
9344 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9345 OUR_HANDLE(r->in.handle)));
9346 result = WERR_BADFID;
9350 /* check to see if the keyname is valid */
9351 if (!strlen(r->in.key_name)) {
9352 result = WERR_INVALID_PARAM;
9356 /* Is the handle to a printer or to the server? */
9358 if (Printer->printer_type == SPLHND_SERVER) {
9360 union spoolss_PrinterData data;
9362 result = getprinterdata_printer_server(tmp_ctx,
9366 if (!W_ERROR_IS_OK(result)) {
9370 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9371 *r->out.type, &data);
9372 if (!W_ERROR_IS_OK(result)) {
9376 *r->out.needed = blob.length;
9378 if (r->in.offered >= *r->out.needed) {
9379 memcpy(r->out.data, blob.data, blob.length);
9386 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9387 result = WERR_BADFID;
9390 printer = lp_const_servicename(snum);
9392 result = winreg_printer_binding_handle(tmp_ctx,
9393 get_session_info_system(),
9396 if (!W_ERROR_IS_OK(result)) {
9400 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9401 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9402 strequal(r->in.value_name, "ChangeId")) {
9403 *r->out.type = REG_DWORD;
9405 if (r->in.offered >= *r->out.needed) {
9406 uint32_t changeid = 0;
9408 result = winreg_printer_get_changeid(tmp_ctx, b,
9411 if (!W_ERROR_IS_OK(result)) {
9415 SIVAL(r->out.data, 0, changeid);
9421 result = winreg_get_printer_dataex(tmp_ctx, b,
9428 if (!W_ERROR_IS_OK(result)) {
9432 *r->out.needed = val_size;
9433 *r->out.type = val_type;
9435 if (r->in.offered >= *r->out.needed) {
9436 memcpy(r->out.data, val_data, val_size);
9440 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9442 if (W_ERROR_IS_OK(result)) {
9443 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9446 talloc_free(tmp_ctx);
9450 /****************************************************************
9451 _spoolss_SetPrinterDataEx
9452 ****************************************************************/
9454 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9455 struct spoolss_SetPrinterDataEx *r)
9457 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9459 WERROR result = WERR_OK;
9460 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9462 struct dcerpc_binding_handle *b;
9463 TALLOC_CTX *tmp_ctx;
9465 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9467 /* From MSDN documentation of SetPrinterDataEx: pass request to
9468 SetPrinterData if key is "PrinterDriverData" */
9471 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9472 OUR_HANDLE(r->in.handle)));
9476 if (Printer->printer_type == SPLHND_SERVER) {
9477 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9478 "Not implemented for server handles yet\n"));
9479 return WERR_INVALID_PARAM;
9482 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9487 * Access check : NT returns "access denied" if you make a
9488 * SetPrinterData call without the necessary privildge.
9489 * we were originally returning OK if nothing changed
9490 * which made Win2k issue **a lot** of SetPrinterData
9491 * when connecting to a printer --jerry
9494 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9495 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9496 "change denied by handle access permissions\n"));
9497 return WERR_ACCESS_DENIED;
9500 tmp_ctx = talloc_new(p->mem_ctx);
9505 result = winreg_printer_binding_handle(tmp_ctx,
9506 get_session_info_system(),
9509 if (!W_ERROR_IS_OK(result)) {
9513 result = winreg_get_printer(tmp_ctx, b,
9514 lp_servicename(snum),
9516 if (!W_ERROR_IS_OK(result)) {
9520 /* check for OID in valuename */
9522 oid_string = strchr(r->in.value_name, ',');
9528 /* save the registry data */
9530 result = winreg_set_printer_dataex(tmp_ctx, b,
9538 if (W_ERROR_IS_OK(result)) {
9539 /* save the OID if one was specified */
9541 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9542 r->in.key_name, SPOOL_OID_KEY);
9544 result = WERR_NOMEM;
9549 * I'm not checking the status here on purpose. Don't know
9550 * if this is right, but I'm returning the status from the
9551 * previous set_printer_dataex() call. I have no idea if
9552 * this is right. --jerry
9554 winreg_set_printer_dataex(tmp_ctx, b,
9559 (uint8_t *) oid_string,
9560 strlen(oid_string) + 1);
9563 result = winreg_printer_update_changeid(tmp_ctx, b,
9564 lp_const_servicename(snum));
9569 talloc_free(tmp_ctx);
9573 /****************************************************************
9574 _spoolss_DeletePrinterDataEx
9575 ****************************************************************/
9577 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9578 struct spoolss_DeletePrinterDataEx *r)
9580 const char *printer;
9582 WERROR status = WERR_OK;
9583 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9585 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9588 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9589 "Invalid handle (%s:%u:%u).\n",
9590 OUR_HANDLE(r->in.handle)));
9594 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9595 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9596 "printer properties change denied by handle\n"));
9597 return WERR_ACCESS_DENIED;
9600 if (!r->in.value_name || !r->in.key_name) {
9604 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9607 printer = lp_const_servicename(snum);
9609 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9610 get_session_info_system(),
9615 if (W_ERROR_IS_OK(status)) {
9616 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9617 get_session_info_system(),
9625 /****************************************************************
9626 _spoolss_EnumPrinterKey
9627 ****************************************************************/
9629 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9630 struct spoolss_EnumPrinterKey *r)
9633 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9635 WERROR result = WERR_BADFILE;
9636 const char **array = NULL;
9639 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9642 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9643 OUR_HANDLE(r->in.handle)));
9647 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9651 result = winreg_enum_printer_key_internal(p->mem_ctx,
9652 get_session_info_system(),
9654 lp_const_servicename(snum),
9658 if (!W_ERROR_IS_OK(result)) {
9662 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9663 result = WERR_NOMEM;
9667 *r->out._ndr_size = r->in.offered / 2;
9668 *r->out.needed = blob.length;
9670 if (r->in.offered < *r->out.needed) {
9671 result = WERR_MORE_DATA;
9674 r->out.key_buffer->string_array = array;
9678 if (!W_ERROR_IS_OK(result)) {
9680 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9688 /****************************************************************
9689 _spoolss_DeletePrinterKey
9690 ****************************************************************/
9692 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9693 struct spoolss_DeletePrinterKey *r)
9695 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9698 const char *printer;
9699 struct dcerpc_binding_handle *b;
9700 TALLOC_CTX *tmp_ctx;
9702 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9705 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9706 OUR_HANDLE(r->in.handle)));
9710 /* if keyname == NULL, return error */
9711 if ( !r->in.key_name )
9712 return WERR_INVALID_PARAM;
9714 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9718 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9719 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9720 "printer properties change denied by handle\n"));
9721 return WERR_ACCESS_DENIED;
9724 printer = lp_const_servicename(snum);
9726 tmp_ctx = talloc_new(p->mem_ctx);
9731 status = winreg_printer_binding_handle(tmp_ctx,
9732 get_session_info_system(),
9735 if (!W_ERROR_IS_OK(status)) {
9739 /* delete the key and all subkeys */
9740 status = winreg_delete_printer_key(tmp_ctx, b,
9743 if (W_ERROR_IS_OK(status)) {
9744 status = winreg_printer_update_changeid(tmp_ctx, b,
9749 talloc_free(tmp_ctx);
9753 /****************************************************************
9754 _spoolss_EnumPrinterDataEx
9755 ****************************************************************/
9757 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9758 struct spoolss_EnumPrinterDataEx *r)
9761 struct spoolss_PrinterEnumValues *info = NULL;
9762 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9766 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9770 *r->out.info = NULL;
9773 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9774 OUR_HANDLE(r->in.handle)));
9779 * first check for a keyname of NULL or "". Win2k seems to send
9780 * this a lot and we should send back WERR_INVALID_PARAM
9781 * no need to spend time looking up the printer in this case.
9785 if (!strlen(r->in.key_name)) {
9786 result = WERR_INVALID_PARAM;
9790 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9794 /* now look for a match on the key name */
9795 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9796 get_session_info_system(),
9798 lp_const_servicename(snum),
9802 if (!W_ERROR_IS_OK(result)) {
9806 #if 0 /* FIXME - gd */
9807 /* housekeeping information in the reply */
9809 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9810 * the hand marshalled container size is a multiple
9811 * of 4 bytes for RPC alignment.
9815 needed += 4-(needed % 4);
9818 *r->out.count = count;
9819 *r->out.info = info;
9822 if (!W_ERROR_IS_OK(result)) {
9826 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9827 spoolss_EnumPrinterDataEx,
9830 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9831 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9833 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9836 /****************************************************************************
9837 ****************************************************************************/
9839 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9840 const char *servername,
9841 const char *environment,
9842 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9847 werr = compose_spoolss_server_path(mem_ctx,
9850 SPOOLSS_PRTPROCS_PATH,
9852 if (!W_ERROR_IS_OK(werr)) {
9856 DEBUG(4,("print processor directory: [%s]\n", path));
9858 r->directory_name = path;
9863 /****************************************************************
9864 _spoolss_GetPrintProcessorDirectory
9865 ****************************************************************/
9867 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9868 struct spoolss_GetPrintProcessorDirectory *r)
9871 char *prnproc_share = NULL;
9872 bool prnproc_share_exists = false;
9875 /* that's an [in out] buffer */
9877 if (!r->in.buffer && (r->in.offered != 0)) {
9878 return WERR_INVALID_PARAM;
9881 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9886 /* r->in.level is ignored */
9888 /* We always should reply with a local print processor directory so that
9889 * users are not forced to have a [prnproc$] share on the Samba spoolss
9890 * server, if users decide to do so, lets announce it though - Guenther */
9892 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9893 if (!prnproc_share) {
9897 prnproc_share_exists = true;
9900 result = getprintprocessordirectory_level_1(p->mem_ctx,
9901 prnproc_share_exists ? r->in.server : NULL,
9903 &r->out.info->info1);
9904 if (!W_ERROR_IS_OK(result)) {
9905 TALLOC_FREE(r->out.info);
9909 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9910 r->out.info, r->in.level);
9911 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9913 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9916 /*******************************************************************
9917 ********************************************************************/
9919 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9920 const char *dllname)
9922 enum ndr_err_code ndr_err;
9923 struct spoolss_MonitorUi ui;
9925 ui.dll_name = dllname;
9927 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9928 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9929 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9930 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9932 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9935 /*******************************************************************
9936 Streams the monitor UI DLL name in UNICODE
9937 *******************************************************************/
9939 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9940 struct security_token *token, DATA_BLOB *in,
9941 DATA_BLOB *out, uint32_t *needed)
9943 const char *dllname = "tcpmonui.dll";
9945 *needed = (strlen(dllname)+1) * 2;
9947 if (out->length < *needed) {
9948 return WERR_INSUFFICIENT_BUFFER;
9951 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9958 /*******************************************************************
9959 ********************************************************************/
9961 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9962 struct spoolss_PortData1 *port1,
9963 const DATA_BLOB *buf)
9965 enum ndr_err_code ndr_err;
9966 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9967 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9968 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9969 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9971 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9974 /*******************************************************************
9975 ********************************************************************/
9977 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9978 struct spoolss_PortData2 *port2,
9979 const DATA_BLOB *buf)
9981 enum ndr_err_code ndr_err;
9982 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9983 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9984 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9985 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9987 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9990 /*******************************************************************
9991 Create a new TCP/IP port
9992 *******************************************************************/
9994 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9995 struct security_token *token, DATA_BLOB *in,
9996 DATA_BLOB *out, uint32_t *needed)
9998 struct spoolss_PortData1 port1;
9999 struct spoolss_PortData2 port2;
10000 char *device_uri = NULL;
10003 const char *portname;
10004 const char *hostaddress;
10006 uint32_t port_number;
10009 /* peek for spoolss_PortData version */
10011 if (!in || (in->length < (128 + 4))) {
10012 return WERR_GENERAL_FAILURE;
10015 version = IVAL(in->data, 128);
10019 ZERO_STRUCT(port1);
10021 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10025 portname = port1.portname;
10026 hostaddress = port1.hostaddress;
10027 queue = port1.queue;
10028 protocol = port1.protocol;
10029 port_number = port1.port_number;
10033 ZERO_STRUCT(port2);
10035 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10039 portname = port2.portname;
10040 hostaddress = port2.hostaddress;
10041 queue = port2.queue;
10042 protocol = port2.protocol;
10043 port_number = port2.port_number;
10047 DEBUG(1,("xcvtcp_addport: "
10048 "unknown version of port_data: %d\n", version));
10049 return WERR_UNKNOWN_PORT;
10052 /* create the device URI and call the add_port_hook() */
10054 switch (protocol) {
10055 case PROTOCOL_RAWTCP_TYPE:
10056 device_uri = talloc_asprintf(mem_ctx,
10057 "socket://%s:%d/", hostaddress,
10061 case PROTOCOL_LPR_TYPE:
10062 device_uri = talloc_asprintf(mem_ctx,
10063 "lpr://%s/%s", hostaddress, queue );
10067 return WERR_UNKNOWN_PORT;
10074 return add_port_hook(mem_ctx, token, portname, device_uri);
10077 /*******************************************************************
10078 *******************************************************************/
10080 struct xcv_api_table xcvtcp_cmds[] = {
10081 { "MonitorUI", xcvtcp_monitorui },
10082 { "AddPort", xcvtcp_addport},
10086 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10087 struct security_token *token, const char *command,
10094 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10096 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10097 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10098 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10101 return WERR_BADFUNC;
10104 /*******************************************************************
10105 *******************************************************************/
10106 #if 0 /* don't support management using the "Local Port" monitor */
10108 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10109 struct security_token *token, DATA_BLOB *in,
10110 DATA_BLOB *out, uint32_t *needed)
10112 const char *dllname = "localui.dll";
10114 *needed = (strlen(dllname)+1) * 2;
10116 if (out->length < *needed) {
10117 return WERR_INSUFFICIENT_BUFFER;
10120 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10127 /*******************************************************************
10128 *******************************************************************/
10130 struct xcv_api_table xcvlocal_cmds[] = {
10131 { "MonitorUI", xcvlocal_monitorui },
10135 struct xcv_api_table xcvlocal_cmds[] = {
10142 /*******************************************************************
10143 *******************************************************************/
10145 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10146 struct security_token *token, const char *command,
10147 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10152 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10154 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10155 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10156 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10158 return WERR_BADFUNC;
10161 /****************************************************************
10163 ****************************************************************/
10165 WERROR _spoolss_XcvData(struct pipes_struct *p,
10166 struct spoolss_XcvData *r)
10168 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10169 DATA_BLOB out_data = data_blob_null;
10173 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10174 OUR_HANDLE(r->in.handle)));
10175 return WERR_BADFID;
10178 /* Has to be a handle to the TCP/IP port monitor */
10180 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10181 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10182 return WERR_BADFID;
10185 /* requires administrative access to the server */
10187 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10188 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10189 return WERR_ACCESS_DENIED;
10192 /* Allocate the outgoing buffer */
10194 if (r->in.out_data_size) {
10195 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10196 if (out_data.data == NULL) {
10201 switch ( Printer->printer_type ) {
10202 case SPLHND_PORTMON_TCP:
10203 werror = process_xcvtcp_command(p->mem_ctx,
10204 p->session_info->security_token,
10205 r->in.function_name,
10206 &r->in.in_data, &out_data,
10209 case SPLHND_PORTMON_LOCAL:
10210 werror = process_xcvlocal_command(p->mem_ctx,
10211 p->session_info->security_token,
10212 r->in.function_name,
10213 &r->in.in_data, &out_data,
10217 werror = WERR_INVALID_PRINT_MONITOR;
10220 if (!W_ERROR_IS_OK(werror)) {
10224 *r->out.status_code = 0;
10226 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10227 memcpy(r->out.out_data, out_data.data,
10228 MIN(r->in.out_data_size, out_data.length));
10234 /****************************************************************
10235 _spoolss_AddPrintProcessor
10236 ****************************************************************/
10238 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10239 struct spoolss_AddPrintProcessor *r)
10241 /* for now, just indicate success and ignore the add. We'll
10242 automatically set the winprint processor for printer
10243 entries later. Used to debug the LexMark Optra S 1855 PCL
10249 /****************************************************************
10251 ****************************************************************/
10253 WERROR _spoolss_AddPort(struct pipes_struct *p,
10254 struct spoolss_AddPort *r)
10256 /* do what w2k3 does */
10258 return WERR_NOT_SUPPORTED;
10261 /****************************************************************
10262 _spoolss_GetPrinterDriver
10263 ****************************************************************/
10265 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10266 struct spoolss_GetPrinterDriver *r)
10268 p->rng_fault_state = true;
10269 return WERR_NOT_SUPPORTED;
10272 /****************************************************************
10273 _spoolss_ReadPrinter
10274 ****************************************************************/
10276 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10277 struct spoolss_ReadPrinter *r)
10279 p->rng_fault_state = true;
10280 return WERR_NOT_SUPPORTED;
10283 /****************************************************************
10284 _spoolss_WaitForPrinterChange
10285 ****************************************************************/
10287 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10288 struct spoolss_WaitForPrinterChange *r)
10290 p->rng_fault_state = true;
10291 return WERR_NOT_SUPPORTED;
10294 /****************************************************************
10295 _spoolss_ConfigurePort
10296 ****************************************************************/
10298 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10299 struct spoolss_ConfigurePort *r)
10301 p->rng_fault_state = true;
10302 return WERR_NOT_SUPPORTED;
10305 /****************************************************************
10306 _spoolss_DeletePort
10307 ****************************************************************/
10309 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10310 struct spoolss_DeletePort *r)
10312 p->rng_fault_state = true;
10313 return WERR_NOT_SUPPORTED;
10316 /****************************************************************
10317 _spoolss_CreatePrinterIC
10318 ****************************************************************/
10320 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10321 struct spoolss_CreatePrinterIC *r)
10323 p->rng_fault_state = true;
10324 return WERR_NOT_SUPPORTED;
10327 /****************************************************************
10328 _spoolss_PlayGDIScriptOnPrinterIC
10329 ****************************************************************/
10331 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10332 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10334 p->rng_fault_state = true;
10335 return WERR_NOT_SUPPORTED;
10338 /****************************************************************
10339 _spoolss_DeletePrinterIC
10340 ****************************************************************/
10342 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10343 struct spoolss_DeletePrinterIC *r)
10345 p->rng_fault_state = true;
10346 return WERR_NOT_SUPPORTED;
10349 /****************************************************************
10350 _spoolss_AddPrinterConnection
10351 ****************************************************************/
10353 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10354 struct spoolss_AddPrinterConnection *r)
10356 p->rng_fault_state = true;
10357 return WERR_NOT_SUPPORTED;
10360 /****************************************************************
10361 _spoolss_DeletePrinterConnection
10362 ****************************************************************/
10364 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10365 struct spoolss_DeletePrinterConnection *r)
10367 p->rng_fault_state = true;
10368 return WERR_NOT_SUPPORTED;
10371 /****************************************************************
10372 _spoolss_PrinterMessageBox
10373 ****************************************************************/
10375 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10376 struct spoolss_PrinterMessageBox *r)
10378 p->rng_fault_state = true;
10379 return WERR_NOT_SUPPORTED;
10382 /****************************************************************
10383 _spoolss_AddMonitor
10384 ****************************************************************/
10386 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10387 struct spoolss_AddMonitor *r)
10389 p->rng_fault_state = true;
10390 return WERR_NOT_SUPPORTED;
10393 /****************************************************************
10394 _spoolss_DeleteMonitor
10395 ****************************************************************/
10397 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10398 struct spoolss_DeleteMonitor *r)
10400 p->rng_fault_state = true;
10401 return WERR_NOT_SUPPORTED;
10404 /****************************************************************
10405 _spoolss_DeletePrintProcessor
10406 ****************************************************************/
10408 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10409 struct spoolss_DeletePrintProcessor *r)
10411 p->rng_fault_state = true;
10412 return WERR_NOT_SUPPORTED;
10415 /****************************************************************
10416 _spoolss_AddPrintProvidor
10417 ****************************************************************/
10419 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10420 struct spoolss_AddPrintProvidor *r)
10422 p->rng_fault_state = true;
10423 return WERR_NOT_SUPPORTED;
10426 /****************************************************************
10427 _spoolss_DeletePrintProvidor
10428 ****************************************************************/
10430 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10431 struct spoolss_DeletePrintProvidor *r)
10433 p->rng_fault_state = true;
10434 return WERR_NOT_SUPPORTED;
10437 /****************************************************************
10438 _spoolss_FindFirstPrinterChangeNotification
10439 ****************************************************************/
10441 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10442 struct spoolss_FindFirstPrinterChangeNotification *r)
10444 p->rng_fault_state = true;
10445 return WERR_NOT_SUPPORTED;
10448 /****************************************************************
10449 _spoolss_FindNextPrinterChangeNotification
10450 ****************************************************************/
10452 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10453 struct spoolss_FindNextPrinterChangeNotification *r)
10455 p->rng_fault_state = true;
10456 return WERR_NOT_SUPPORTED;
10459 /****************************************************************
10460 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10461 ****************************************************************/
10463 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10464 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10466 p->rng_fault_state = true;
10467 return WERR_NOT_SUPPORTED;
10470 /****************************************************************
10471 _spoolss_ReplyOpenPrinter
10472 ****************************************************************/
10474 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10475 struct spoolss_ReplyOpenPrinter *r)
10477 p->rng_fault_state = true;
10478 return WERR_NOT_SUPPORTED;
10481 /****************************************************************
10482 _spoolss_RouterReplyPrinter
10483 ****************************************************************/
10485 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10486 struct spoolss_RouterReplyPrinter *r)
10488 p->rng_fault_state = true;
10489 return WERR_NOT_SUPPORTED;
10492 /****************************************************************
10493 _spoolss_ReplyClosePrinter
10494 ****************************************************************/
10496 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10497 struct spoolss_ReplyClosePrinter *r)
10499 p->rng_fault_state = true;
10500 return WERR_NOT_SUPPORTED;
10503 /****************************************************************
10505 ****************************************************************/
10507 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10508 struct spoolss_AddPortEx *r)
10510 p->rng_fault_state = true;
10511 return WERR_NOT_SUPPORTED;
10514 /****************************************************************
10515 _spoolss_RouterFindFirstPrinterChangeNotification
10516 ****************************************************************/
10518 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10519 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10521 p->rng_fault_state = true;
10522 return WERR_NOT_SUPPORTED;
10525 /****************************************************************
10526 _spoolss_SpoolerInit
10527 ****************************************************************/
10529 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10530 struct spoolss_SpoolerInit *r)
10532 p->rng_fault_state = true;
10533 return WERR_NOT_SUPPORTED;
10536 /****************************************************************
10537 _spoolss_ResetPrinterEx
10538 ****************************************************************/
10540 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10541 struct spoolss_ResetPrinterEx *r)
10543 p->rng_fault_state = true;
10544 return WERR_NOT_SUPPORTED;
10547 /****************************************************************
10548 _spoolss_RouterReplyPrinterEx
10549 ****************************************************************/
10551 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10552 struct spoolss_RouterReplyPrinterEx *r)
10554 p->rng_fault_state = true;
10555 return WERR_NOT_SUPPORTED;
10558 /****************************************************************
10560 ****************************************************************/
10562 WERROR _spoolss_44(struct pipes_struct *p,
10563 struct spoolss_44 *r)
10565 p->rng_fault_state = true;
10566 return WERR_NOT_SUPPORTED;
10569 /****************************************************************
10571 ****************************************************************/
10573 WERROR _spoolss_SetPort(struct pipes_struct *p,
10574 struct spoolss_SetPort *r)
10576 p->rng_fault_state = true;
10577 return WERR_NOT_SUPPORTED;
10580 /****************************************************************
10582 ****************************************************************/
10584 WERROR _spoolss_4a(struct pipes_struct *p,
10585 struct spoolss_4a *r)
10587 p->rng_fault_state = true;
10588 return WERR_NOT_SUPPORTED;
10591 /****************************************************************
10593 ****************************************************************/
10595 WERROR _spoolss_4b(struct pipes_struct *p,
10596 struct spoolss_4b *r)
10598 p->rng_fault_state = true;
10599 return WERR_NOT_SUPPORTED;
10602 /****************************************************************
10604 ****************************************************************/
10606 WERROR _spoolss_4c(struct pipes_struct *p,
10607 struct spoolss_4c *r)
10609 p->rng_fault_state = true;
10610 return WERR_NOT_SUPPORTED;
10613 /****************************************************************
10615 ****************************************************************/
10617 WERROR _spoolss_53(struct pipes_struct *p,
10618 struct spoolss_53 *r)
10620 p->rng_fault_state = true;
10621 return WERR_NOT_SUPPORTED;
10624 /****************************************************************
10625 _spoolss_AddPerMachineConnection
10626 ****************************************************************/
10628 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10629 struct spoolss_AddPerMachineConnection *r)
10631 p->rng_fault_state = true;
10632 return WERR_NOT_SUPPORTED;
10635 /****************************************************************
10636 _spoolss_DeletePerMachineConnection
10637 ****************************************************************/
10639 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10640 struct spoolss_DeletePerMachineConnection *r)
10642 p->rng_fault_state = true;
10643 return WERR_NOT_SUPPORTED;
10646 /****************************************************************
10647 _spoolss_EnumPerMachineConnections
10648 ****************************************************************/
10650 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10651 struct spoolss_EnumPerMachineConnections *r)
10653 p->rng_fault_state = true;
10654 return WERR_NOT_SUPPORTED;
10657 /****************************************************************
10659 ****************************************************************/
10661 WERROR _spoolss_5a(struct pipes_struct *p,
10662 struct spoolss_5a *r)
10664 p->rng_fault_state = true;
10665 return WERR_NOT_SUPPORTED;
10668 /****************************************************************
10670 ****************************************************************/
10672 WERROR _spoolss_5b(struct pipes_struct *p,
10673 struct spoolss_5b *r)
10675 p->rng_fault_state = true;
10676 return WERR_NOT_SUPPORTED;
10679 /****************************************************************
10681 ****************************************************************/
10683 WERROR _spoolss_5c(struct pipes_struct *p,
10684 struct spoolss_5c *r)
10686 p->rng_fault_state = true;
10687 return WERR_NOT_SUPPORTED;
10690 /****************************************************************
10692 ****************************************************************/
10694 WERROR _spoolss_5d(struct pipes_struct *p,
10695 struct spoolss_5d *r)
10697 p->rng_fault_state = true;
10698 return WERR_NOT_SUPPORTED;
10701 /****************************************************************
10703 ****************************************************************/
10705 WERROR _spoolss_5e(struct pipes_struct *p,
10706 struct spoolss_5e *r)
10708 p->rng_fault_state = true;
10709 return WERR_NOT_SUPPORTED;
10712 /****************************************************************
10714 ****************************************************************/
10716 WERROR _spoolss_5f(struct pipes_struct *p,
10717 struct spoolss_5f *r)
10719 p->rng_fault_state = true;
10720 return WERR_NOT_SUPPORTED;
10723 /****************************************************************
10725 ****************************************************************/
10727 WERROR _spoolss_60(struct pipes_struct *p,
10728 struct spoolss_60 *r)
10730 p->rng_fault_state = true;
10731 return WERR_NOT_SUPPORTED;
10734 /****************************************************************
10736 ****************************************************************/
10738 WERROR _spoolss_61(struct pipes_struct *p,
10739 struct spoolss_61 *r)
10741 p->rng_fault_state = true;
10742 return WERR_NOT_SUPPORTED;
10745 /****************************************************************
10747 ****************************************************************/
10749 WERROR _spoolss_62(struct pipes_struct *p,
10750 struct spoolss_62 *r)
10752 p->rng_fault_state = true;
10753 return WERR_NOT_SUPPORTED;
10756 /****************************************************************
10758 ****************************************************************/
10760 WERROR _spoolss_63(struct pipes_struct *p,
10761 struct spoolss_63 *r)
10763 p->rng_fault_state = true;
10764 return WERR_NOT_SUPPORTED;
10767 /****************************************************************
10769 ****************************************************************/
10771 WERROR _spoolss_64(struct pipes_struct *p,
10772 struct spoolss_64 *r)
10774 p->rng_fault_state = true;
10775 return WERR_NOT_SUPPORTED;
10778 /****************************************************************
10780 ****************************************************************/
10782 WERROR _spoolss_65(struct pipes_struct *p,
10783 struct spoolss_65 *r)
10785 p->rng_fault_state = true;
10786 return WERR_NOT_SUPPORTED;
10789 /****************************************************************
10790 _spoolss_GetCorePrinterDrivers
10791 ****************************************************************/
10793 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10794 struct spoolss_GetCorePrinterDrivers *r)
10796 p->rng_fault_state = true;
10797 return WERR_NOT_SUPPORTED;
10800 /****************************************************************
10802 ****************************************************************/
10804 WERROR _spoolss_67(struct pipes_struct *p,
10805 struct spoolss_67 *r)
10807 p->rng_fault_state = true;
10808 return WERR_NOT_SUPPORTED;
10811 /****************************************************************
10812 _spoolss_GetPrinterDriverPackagePath
10813 ****************************************************************/
10815 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10816 struct spoolss_GetPrinterDriverPackagePath *r)
10818 p->rng_fault_state = true;
10819 return WERR_NOT_SUPPORTED;
10822 /****************************************************************
10824 ****************************************************************/
10826 WERROR _spoolss_69(struct pipes_struct *p,
10827 struct spoolss_69 *r)
10829 p->rng_fault_state = true;
10830 return WERR_NOT_SUPPORTED;
10833 /****************************************************************
10835 ****************************************************************/
10837 WERROR _spoolss_6a(struct pipes_struct *p,
10838 struct spoolss_6a *r)
10840 p->rng_fault_state = true;
10841 return WERR_NOT_SUPPORTED;
10844 /****************************************************************
10846 ****************************************************************/
10848 WERROR _spoolss_6b(struct pipes_struct *p,
10849 struct spoolss_6b *r)
10851 p->rng_fault_state = true;
10852 return WERR_NOT_SUPPORTED;
10855 /****************************************************************
10857 ****************************************************************/
10859 WERROR _spoolss_6c(struct pipes_struct *p,
10860 struct spoolss_6c *r)
10862 p->rng_fault_state = true;
10863 return WERR_NOT_SUPPORTED;
10866 /****************************************************************
10868 ****************************************************************/
10870 WERROR _spoolss_6d(struct pipes_struct *p,
10871 struct spoolss_6d *r)
10873 p->rng_fault_state = true;
10874 return WERR_NOT_SUPPORTED;