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,
2145 get_session_info_system(),
2148 status = WERR_PRINTER_DRIVER_IN_USE;
2153 status = winreg_get_driver(tmp_ctx, b,
2155 r->in.driver, 3, &info_win2k);
2156 if (W_ERROR_IS_OK(status)) {
2157 /* if we get to here, we now have 2 driver info structures to remove */
2158 /* remove the Win2k driver first*/
2160 status = winreg_del_driver(tmp_ctx, b,
2162 talloc_free(info_win2k);
2164 /* this should not have failed---if it did, report to client */
2165 if (!W_ERROR_IS_OK(status)) {
2171 status = winreg_del_driver(tmp_ctx, b,
2175 talloc_free(tmp_ctx);
2180 /****************************************************************
2181 _spoolss_DeletePrinterDriverEx
2182 ****************************************************************/
2184 WERROR _spoolss_DeletePrinterDriverEx(struct pipes_struct *p,
2185 struct spoolss_DeletePrinterDriverEx *r)
2187 struct spoolss_DriverInfo8 *info = NULL;
2188 struct spoolss_DriverInfo8 *info_win2k = NULL;
2192 struct dcerpc_binding_handle *b;
2193 TALLOC_CTX *tmp_ctx = NULL;
2195 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2196 and not a printer admin, then fail */
2198 if ( (p->session_info->unix_token->uid != sec_initial_uid())
2199 && !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR)
2200 && !token_contains_name_in_list(
2201 uidtoname(p->session_info->unix_token->uid),
2202 p->session_info->info->domain_name,
2204 p->session_info->security_token, lp_printer_admin(-1)) )
2206 return WERR_ACCESS_DENIED;
2209 /* check that we have a valid driver name first */
2210 if ((version = get_version_id(r->in.architecture)) == -1) {
2211 /* this is what NT returns */
2212 return WERR_INVALID_ENVIRONMENT;
2215 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) {
2216 version = r->in.version;
2219 tmp_ctx = talloc_new(p->mem_ctx);
2224 status = winreg_printer_binding_handle(tmp_ctx,
2225 get_session_info_system(),
2228 if (!W_ERROR_IS_OK(status)) {
2232 status = winreg_get_driver(tmp_ctx, b,
2237 if (!W_ERROR_IS_OK(status)) {
2238 status = WERR_UNKNOWN_PRINTER_DRIVER;
2241 * if the client asked for a specific version,
2242 * or this is something other than Windows NT x86,
2246 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2249 /* try for Win2k driver if "Windows NT x86" */
2252 status = winreg_get_driver(tmp_ctx, b,
2256 if (!W_ERROR_IS_OK(status)) {
2257 status = WERR_UNKNOWN_PRINTER_DRIVER;
2262 if (printer_driver_in_use(tmp_ctx,
2263 get_session_info_system(),
2266 status = WERR_PRINTER_DRIVER_IN_USE;
2271 * we have a couple of cases to consider.
2272 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2273 * then the delete should fail if **any** files overlap with
2275 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2276 * non-overlapping files
2277 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2278 * is set, the do not delete any files
2279 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2282 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2284 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2287 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2288 printer_driver_files_in_use(tmp_ctx,
2289 get_session_info_system(),
2292 /* no idea of the correct error here */
2293 status = WERR_ACCESS_DENIED;
2298 /* also check for W32X86/3 if necessary; maybe we already have? */
2300 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2301 status = winreg_get_driver(tmp_ctx, b,
2303 r->in.driver, 3, &info_win2k);
2304 if (W_ERROR_IS_OK(status)) {
2307 (r->in.delete_flags & DPD_DELETE_ALL_FILES) &&
2308 printer_driver_files_in_use(info,
2309 get_session_info_system(),
2312 /* no idea of the correct error here */
2313 talloc_free(info_win2k);
2314 status = WERR_ACCESS_DENIED;
2318 /* if we get to here, we now have 2 driver info structures to remove */
2319 /* remove the Win2k driver first*/
2321 status = winreg_del_driver(tmp_ctx, b,
2325 /* this should not have failed---if it did, report to client */
2327 if (!W_ERROR_IS_OK(status)) {
2332 * now delete any associated files if delete_files is
2333 * true. Even if this part failes, we return succes
2334 * because the driver doesn not exist any more
2337 delete_driver_files(get_session_info_system(),
2343 status = winreg_del_driver(tmp_ctx, b,
2346 if (!W_ERROR_IS_OK(status)) {
2351 * now delete any associated files if delete_files is
2352 * true. Even if this part failes, we return succes
2353 * because the driver doesn not exist any more
2356 delete_driver_files(get_session_info_system(), info);
2360 talloc_free(tmp_ctx);
2365 /********************************************************************
2366 GetPrinterData on a printer server Handle.
2367 ********************************************************************/
2369 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2371 enum winreg_Type *type,
2372 union spoolss_PrinterData *data)
2374 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2376 if (!strcasecmp_m(value, "W3SvcInstalled")) {
2382 if (!strcasecmp_m(value, "BeepEnabled")) {
2388 if (!strcasecmp_m(value, "EventLog")) {
2390 /* formally was 0x1b */
2395 if (!strcasecmp_m(value, "NetPopup")) {
2401 if (!strcasecmp_m(value, "MajorVersion")) {
2404 /* Windows NT 4.0 seems to not allow uploading of drivers
2405 to a server that reports 0x3 as the MajorVersion.
2406 need to investigate more how Win2k gets around this .
2409 if (RA_WINNT == get_remote_arch()) {
2418 if (!strcasecmp_m(value, "MinorVersion")) {
2425 * uint32_t size = 0x114
2426 * uint32_t major = 5
2427 * uint32_t minor = [0|1]
2428 * uint32_t build = [2195|2600]
2429 * extra unicode string = e.g. "Service Pack 3"
2431 if (!strcasecmp_m(value, "OSVersion")) {
2433 enum ndr_err_code ndr_err;
2434 struct spoolss_OSVersion os;
2436 os.major = 5; /* Windows 2000 == 5.0 */
2438 os.build = 2195; /* build */
2439 os.extra_string = ""; /* leave extra string empty */
2441 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os,
2442 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2443 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2444 return WERR_GENERAL_FAILURE;
2448 data->binary = blob;
2454 if (!strcasecmp_m(value, "DefaultSpoolDirectory")) {
2457 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2458 W_ERROR_HAVE_NO_MEMORY(data->string);
2463 if (!strcasecmp_m(value, "Architecture")) {
2465 data->string = talloc_strdup(mem_ctx,
2466 lp_parm_const_string(GLOBAL_SECTION_SNUM, "spoolss", "architecture", SPOOLSS_ARCHITECTURE_NT_X86));
2467 W_ERROR_HAVE_NO_MEMORY(data->string);
2472 if (!strcasecmp_m(value, "DsPresent")) {
2475 /* only show the publish check box if we are a
2476 member of a AD domain */
2478 if (lp_security() == SEC_ADS) {
2486 if (!strcasecmp_m(value, "DNSMachineName")) {
2487 const char *hostname = get_mydnsfullname();
2490 return WERR_BADFILE;
2494 data->string = talloc_strdup(mem_ctx, hostname);
2495 W_ERROR_HAVE_NO_MEMORY(data->string);
2502 return WERR_INVALID_PARAM;
2505 /****************************************************************
2506 _spoolss_GetPrinterData
2507 ****************************************************************/
2509 WERROR _spoolss_GetPrinterData(struct pipes_struct *p,
2510 struct spoolss_GetPrinterData *r)
2512 struct spoolss_GetPrinterDataEx r2;
2514 r2.in.handle = r->in.handle;
2515 r2.in.key_name = "PrinterDriverData";
2516 r2.in.value_name = r->in.value_name;
2517 r2.in.offered = r->in.offered;
2518 r2.out.type = r->out.type;
2519 r2.out.data = r->out.data;
2520 r2.out.needed = r->out.needed;
2522 return _spoolss_GetPrinterDataEx(p, &r2);
2525 /*********************************************************
2526 Connect to the client machine.
2527 **********************************************************/
2529 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2530 struct sockaddr_storage *client_ss, const char *remote_machine)
2533 struct cli_state *the_cli;
2534 struct sockaddr_storage rm_addr;
2535 char addr[INET6_ADDRSTRLEN];
2537 if ( is_zero_addr(client_ss) ) {
2538 DEBUG(2,("spoolss_connect_to_client: resolving %s\n",
2540 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2541 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2544 print_sockaddr(addr, sizeof(addr), &rm_addr);
2546 rm_addr = *client_ss;
2547 print_sockaddr(addr, sizeof(addr), &rm_addr);
2548 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2552 if (ismyaddr((struct sockaddr *)(void *)&rm_addr)) {
2553 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n",
2558 /* setup the connection */
2559 ret = cli_full_connection( &the_cli, lp_netbios_name(), remote_machine,
2560 &rm_addr, 0, "IPC$", "IPC",
2564 0, lp_client_signing());
2566 if ( !NT_STATUS_IS_OK( ret ) ) {
2567 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2572 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2573 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2574 cli_shutdown(the_cli);
2579 * Ok - we have an anonymous connection to the IPC$ share.
2580 * Now start the NT Domain stuff :-).
2583 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2584 if (!NT_STATUS_IS_OK(ret)) {
2585 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2586 remote_machine, nt_errstr(ret)));
2587 cli_shutdown(the_cli);
2594 /***************************************************************************
2595 Connect to the client.
2596 ****************************************************************************/
2598 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2599 uint32_t localprinter,
2600 enum winreg_Type type,
2601 struct policy_handle *handle,
2602 struct notify_back_channel **_chan,
2603 struct sockaddr_storage *client_ss,
2604 struct messaging_context *msg_ctx)
2608 struct notify_back_channel *chan;
2610 for (chan = back_channels; chan; chan = chan->next) {
2611 if (memcmp(&chan->client_address, client_ss,
2612 sizeof(struct sockaddr_storage)) == 0) {
2618 * If it's the first connection, contact the client
2619 * and connect to the IPC$ share anonymously
2622 fstring unix_printer;
2624 /* the +2 is to strip the leading 2 backslashs */
2625 fstrcpy(unix_printer, printer + 2);
2627 chan = talloc_zero(back_channels, struct notify_back_channel);
2631 chan->client_address = *client_ss;
2633 if (!spoolss_connect_to_client(&chan->cli_pipe, client_ss, unix_printer)) {
2637 chan->binding_handle = chan->cli_pipe->binding_handle;
2639 DLIST_ADD(back_channels, chan);
2641 messaging_register(msg_ctx, NULL, MSG_PRINTER_NOTIFY2,
2642 receive_notify2_message_list);
2643 /* Tell the connections db we're now interested in printer
2644 * notify messages. */
2645 serverid_register_msg_flags(messaging_server_id(msg_ctx),
2646 true, FLAG_MSG_PRINT_NOTIFY);
2650 * Tell the specific printing tdb we want messages for this printer
2651 * by registering our PID.
2654 if (!print_notify_register_pid(snum)) {
2655 DEBUG(0, ("Failed to register our pid for printer %s\n",
2659 status = dcerpc_spoolss_ReplyOpenPrinter(chan->binding_handle,
2668 if (!NT_STATUS_IS_OK(status)) {
2669 DEBUG(5, ("dcerpc_spoolss_ReplyOpenPrinter returned [%s]\n", nt_errstr(status)));
2670 result = ntstatus_to_werror(status);
2671 } else if (!W_ERROR_IS_OK(result)) {
2672 DEBUG(5, ("ReplyOpenPrinter returned [%s]\n", win_errstr(result)));
2675 chan->active_connections++;
2678 return (W_ERROR_IS_OK(result));
2681 /****************************************************************
2682 ****************************************************************/
2684 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2685 const struct spoolss_NotifyOption *r)
2687 struct spoolss_NotifyOption *option;
2694 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2701 if (!option->count) {
2705 option->types = talloc_zero_array(option,
2706 struct spoolss_NotifyOptionType, option->count);
2707 if (!option->types) {
2708 talloc_free(option);
2712 for (i=0; i < option->count; i++) {
2713 option->types[i] = r->types[i];
2715 if (option->types[i].count) {
2716 option->types[i].fields = talloc_zero_array(option,
2717 union spoolss_Field, option->types[i].count);
2718 if (!option->types[i].fields) {
2719 talloc_free(option);
2722 for (k=0; k<option->types[i].count; k++) {
2723 option->types[i].fields[k] =
2724 r->types[i].fields[k];
2732 /****************************************************************
2733 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2735 * before replying OK: status=0 a rpc call is made to the workstation
2736 * asking ReplyOpenPrinter
2738 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2739 * called from api_spoolss_rffpcnex
2740 ****************************************************************/
2742 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(struct pipes_struct *p,
2743 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2746 struct spoolss_NotifyOption *option = r->in.notify_options;
2747 struct sockaddr_storage client_ss;
2748 socklen_t client_len;
2750 /* store the notify value in the printer struct */
2752 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
2755 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2756 "Invalid handle (%s:%u:%u).\n",
2757 OUR_HANDLE(r->in.handle)));
2761 Printer->notify.flags = r->in.flags;
2762 Printer->notify.options = r->in.options;
2763 Printer->notify.printerlocal = r->in.printer_local;
2764 Printer->notify.msg_ctx = p->msg_ctx;
2766 TALLOC_FREE(Printer->notify.option);
2767 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2769 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2771 /* Connect to the client machine and send a ReplyOpenPrinter */
2773 if ( Printer->printer_type == SPLHND_SERVER)
2775 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2776 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2779 DEBUG(10,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2780 "remote_address is %s\n",
2781 tsocket_address_string(p->remote_address, p->mem_ctx)));
2783 if (!lp_print_notify_backchannel(snum)) {
2784 DEBUG(10, ("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2785 "backchannel disabled\n"));
2786 return WERR_SERVER_UNAVAILABLE;
2789 client_len = tsocket_address_bsd_sockaddr(p->remote_address,
2790 (struct sockaddr *) &client_ss,
2791 sizeof(struct sockaddr_storage));
2792 if (client_len < 0) {
2796 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2797 Printer->notify.printerlocal, REG_SZ,
2798 &Printer->notify.cli_hnd,
2799 &Printer->notify.cli_chan,
2800 &client_ss, p->msg_ctx)) {
2801 return WERR_SERVER_UNAVAILABLE;
2807 /*******************************************************************
2808 * fill a notify_info_data with the servername
2809 ********************************************************************/
2811 static void spoolss_notify_server_name(struct messaging_context *msg_ctx,
2813 struct spoolss_Notify *data,
2814 print_queue_struct *queue,
2815 struct spoolss_PrinterInfo2 *pinfo2,
2816 TALLOC_CTX *mem_ctx)
2818 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->servername);
2821 /*******************************************************************
2822 * fill a notify_info_data with the printername (not including the servername).
2823 ********************************************************************/
2825 static void spoolss_notify_printer_name(struct messaging_context *msg_ctx,
2827 struct spoolss_Notify *data,
2828 print_queue_struct *queue,
2829 struct spoolss_PrinterInfo2 *pinfo2,
2830 TALLOC_CTX *mem_ctx)
2832 /* the notify name should not contain the \\server\ part */
2833 const char *p = strrchr(pinfo2->printername, '\\');
2836 p = pinfo2->printername;
2841 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2844 /*******************************************************************
2845 * fill a notify_info_data with the servicename
2846 ********************************************************************/
2848 static void spoolss_notify_share_name(struct messaging_context *msg_ctx,
2850 struct spoolss_Notify *data,
2851 print_queue_struct *queue,
2852 struct spoolss_PrinterInfo2 *pinfo2,
2853 TALLOC_CTX *mem_ctx)
2855 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2858 /*******************************************************************
2859 * fill a notify_info_data with the port name
2860 ********************************************************************/
2862 static void spoolss_notify_port_name(struct messaging_context *msg_ctx,
2864 struct spoolss_Notify *data,
2865 print_queue_struct *queue,
2866 struct spoolss_PrinterInfo2 *pinfo2,
2867 TALLOC_CTX *mem_ctx)
2869 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->portname);
2872 /*******************************************************************
2873 * fill a notify_info_data with the printername
2874 * but it doesn't exist, have to see what to do
2875 ********************************************************************/
2877 static void spoolss_notify_driver_name(struct messaging_context *msg_ctx,
2879 struct spoolss_Notify *data,
2880 print_queue_struct *queue,
2881 struct spoolss_PrinterInfo2 *pinfo2,
2882 TALLOC_CTX *mem_ctx)
2884 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->drivername);
2887 /*******************************************************************
2888 * fill a notify_info_data with the comment
2889 ********************************************************************/
2891 static void spoolss_notify_comment(struct messaging_context *msg_ctx,
2893 struct spoolss_Notify *data,
2894 print_queue_struct *queue,
2895 struct spoolss_PrinterInfo2 *pinfo2,
2896 TALLOC_CTX *mem_ctx)
2900 if (*pinfo2->comment == '\0') {
2901 p = lp_comment(snum);
2903 p = pinfo2->comment;
2906 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2909 /*******************************************************************
2910 * fill a notify_info_data with the comment
2911 * location = "Room 1, floor 2, building 3"
2912 ********************************************************************/
2914 static void spoolss_notify_location(struct messaging_context *msg_ctx,
2916 struct spoolss_Notify *data,
2917 print_queue_struct *queue,
2918 struct spoolss_PrinterInfo2 *pinfo2,
2919 TALLOC_CTX *mem_ctx)
2921 const char *loc = pinfo2->location;
2924 status = printer_list_get_printer(mem_ctx,
2929 if (NT_STATUS_IS_OK(status)) {
2931 loc = pinfo2->location;
2935 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, loc);
2938 /*******************************************************************
2939 * fill a notify_info_data with the device mode
2940 * jfm:xxxx don't to it for know but that's a real problem !!!
2941 ********************************************************************/
2943 static void spoolss_notify_devmode(struct messaging_context *msg_ctx,
2945 struct spoolss_Notify *data,
2946 print_queue_struct *queue,
2947 struct spoolss_PrinterInfo2 *pinfo2,
2948 TALLOC_CTX *mem_ctx)
2950 /* for a dummy implementation we have to zero the fields */
2951 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2954 /*******************************************************************
2955 * fill a notify_info_data with the separator file name
2956 ********************************************************************/
2958 static void spoolss_notify_sepfile(struct messaging_context *msg_ctx,
2960 struct spoolss_Notify *data,
2961 print_queue_struct *queue,
2962 struct spoolss_PrinterInfo2 *pinfo2,
2963 TALLOC_CTX *mem_ctx)
2965 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->sepfile);
2968 /*******************************************************************
2969 * fill a notify_info_data with the print processor
2970 * jfm:xxxx return always winprint to indicate we don't do anything to it
2971 ********************************************************************/
2973 static void spoolss_notify_print_processor(struct messaging_context *msg_ctx,
2975 struct spoolss_Notify *data,
2976 print_queue_struct *queue,
2977 struct spoolss_PrinterInfo2 *pinfo2,
2978 TALLOC_CTX *mem_ctx)
2980 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->printprocessor);
2983 /*******************************************************************
2984 * fill a notify_info_data with the print processor options
2985 * jfm:xxxx send an empty string
2986 ********************************************************************/
2988 static void spoolss_notify_parameters(struct messaging_context *msg_ctx,
2990 struct spoolss_Notify *data,
2991 print_queue_struct *queue,
2992 struct spoolss_PrinterInfo2 *pinfo2,
2993 TALLOC_CTX *mem_ctx)
2995 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->parameters);
2998 /*******************************************************************
2999 * fill a notify_info_data with the data type
3000 * jfm:xxxx always send RAW as data type
3001 ********************************************************************/
3003 static void spoolss_notify_datatype(struct messaging_context *msg_ctx,
3005 struct spoolss_Notify *data,
3006 print_queue_struct *queue,
3007 struct spoolss_PrinterInfo2 *pinfo2,
3008 TALLOC_CTX *mem_ctx)
3010 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, pinfo2->datatype);
3013 /*******************************************************************
3014 * fill a notify_info_data with the security descriptor
3015 * jfm:xxxx send an null pointer to say no security desc
3016 * have to implement security before !
3017 ********************************************************************/
3019 static void spoolss_notify_security_desc(struct messaging_context *msg_ctx,
3021 struct spoolss_Notify *data,
3022 print_queue_struct *queue,
3023 struct spoolss_PrinterInfo2 *pinfo2,
3024 TALLOC_CTX *mem_ctx)
3026 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data, pinfo2->secdesc);
3029 /*******************************************************************
3030 * fill a notify_info_data with the attributes
3031 * jfm:xxxx a samba printer is always shared
3032 ********************************************************************/
3034 static void spoolss_notify_attributes(struct messaging_context *msg_ctx,
3036 struct spoolss_Notify *data,
3037 print_queue_struct *queue,
3038 struct spoolss_PrinterInfo2 *pinfo2,
3039 TALLOC_CTX *mem_ctx)
3041 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->attributes);
3044 /*******************************************************************
3045 * fill a notify_info_data with the priority
3046 ********************************************************************/
3048 static void spoolss_notify_priority(struct messaging_context *msg_ctx,
3050 struct spoolss_Notify *data,
3051 print_queue_struct *queue,
3052 struct spoolss_PrinterInfo2 *pinfo2,
3053 TALLOC_CTX *mem_ctx)
3055 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->priority);
3058 /*******************************************************************
3059 * fill a notify_info_data with the default priority
3060 ********************************************************************/
3062 static void spoolss_notify_default_priority(struct messaging_context *msg_ctx,
3064 struct spoolss_Notify *data,
3065 print_queue_struct *queue,
3066 struct spoolss_PrinterInfo2 *pinfo2,
3067 TALLOC_CTX *mem_ctx)
3069 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->defaultpriority);
3072 /*******************************************************************
3073 * fill a notify_info_data with the start time
3074 ********************************************************************/
3076 static void spoolss_notify_start_time(struct messaging_context *msg_ctx,
3078 struct spoolss_Notify *data,
3079 print_queue_struct *queue,
3080 struct spoolss_PrinterInfo2 *pinfo2,
3081 TALLOC_CTX *mem_ctx)
3083 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->starttime);
3086 /*******************************************************************
3087 * fill a notify_info_data with the until time
3088 ********************************************************************/
3090 static void spoolss_notify_until_time(struct messaging_context *msg_ctx,
3092 struct spoolss_Notify *data,
3093 print_queue_struct *queue,
3094 struct spoolss_PrinterInfo2 *pinfo2,
3095 TALLOC_CTX *mem_ctx)
3097 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->untiltime);
3100 /*******************************************************************
3101 * fill a notify_info_data with the status
3102 ********************************************************************/
3104 static void spoolss_notify_status(struct messaging_context *msg_ctx,
3106 struct spoolss_Notify *data,
3107 print_queue_struct *queue,
3108 struct spoolss_PrinterInfo2 *pinfo2,
3109 TALLOC_CTX *mem_ctx)
3111 print_status_struct status;
3113 print_queue_length(msg_ctx, snum, &status);
3114 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
3117 /*******************************************************************
3118 * fill a notify_info_data with the number of jobs queued
3119 ********************************************************************/
3121 static void spoolss_notify_cjobs(struct messaging_context *msg_ctx,
3123 struct spoolss_Notify *data,
3124 print_queue_struct *queue,
3125 struct spoolss_PrinterInfo2 *pinfo2,
3126 TALLOC_CTX *mem_ctx)
3128 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(
3129 data, print_queue_length(msg_ctx, snum, NULL));
3132 /*******************************************************************
3133 * fill a notify_info_data with the average ppm
3134 ********************************************************************/
3136 static void spoolss_notify_average_ppm(struct messaging_context *msg_ctx,
3138 struct spoolss_Notify *data,
3139 print_queue_struct *queue,
3140 struct spoolss_PrinterInfo2 *pinfo2,
3141 TALLOC_CTX *mem_ctx)
3143 /* always respond 8 pages per minutes */
3144 /* a little hard ! */
3145 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, pinfo2->averageppm);
3148 /*******************************************************************
3149 * fill a notify_info_data with username
3150 ********************************************************************/
3152 static void spoolss_notify_username(struct messaging_context *msg_ctx,
3154 struct spoolss_Notify *data,
3155 print_queue_struct *queue,
3156 struct spoolss_PrinterInfo2 *pinfo2,
3157 TALLOC_CTX *mem_ctx)
3159 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
3162 /*******************************************************************
3163 * fill a notify_info_data with job status
3164 ********************************************************************/
3166 static void spoolss_notify_job_status(struct messaging_context *msg_ctx,
3168 struct spoolss_Notify *data,
3169 print_queue_struct *queue,
3170 struct spoolss_PrinterInfo2 *pinfo2,
3171 TALLOC_CTX *mem_ctx)
3173 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
3176 /*******************************************************************
3177 * fill a notify_info_data with job name
3178 ********************************************************************/
3180 static void spoolss_notify_job_name(struct messaging_context *msg_ctx,
3182 struct spoolss_Notify *data,
3183 print_queue_struct *queue,
3184 struct spoolss_PrinterInfo2 *pinfo2,
3185 TALLOC_CTX *mem_ctx)
3187 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
3190 /*******************************************************************
3191 * fill a notify_info_data with job status
3192 ********************************************************************/
3194 static void spoolss_notify_job_status_string(struct messaging_context *msg_ctx,
3196 struct spoolss_Notify *data,
3197 print_queue_struct *queue,
3198 struct spoolss_PrinterInfo2 *pinfo2,
3199 TALLOC_CTX *mem_ctx)
3202 * Now we're returning job status codes we just return a "" here. JRA.
3207 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3210 switch (queue->status) {
3215 p = ""; /* NT provides the paused string */
3224 #endif /* NO LONGER NEEDED. */
3226 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
3229 /*******************************************************************
3230 * fill a notify_info_data with job time
3231 ********************************************************************/
3233 static void spoolss_notify_job_time(struct messaging_context *msg_ctx,
3235 struct spoolss_Notify *data,
3236 print_queue_struct *queue,
3237 struct spoolss_PrinterInfo2 *pinfo2,
3238 TALLOC_CTX *mem_ctx)
3240 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3243 /*******************************************************************
3244 * fill a notify_info_data with job size
3245 ********************************************************************/
3247 static void spoolss_notify_job_size(struct messaging_context *msg_ctx,
3249 struct spoolss_Notify *data,
3250 print_queue_struct *queue,
3251 struct spoolss_PrinterInfo2 *pinfo2,
3252 TALLOC_CTX *mem_ctx)
3254 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
3257 /*******************************************************************
3258 * fill a notify_info_data with page info
3259 ********************************************************************/
3260 static void spoolss_notify_total_pages(struct messaging_context *msg_ctx,
3262 struct spoolss_Notify *data,
3263 print_queue_struct *queue,
3264 struct spoolss_PrinterInfo2 *pinfo2,
3265 TALLOC_CTX *mem_ctx)
3267 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
3270 /*******************************************************************
3271 * fill a notify_info_data with pages printed info.
3272 ********************************************************************/
3273 static void spoolss_notify_pages_printed(struct messaging_context *msg_ctx,
3275 struct spoolss_Notify *data,
3276 print_queue_struct *queue,
3277 struct spoolss_PrinterInfo2 *pinfo2,
3278 TALLOC_CTX *mem_ctx)
3280 /* Add code when back-end tracks this */
3281 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3284 /*******************************************************************
3285 Fill a notify_info_data with job position.
3286 ********************************************************************/
3288 static void spoolss_notify_job_position(struct messaging_context *msg_ctx,
3290 struct spoolss_Notify *data,
3291 print_queue_struct *queue,
3292 struct spoolss_PrinterInfo2 *pinfo2,
3293 TALLOC_CTX *mem_ctx)
3295 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3298 /*******************************************************************
3299 Fill a notify_info_data with submitted time.
3300 ********************************************************************/
3302 static void spoolss_notify_submitted_time(struct messaging_context *msg_ctx,
3304 struct spoolss_Notify *data,
3305 print_queue_struct *queue,
3306 struct spoolss_PrinterInfo2 *pinfo2,
3307 TALLOC_CTX *mem_ctx)
3309 data->data.string.string = NULL;
3310 data->data.string.size = 0;
3312 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3313 &data->data.string.string,
3314 &data->data.string.size);
3318 struct s_notify_info_data_table
3320 enum spoolss_NotifyType type;
3323 enum spoolss_NotifyTable variable_type;
3324 void (*fn) (struct messaging_context *msg_ctx,
3325 int snum, struct spoolss_Notify *data,
3326 print_queue_struct *queue,
3327 struct spoolss_PrinterInfo2 *pinfo2,
3328 TALLOC_CTX *mem_ctx);
3331 /* A table describing the various print notification constants and
3332 whether the notification data is a pointer to a variable sized
3333 buffer, a one value uint32_t or a two value uint32_t. */
3335 static const struct s_notify_info_data_table notify_info_data_table[] =
3337 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3338 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3339 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3340 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3341 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3342 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3343 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3344 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3345 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3346 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3347 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3348 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3349 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3350 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3351 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3352 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3353 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3354 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3355 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3356 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3357 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3358 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3359 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3360 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3361 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3362 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3363 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3364 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3365 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3366 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3367 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3368 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3369 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3370 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3371 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3372 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3373 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3374 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3375 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3376 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3377 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3378 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3379 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3380 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3381 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3382 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3383 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3384 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3385 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3388 /*******************************************************************
3389 Return the variable_type of info_data structure.
3390 ********************************************************************/
3392 static enum spoolss_NotifyTable variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3397 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3398 if ( (notify_info_data_table[i].type == type) &&
3399 (notify_info_data_table[i].field == field) ) {
3400 return notify_info_data_table[i].variable_type;
3404 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3406 return (enum spoolss_NotifyTable) 0;
3409 /****************************************************************************
3410 ****************************************************************************/
3412 static bool search_notify(enum spoolss_NotifyType type,
3418 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3419 if (notify_info_data_table[i].type == type &&
3420 notify_info_data_table[i].field == field &&
3421 notify_info_data_table[i].fn != NULL) {
3430 /****************************************************************************
3431 ****************************************************************************/
3433 static void construct_info_data(struct spoolss_Notify *info_data,
3434 enum spoolss_NotifyType type,
3435 uint16_t field, int id)
3437 info_data->type = type;
3438 info_data->field.field = field;
3439 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3440 info_data->job_id = id;
3443 /*******************************************************************
3445 * fill a notify_info struct with info asked
3447 ********************************************************************/
3449 static bool construct_notify_printer_info(struct messaging_context *msg_ctx,
3450 struct printer_handle *print_hnd,
3451 struct spoolss_NotifyInfo *info,
3452 struct spoolss_PrinterInfo2 *pinfo2,
3454 const struct spoolss_NotifyOptionType *option_type,
3456 TALLOC_CTX *mem_ctx)
3459 enum spoolss_NotifyType type;
3462 struct spoolss_Notify *current_data;
3464 type = option_type->type;
3466 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3467 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3468 option_type->count, lp_servicename(snum)));
3470 for(field_num=0; field_num < option_type->count; field_num++) {
3471 field = option_type->fields[field_num].field;
3473 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3475 if (!search_notify(type, field, &j) )
3478 info->notifies = talloc_realloc(info, info->notifies,
3479 struct spoolss_Notify,
3481 if (info->notifies == NULL) {
3482 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3486 current_data = &info->notifies[info->count];
3488 construct_info_data(current_data, type, field, id);
3490 DEBUG(10, ("construct_notify_printer_info: "
3491 "calling [%s] snum=%d printername=[%s])\n",
3492 notify_info_data_table[j].name, snum,
3493 pinfo2->printername));
3495 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3496 NULL, pinfo2, mem_ctx);
3504 /*******************************************************************
3506 * fill a notify_info struct with info asked
3508 ********************************************************************/
3510 static bool construct_notify_jobs_info(struct messaging_context *msg_ctx,
3511 print_queue_struct *queue,
3512 struct spoolss_NotifyInfo *info,
3513 struct spoolss_PrinterInfo2 *pinfo2,
3515 const struct spoolss_NotifyOptionType *option_type,
3517 TALLOC_CTX *mem_ctx)
3520 enum spoolss_NotifyType type;
3522 struct spoolss_Notify *current_data;
3524 DEBUG(4,("construct_notify_jobs_info\n"));
3526 type = option_type->type;
3528 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3529 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3530 option_type->count));
3532 for(field_num=0; field_num<option_type->count; field_num++) {
3533 field = option_type->fields[field_num].field;
3535 if (!search_notify(type, field, &j) )
3538 info->notifies = talloc_realloc(info, info->notifies,
3539 struct spoolss_Notify,
3541 if (info->notifies == NULL) {
3542 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3546 current_data=&(info->notifies[info->count]);
3548 construct_info_data(current_data, type, field, id);
3549 notify_info_data_table[j].fn(msg_ctx, snum, current_data,
3550 queue, pinfo2, mem_ctx);
3558 * JFM: The enumeration is not that simple, it's even non obvious.
3560 * let's take an example: I want to monitor the PRINTER SERVER for
3561 * the printer's name and the number of jobs currently queued.
3562 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3563 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3565 * I have 3 printers on the back of my server.
3567 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3570 * 1 printer 1 name 1
3571 * 2 printer 1 cjob 1
3572 * 3 printer 2 name 2
3573 * 4 printer 2 cjob 2
3574 * 5 printer 3 name 3
3575 * 6 printer 3 name 3
3577 * that's the print server case, the printer case is even worse.
3580 /*******************************************************************
3582 * enumerate all printers on the printserver
3583 * fill a notify_info struct with info asked
3585 ********************************************************************/
3587 static WERROR printserver_notify_info(struct pipes_struct *p,
3588 struct policy_handle *hnd,
3589 struct spoolss_NotifyInfo *info,
3590 TALLOC_CTX *mem_ctx)
3593 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3594 int n_services=lp_numservices();
3596 struct spoolss_NotifyOption *option;
3597 struct spoolss_NotifyOptionType option_type;
3598 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3601 DEBUG(4,("printserver_notify_info\n"));
3606 option = Printer->notify.option;
3609 info->notifies = NULL;
3612 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3613 sending a ffpcn() request first */
3618 for (i=0; i<option->count; i++) {
3619 option_type = option->types[i];
3621 if (option_type.type != PRINTER_NOTIFY_TYPE)
3624 for (snum = 0; snum < n_services; snum++) {
3625 if (!lp_browseable(snum) ||
3626 !lp_snum_ok(snum) ||
3627 !lp_print_ok(snum)) {
3628 continue; /* skip */
3631 /* Maybe we should use the SYSTEM session_info here... */
3632 result = winreg_get_printer_internal(mem_ctx,
3633 get_session_info_system(),
3635 lp_servicename(snum),
3637 if (!W_ERROR_IS_OK(result)) {
3638 DEBUG(4, ("printserver_notify_info: "
3639 "Failed to get printer [%s]\n",
3640 lp_servicename(snum)));
3645 construct_notify_printer_info(p->msg_ctx,
3651 TALLOC_FREE(pinfo2);
3657 * Debugging information, don't delete.
3660 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3661 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3662 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3664 for (i=0; i<info->count; i++) {
3665 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3666 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3667 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3674 /*******************************************************************
3676 * fill a notify_info struct with info asked
3678 ********************************************************************/
3680 static WERROR printer_notify_info(struct pipes_struct *p,
3681 struct policy_handle *hnd,
3682 struct spoolss_NotifyInfo *info,
3683 TALLOC_CTX *mem_ctx)
3686 struct printer_handle *Printer = find_printer_index_by_hnd(p, hnd);
3689 struct spoolss_NotifyOption *option;
3690 struct spoolss_NotifyOptionType option_type;
3692 print_queue_struct *queue=NULL;
3693 print_status_struct status;
3694 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
3697 DEBUG(4,("printer_notify_info\n"));
3702 option = Printer->notify.option;
3706 info->notifies = NULL;
3709 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3710 sending a ffpcn() request first */
3715 if (!get_printer_snum(p, hnd, &snum, NULL)) {
3719 /* Maybe we should use the SYSTEM session_info here... */
3720 result = winreg_get_printer_internal(mem_ctx,
3721 get_session_info_system(),
3723 lp_servicename(snum), &pinfo2);
3724 if (!W_ERROR_IS_OK(result)) {
3728 for (i=0; i<option->count; i++) {
3729 option_type = option->types[i];
3731 switch (option_type.type) {
3732 case PRINTER_NOTIFY_TYPE:
3733 if (construct_notify_printer_info(p->msg_ctx,
3742 case JOB_NOTIFY_TYPE:
3744 count = print_queue_status(p->msg_ctx, snum, &queue,
3747 for (j=0; j<count; j++) {
3748 construct_notify_jobs_info(p->msg_ctx,
3762 * Debugging information, don't delete.
3765 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3766 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3767 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3769 for (i=0; i<info->count; i++) {
3770 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3771 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3772 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3776 talloc_free(pinfo2);
3780 /****************************************************************
3781 _spoolss_RouterRefreshPrinterChangeNotify
3782 ****************************************************************/
3784 WERROR _spoolss_RouterRefreshPrinterChangeNotify(struct pipes_struct *p,
3785 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3787 struct spoolss_NotifyInfo *info;
3789 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
3790 WERROR result = WERR_BADFID;
3792 /* we always have a spoolss_NotifyInfo struct */
3793 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3795 result = WERR_NOMEM;
3799 *r->out.info = info;
3802 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3803 "Invalid handle (%s:%u:%u).\n",
3804 OUR_HANDLE(r->in.handle)));
3808 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3811 * We are now using the change value, and
3812 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3813 * I don't have a global notification system, I'm sending back all the
3814 * information even when _NOTHING_ has changed.
3817 /* We need to keep track of the change value to send back in
3818 RRPCN replies otherwise our updates are ignored. */
3820 Printer->notify.fnpcn = true;
3822 if (Printer->notify.cli_chan != NULL &&
3823 Printer->notify.cli_chan->active_connections > 0) {
3824 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3825 "Saving change value in request [%x]\n",
3827 Printer->notify.change = r->in.change_low;
3830 /* just ignore the spoolss_NotifyOption */
3832 switch (Printer->printer_type) {
3834 result = printserver_notify_info(p, r->in.handle,
3838 case SPLHND_PRINTER:
3839 result = printer_notify_info(p, r->in.handle,
3844 Printer->notify.fnpcn = false;
3850 /********************************************************************
3851 ********************************************************************/
3853 static WERROR create_printername(TALLOC_CTX *mem_ctx,
3854 const char *servername,
3855 const char *printername,
3856 const char **printername_p)
3858 /* FIXME: add lp_force_printername() */
3860 if (servername == NULL) {
3861 *printername_p = talloc_strdup(mem_ctx, printername);
3862 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3866 if (servername[0] == '\\' && servername[1] == '\\') {
3870 *printername_p = talloc_asprintf(mem_ctx, "\\\\%s\\%s", servername, printername);
3871 W_ERROR_HAVE_NO_MEMORY(*printername_p);
3876 /********************************************************************
3877 ********************************************************************/
3879 static void compose_devicemode_devicename(struct spoolss_DeviceMode *dm,
3880 const char *printername)
3886 dm->devicename = talloc_strndup(dm, printername,
3887 MIN(strlen(printername), 31));
3890 /********************************************************************
3891 * construct_printer_info_0
3892 * fill a printer_info_0 struct
3893 ********************************************************************/
3895 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3896 const struct auth_session_info *session_info,
3897 struct messaging_context *msg_ctx,
3898 struct spoolss_PrinterInfo2 *info2,
3899 const char *servername,
3900 struct spoolss_PrinterInfo0 *r,
3904 struct printer_session_counter *session_counter;
3905 struct timeval setuptime;
3906 print_status_struct status;
3909 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
3910 if (!W_ERROR_IS_OK(result)) {
3915 r->servername = talloc_strdup(mem_ctx, servername);
3916 W_ERROR_HAVE_NO_MEMORY(r->servername);
3918 r->servername = NULL;
3921 count = print_queue_length(msg_ctx, snum, &status);
3923 /* check if we already have a counter for this printer */
3924 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3925 if (session_counter->snum == snum)
3929 /* it's the first time, add it to the list */
3930 if (session_counter == NULL) {
3931 session_counter = talloc_zero(counter_list, struct printer_session_counter);
3932 W_ERROR_HAVE_NO_MEMORY(session_counter);
3933 session_counter->snum = snum;
3934 session_counter->counter = 0;
3935 DLIST_ADD(counter_list, session_counter);
3939 session_counter->counter++;
3945 get_startup_time(&setuptime);
3946 init_systemtime(&r->time, gmtime(&setuptime.tv_sec));
3949 * the global_counter should be stored in a TDB as it's common to all the clients
3950 * and should be zeroed on samba startup
3952 r->global_counter = session_counter->counter;
3954 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
3955 SSVAL(&r->version, 0, 0x0005); /* NT 5 */
3956 SSVAL(&r->version, 2, 0x0893); /* build 2195 */
3957 r->free_build = SPOOLSS_RELEASE_BUILD;
3959 r->max_spooling = 0;
3960 r->session_counter = session_counter->counter;
3961 r->num_error_out_of_paper = 0x0;
3962 r->num_error_not_ready = 0x0; /* number of print failure */
3964 r->number_of_processors = 0x1;
3965 r->processor_type = PROCESSOR_INTEL_PENTIUM; /* 586 Pentium ? */
3966 r->high_part_total_bytes = 0x0;
3968 /* ChangeID in milliseconds*/
3969 winreg_printer_get_changeid_internal(mem_ctx, session_info, msg_ctx,
3970 info2->sharename, &r->change_id);
3972 r->last_error = WERR_OK;
3973 r->status = nt_printq_status(status.status);
3974 r->enumerate_network_printers = 0x0;
3975 r->c_setprinter = 0x0;
3976 r->processor_architecture = PROCESSOR_ARCHITECTURE_INTEL;
3977 r->processor_level = 0x6; /* 6 ???*/
3986 /********************************************************************
3987 * construct_printer_info1
3988 * fill a spoolss_PrinterInfo1 struct
3989 ********************************************************************/
3991 static WERROR construct_printer_info1(TALLOC_CTX *mem_ctx,
3992 const struct spoolss_PrinterInfo2 *info2,
3994 const char *servername,
3995 struct spoolss_PrinterInfo1 *r,
4002 if (info2->comment == NULL || info2->comment[0] == '\0') {
4003 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4005 r->comment = talloc_strdup(mem_ctx, info2->comment); /* saved comment */
4007 W_ERROR_HAVE_NO_MEMORY(r->comment);
4009 result = create_printername(mem_ctx, servername, info2->printername, &r->name);
4010 if (!W_ERROR_IS_OK(result)) {
4014 r->description = talloc_asprintf(mem_ctx, "%s,%s,%s",
4018 W_ERROR_HAVE_NO_MEMORY(r->description);
4023 /********************************************************************
4024 * construct_printer_info2
4025 * fill a spoolss_PrinterInfo2 struct
4026 ********************************************************************/
4028 static WERROR construct_printer_info2(TALLOC_CTX *mem_ctx,
4029 struct messaging_context *msg_ctx,
4030 const struct spoolss_PrinterInfo2 *info2,
4031 const char *servername,
4032 struct spoolss_PrinterInfo2 *r,
4036 print_status_struct status;
4039 count = print_queue_length(msg_ctx, snum, &status);
4042 r->servername = talloc_strdup(mem_ctx, servername);
4043 W_ERROR_HAVE_NO_MEMORY(r->servername);
4045 r->servername = NULL;
4048 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4049 if (!W_ERROR_IS_OK(result)) {
4053 r->sharename = talloc_strdup(mem_ctx, lp_servicename(snum));
4054 W_ERROR_HAVE_NO_MEMORY(r->sharename);
4055 r->portname = talloc_strdup(mem_ctx, info2->portname);
4056 W_ERROR_HAVE_NO_MEMORY(r->portname);
4057 r->drivername = talloc_strdup(mem_ctx, info2->drivername);
4058 W_ERROR_HAVE_NO_MEMORY(r->drivername);
4060 if (info2->comment[0] == '\0') {
4061 r->comment = talloc_strdup(mem_ctx, lp_comment(snum));
4063 r->comment = talloc_strdup(mem_ctx, info2->comment);
4065 W_ERROR_HAVE_NO_MEMORY(r->comment);
4067 r->location = talloc_strdup(mem_ctx, info2->location);
4068 if (info2->location[0] == '\0') {
4069 const char *loc = NULL;
4072 nt_status = printer_list_get_printer(mem_ctx,
4077 if (NT_STATUS_IS_OK(nt_status)) {
4079 r->location = talloc_strdup(mem_ctx, loc);
4083 W_ERROR_HAVE_NO_MEMORY(r->location);
4085 r->sepfile = talloc_strdup(mem_ctx, info2->sepfile);
4086 W_ERROR_HAVE_NO_MEMORY(r->sepfile);
4087 r->printprocessor = talloc_strdup(mem_ctx, info2->printprocessor);
4088 W_ERROR_HAVE_NO_MEMORY(r->printprocessor);
4089 r->datatype = talloc_strdup(mem_ctx, info2->datatype);
4090 W_ERROR_HAVE_NO_MEMORY(r->datatype);
4091 r->parameters = talloc_strdup(mem_ctx, info2->parameters);
4092 W_ERROR_HAVE_NO_MEMORY(r->parameters);
4094 r->attributes = info2->attributes;
4096 r->priority = info2->priority;
4097 r->defaultpriority = info2->defaultpriority;
4098 r->starttime = info2->starttime;
4099 r->untiltime = info2->untiltime;
4100 r->status = nt_printq_status(status.status);
4102 r->averageppm = info2->averageppm;
4104 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4106 DEBUG(8,("Returning NULL Devicemode!\n"));
4109 compose_devicemode_devicename(r->devmode, r->printername);
4113 if (info2->secdesc != NULL) {
4114 /* don't use talloc_steal() here unless you do a deep steal of all
4115 the SEC_DESC members */
4117 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4123 /********************************************************************
4124 * construct_printer_info3
4125 * fill a spoolss_PrinterInfo3 struct
4126 ********************************************************************/
4128 static WERROR construct_printer_info3(TALLOC_CTX *mem_ctx,
4129 const struct spoolss_PrinterInfo2 *info2,
4130 const char *servername,
4131 struct spoolss_PrinterInfo3 *r,
4134 /* These are the components of the SD we are returning. */
4136 if (info2->secdesc != NULL) {
4137 /* don't use talloc_steal() here unless you do a deep steal of all
4138 the SEC_DESC members */
4140 r->secdesc = dup_sec_desc(mem_ctx, info2->secdesc);
4141 W_ERROR_HAVE_NO_MEMORY(r->secdesc);
4147 /********************************************************************
4148 * construct_printer_info4
4149 * fill a spoolss_PrinterInfo4 struct
4150 ********************************************************************/
4152 static WERROR construct_printer_info4(TALLOC_CTX *mem_ctx,
4153 const struct spoolss_PrinterInfo2 *info2,
4154 const char *servername,
4155 struct spoolss_PrinterInfo4 *r,
4160 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4161 if (!W_ERROR_IS_OK(result)) {
4166 r->servername = talloc_strdup(mem_ctx, servername);
4167 W_ERROR_HAVE_NO_MEMORY(r->servername);
4169 r->servername = NULL;
4172 r->attributes = info2->attributes;
4177 /********************************************************************
4178 * construct_printer_info5
4179 * fill a spoolss_PrinterInfo5 struct
4180 ********************************************************************/
4182 static WERROR construct_printer_info5(TALLOC_CTX *mem_ctx,
4183 const struct spoolss_PrinterInfo2 *info2,
4184 const char *servername,
4185 struct spoolss_PrinterInfo5 *r,
4190 result = create_printername(mem_ctx, servername, info2->printername, &r->printername);
4191 if (!W_ERROR_IS_OK(result)) {
4195 r->portname = talloc_strdup(mem_ctx, info2->portname);
4196 W_ERROR_HAVE_NO_MEMORY(r->portname);
4198 r->attributes = info2->attributes;
4200 /* these two are not used by NT+ according to MSDN */
4201 r->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4202 r->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4207 /********************************************************************
4208 * construct_printer_info_6
4209 * fill a spoolss_PrinterInfo6 struct
4210 ********************************************************************/
4212 static WERROR construct_printer_info6(TALLOC_CTX *mem_ctx,
4213 struct messaging_context *msg_ctx,
4214 const struct spoolss_PrinterInfo2 *info2,
4215 const char *servername,
4216 struct spoolss_PrinterInfo6 *r,
4219 print_status_struct status;
4221 print_queue_length(msg_ctx, snum, &status);
4223 r->status = nt_printq_status(status.status);
4228 /********************************************************************
4229 * construct_printer_info7
4230 * fill a spoolss_PrinterInfo7 struct
4231 ********************************************************************/
4233 static WERROR construct_printer_info7(TALLOC_CTX *mem_ctx,
4234 struct messaging_context *msg_ctx,
4235 const char *servername,
4236 struct spoolss_PrinterInfo7 *r,
4239 const struct auth_session_info *session_info = get_session_info_system();
4242 if (is_printer_published(mem_ctx, session_info, msg_ctx,
4244 lp_servicename(snum), &guid, NULL)) {
4245 r->guid = talloc_strdup_upper(mem_ctx, GUID_string2(mem_ctx, &guid));
4246 r->action = DSPRINT_PUBLISH;
4248 r->guid = talloc_strdup(mem_ctx, "");
4249 r->action = DSPRINT_UNPUBLISH;
4251 W_ERROR_HAVE_NO_MEMORY(r->guid);
4256 /********************************************************************
4257 * construct_printer_info8
4258 * fill a spoolss_PrinterInfo8 struct
4259 ********************************************************************/
4261 static WERROR construct_printer_info8(TALLOC_CTX *mem_ctx,
4262 const struct spoolss_PrinterInfo2 *info2,
4263 const char *servername,
4264 struct spoolss_DeviceModeInfo *r,
4268 const char *printername;
4270 result = create_printername(mem_ctx, servername, info2->printername, &printername);
4271 if (!W_ERROR_IS_OK(result)) {
4275 copy_devicemode(mem_ctx, info2->devmode, &r->devmode);
4277 DEBUG(8,("Returning NULL Devicemode!\n"));
4280 compose_devicemode_devicename(r->devmode, printername);
4286 /********************************************************************
4287 ********************************************************************/
4289 static bool snum_is_shared_printer(int snum)
4291 return (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum));
4294 /********************************************************************
4295 Spoolss_enumprinters.
4296 ********************************************************************/
4298 static WERROR enum_all_printers_info_level(TALLOC_CTX *mem_ctx,
4299 const struct auth_session_info *session_info,
4300 struct messaging_context *msg_ctx,
4301 const char *servername,
4304 union spoolss_PrinterInfo **info_p,
4308 int n_services = lp_numservices();
4309 union spoolss_PrinterInfo *info = NULL;
4311 WERROR result = WERR_OK;
4312 struct dcerpc_binding_handle *b = NULL;
4313 TALLOC_CTX *tmp_ctx = NULL;
4315 tmp_ctx = talloc_new(mem_ctx);
4323 for (snum = 0; snum < n_services; snum++) {
4325 const char *printer;
4326 struct spoolss_PrinterInfo2 *info2;
4328 if (!snum_is_shared_printer(snum)) {
4332 printer = lp_const_servicename(snum);
4334 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n",
4338 result = winreg_printer_binding_handle(tmp_ctx,
4342 if (!W_ERROR_IS_OK(result)) {
4347 result = winreg_create_printer(tmp_ctx, b,
4349 if (!W_ERROR_IS_OK(result)) {
4353 info = talloc_realloc(tmp_ctx, info,
4354 union spoolss_PrinterInfo,
4357 result = WERR_NOMEM;
4361 result = winreg_get_printer(tmp_ctx, b,
4363 if (!W_ERROR_IS_OK(result)) {
4369 result = construct_printer_info0(info, session_info,
4372 &info[count].info0, snum);
4375 result = construct_printer_info1(info, info2, flags,
4377 &info[count].info1, snum);
4380 result = construct_printer_info2(info, msg_ctx, info2,
4382 &info[count].info2, snum);
4385 result = construct_printer_info4(info, info2,
4387 &info[count].info4, snum);
4390 result = construct_printer_info5(info, info2,
4392 &info[count].info5, snum);
4396 result = WERR_UNKNOWN_LEVEL;
4400 if (!W_ERROR_IS_OK(result)) {
4408 if (W_ERROR_IS_OK(result)) {
4409 *info_p = talloc_move(mem_ctx, &info);
4413 talloc_free(tmp_ctx);
4418 /********************************************************************
4419 * handle enumeration of printers at level 0
4420 ********************************************************************/
4422 static WERROR enumprinters_level0(TALLOC_CTX *mem_ctx,
4423 const struct auth_session_info *session_info,
4424 struct messaging_context *msg_ctx,
4426 const char *servername,
4427 union spoolss_PrinterInfo **info,
4430 DEBUG(4,("enum_all_printers_info_0\n"));
4432 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4433 servername, 0, flags, info, count);
4437 /********************************************************************
4438 ********************************************************************/
4440 static WERROR enum_all_printers_info_1(TALLOC_CTX *mem_ctx,
4441 const struct auth_session_info *session_info,
4442 struct messaging_context *msg_ctx,
4443 const char *servername,
4445 union spoolss_PrinterInfo **info,
4448 DEBUG(4,("enum_all_printers_info_1\n"));
4450 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4451 servername, 1, flags, info, count);
4454 /********************************************************************
4455 enum_all_printers_info_1_local.
4456 *********************************************************************/
4458 static WERROR enum_all_printers_info_1_local(TALLOC_CTX *mem_ctx,
4459 const struct auth_session_info *session_info,
4460 struct messaging_context *msg_ctx,
4461 const char *servername,
4462 union spoolss_PrinterInfo **info,
4465 DEBUG(4,("enum_all_printers_info_1_local\n"));
4467 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4468 servername, PRINTER_ENUM_ICON8, info, count);
4471 /********************************************************************
4472 enum_all_printers_info_1_name.
4473 *********************************************************************/
4475 static WERROR enum_all_printers_info_1_name(TALLOC_CTX *mem_ctx,
4476 const struct auth_session_info *session_info,
4477 struct messaging_context *msg_ctx,
4478 const char *servername,
4479 union spoolss_PrinterInfo **info,
4482 const char *s = servername;
4484 DEBUG(4,("enum_all_printers_info_1_name\n"));
4486 if ((servername[0] == '\\') && (servername[1] == '\\')) {
4490 if (!is_myname_or_ipaddr(s)) {
4491 return WERR_INVALID_NAME;
4494 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4495 servername, PRINTER_ENUM_ICON8, info, count);
4498 /********************************************************************
4499 enum_all_printers_info_1_network.
4500 *********************************************************************/
4502 static WERROR enum_all_printers_info_1_network(TALLOC_CTX *mem_ctx,
4503 const struct auth_session_info *session_info,
4504 struct messaging_context *msg_ctx,
4505 const char *servername,
4506 union spoolss_PrinterInfo **info,
4509 const char *s = servername;
4511 DEBUG(4,("enum_all_printers_info_1_network\n"));
4513 /* If we respond to a enum_printers level 1 on our name with flags
4514 set to PRINTER_ENUM_REMOTE with a list of printers then these
4515 printers incorrectly appear in the APW browse list.
4516 Specifically the printers for the server appear at the workgroup
4517 level where all the other servers in the domain are
4518 listed. Windows responds to this call with a
4519 WERR_CAN_NOT_COMPLETE so we should do the same. */
4521 if (servername[0] == '\\' && servername[1] == '\\') {
4525 if (is_myname_or_ipaddr(s)) {
4526 return WERR_CAN_NOT_COMPLETE;
4529 return enum_all_printers_info_1(mem_ctx, session_info, msg_ctx,
4530 servername, PRINTER_ENUM_NAME, info, count);
4533 /********************************************************************
4534 * api_spoolss_enumprinters
4536 * called from api_spoolss_enumprinters (see this to understand)
4537 ********************************************************************/
4539 static WERROR enum_all_printers_info_2(TALLOC_CTX *mem_ctx,
4540 const struct auth_session_info *session_info,
4541 struct messaging_context *msg_ctx,
4542 const char *servername,
4543 union spoolss_PrinterInfo **info,
4546 DEBUG(4,("enum_all_printers_info_2\n"));
4548 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4549 servername, 2, 0, info, count);
4552 /********************************************************************
4553 * handle enumeration of printers at level 1
4554 ********************************************************************/
4556 static WERROR enumprinters_level1(TALLOC_CTX *mem_ctx,
4557 const struct auth_session_info *session_info,
4558 struct messaging_context *msg_ctx,
4560 const char *servername,
4561 union spoolss_PrinterInfo **info,
4564 /* Not all the flags are equals */
4566 if (flags & PRINTER_ENUM_LOCAL) {
4567 return enum_all_printers_info_1_local(mem_ctx, session_info,
4568 msg_ctx, servername, info, count);
4571 if (flags & PRINTER_ENUM_NAME) {
4572 return enum_all_printers_info_1_name(mem_ctx, session_info,
4573 msg_ctx, servername, info,
4577 if (flags & PRINTER_ENUM_NETWORK) {
4578 return enum_all_printers_info_1_network(mem_ctx, session_info,
4579 msg_ctx, servername, info,
4583 return WERR_OK; /* NT4sp5 does that */
4586 /********************************************************************
4587 * handle enumeration of printers at level 2
4588 ********************************************************************/
4590 static WERROR enumprinters_level2(TALLOC_CTX *mem_ctx,
4591 const struct auth_session_info *session_info,
4592 struct messaging_context *msg_ctx,
4594 const char *servername,
4595 union spoolss_PrinterInfo **info,
4598 if (flags & PRINTER_ENUM_LOCAL) {
4600 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4605 if (flags & PRINTER_ENUM_NAME) {
4606 if (servername && !is_myname_or_ipaddr(canon_servername(servername))) {
4607 return WERR_INVALID_NAME;
4610 return enum_all_printers_info_2(mem_ctx, session_info, msg_ctx,
4615 if (flags & PRINTER_ENUM_REMOTE) {
4616 return WERR_UNKNOWN_LEVEL;
4622 /********************************************************************
4623 * handle enumeration of printers at level 4
4624 ********************************************************************/
4626 static WERROR enumprinters_level4(TALLOC_CTX *mem_ctx,
4627 const struct auth_session_info *session_info,
4628 struct messaging_context *msg_ctx,
4630 const char *servername,
4631 union spoolss_PrinterInfo **info,
4634 DEBUG(4,("enum_all_printers_info_4\n"));
4636 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4637 servername, 4, flags, info, count);
4641 /********************************************************************
4642 * handle enumeration of printers at level 5
4643 ********************************************************************/
4645 static WERROR enumprinters_level5(TALLOC_CTX *mem_ctx,
4646 const struct auth_session_info *session_info,
4647 struct messaging_context *msg_ctx,
4649 const char *servername,
4650 union spoolss_PrinterInfo **info,
4653 DEBUG(4,("enum_all_printers_info_5\n"));
4655 return enum_all_printers_info_level(mem_ctx, session_info, msg_ctx,
4656 servername, 5, flags, info, count);
4659 /****************************************************************
4660 _spoolss_EnumPrinters
4661 ****************************************************************/
4663 WERROR _spoolss_EnumPrinters(struct pipes_struct *p,
4664 struct spoolss_EnumPrinters *r)
4666 const struct auth_session_info *session_info = get_session_info_system();
4669 /* that's an [in out] buffer */
4671 if (!r->in.buffer && (r->in.offered != 0)) {
4672 return WERR_INVALID_PARAM;
4675 DEBUG(4,("_spoolss_EnumPrinters\n"));
4679 *r->out.info = NULL;
4683 * flags==PRINTER_ENUM_NAME
4684 * if name=="" then enumerates all printers
4685 * if name!="" then enumerate the printer
4686 * flags==PRINTER_ENUM_REMOTE
4687 * name is NULL, enumerate printers
4688 * Level 2: name!="" enumerates printers, name can't be NULL
4689 * Level 3: doesn't exist
4690 * Level 4: does a local registry lookup
4691 * Level 5: same as Level 2
4694 if (r->in.server && r->in.server[0] == '\0') {
4695 r->in.server = NULL;
4698 switch (r->in.level) {
4700 result = enumprinters_level0(p->mem_ctx, session_info,
4701 p->msg_ctx, r->in.flags,
4703 r->out.info, r->out.count);
4706 result = enumprinters_level1(p->mem_ctx, session_info,
4707 p->msg_ctx, r->in.flags,
4709 r->out.info, r->out.count);
4712 result = enumprinters_level2(p->mem_ctx, session_info,
4713 p->msg_ctx, r->in.flags,
4715 r->out.info, r->out.count);
4718 result = enumprinters_level4(p->mem_ctx, session_info,
4719 p->msg_ctx, r->in.flags,
4721 r->out.info, r->out.count);
4724 result = enumprinters_level5(p->mem_ctx, session_info,
4725 p->msg_ctx, r->in.flags,
4727 r->out.info, r->out.count);
4730 return WERR_UNKNOWN_LEVEL;
4733 if (!W_ERROR_IS_OK(result)) {
4737 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
4738 spoolss_EnumPrinters,
4739 *r->out.info, r->in.level,
4741 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
4742 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
4744 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4747 /****************************************************************
4749 ****************************************************************/
4751 WERROR _spoolss_GetPrinter(struct pipes_struct *p,
4752 struct spoolss_GetPrinter *r)
4754 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
4755 struct spoolss_PrinterInfo2 *info2 = NULL;
4756 WERROR result = WERR_OK;
4759 /* that's an [in out] buffer */
4761 if (!r->in.buffer && (r->in.offered != 0)) {
4762 return WERR_INVALID_PARAM;
4767 if (Printer == NULL) {
4771 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
4775 result = winreg_get_printer_internal(p->mem_ctx,
4776 get_session_info_system(),
4778 lp_const_servicename(snum),
4780 if (!W_ERROR_IS_OK(result)) {
4784 switch (r->in.level) {
4786 result = construct_printer_info0(p->mem_ctx,
4787 get_session_info_system(),
4790 Printer->servername,
4791 &r->out.info->info0,
4795 result = construct_printer_info1(p->mem_ctx, info2,
4797 Printer->servername,
4798 &r->out.info->info1, snum);
4801 result = construct_printer_info2(p->mem_ctx, p->msg_ctx, info2,
4802 Printer->servername,
4803 &r->out.info->info2, snum);
4806 result = construct_printer_info3(p->mem_ctx, info2,
4807 Printer->servername,
4808 &r->out.info->info3, snum);
4811 result = construct_printer_info4(p->mem_ctx, info2,
4812 Printer->servername,
4813 &r->out.info->info4, snum);
4816 result = construct_printer_info5(p->mem_ctx, info2,
4817 Printer->servername,
4818 &r->out.info->info5, snum);
4821 result = construct_printer_info6(p->mem_ctx, p->msg_ctx, info2,
4822 Printer->servername,
4823 &r->out.info->info6, snum);
4826 result = construct_printer_info7(p->mem_ctx, p->msg_ctx,
4827 Printer->servername,
4828 &r->out.info->info7, snum);
4831 result = construct_printer_info8(p->mem_ctx, info2,
4832 Printer->servername,
4833 &r->out.info->info8, snum);
4836 result = WERR_UNKNOWN_LEVEL;
4842 if (!W_ERROR_IS_OK(result)) {
4843 DEBUG(0, ("_spoolss_GetPrinter: failed to construct printer info level %d - %s\n",
4844 r->in.level, win_errstr(result)));
4845 TALLOC_FREE(r->out.info);
4849 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrinterInfo,
4850 r->out.info, r->in.level);
4851 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
4853 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
4856 /********************************************************************
4857 ********************************************************************/
4859 #define FILL_DRIVER_STRING(mem_ctx, in, out) \
4861 if (in && strlen(in)) { \
4862 out = talloc_strdup(mem_ctx, in); \
4864 out = talloc_strdup(mem_ctx, ""); \
4866 W_ERROR_HAVE_NO_MEMORY(out); \
4869 #define FILL_DRIVER_UNC_STRING(mem_ctx, server, arch, ver, in, out) \
4871 if (in && strlen(in)) { \
4872 out = talloc_asprintf(mem_ctx, "\\\\%s\\print$\\%s\\%d\\%s", server, get_short_archi(arch), ver, in); \
4874 out = talloc_strdup(mem_ctx, ""); \
4876 W_ERROR_HAVE_NO_MEMORY(out); \
4879 static WERROR string_array_from_driver_info(TALLOC_CTX *mem_ctx,
4880 const char **string_array,
4881 const char ***presult,
4882 const char *cservername,
4886 int i, num_strings = 0;
4887 const char **array = NULL;
4889 if (string_array == NULL) {
4890 return WERR_INVALID_PARAMETER;
4893 for (i=0; string_array[i] && string_array[i][0] != '\0'; i++) {
4894 const char *str = NULL;
4896 if (cservername == NULL || arch == NULL) {
4897 FILL_DRIVER_STRING(mem_ctx, string_array[i], str);
4899 FILL_DRIVER_UNC_STRING(mem_ctx, cservername, arch, version, string_array[i], str);
4902 if (!add_string_to_array(mem_ctx, str, &array, &num_strings)) {
4909 ADD_TO_ARRAY(mem_ctx, const char *, NULL,
4910 &array, &num_strings);
4920 /********************************************************************
4921 * fill a spoolss_DriverInfo1 struct
4922 ********************************************************************/
4924 static WERROR fill_printer_driver_info1(TALLOC_CTX *mem_ctx,
4925 struct spoolss_DriverInfo1 *r,
4926 const struct spoolss_DriverInfo8 *driver,
4927 const char *servername)
4929 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4930 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4935 /********************************************************************
4936 * fill a spoolss_DriverInfo2 struct
4937 ********************************************************************/
4939 static WERROR fill_printer_driver_info2(TALLOC_CTX *mem_ctx,
4940 struct spoolss_DriverInfo2 *r,
4941 const struct spoolss_DriverInfo8 *driver,
4942 const char *servername)
4945 const char *cservername = canon_servername(servername);
4947 r->version = driver->version;
4949 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4950 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4951 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4952 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4954 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4955 driver->architecture,
4957 driver->driver_path,
4960 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4961 driver->architecture,
4966 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4967 driver->architecture,
4969 driver->config_file,
4975 /********************************************************************
4976 * fill a spoolss_DriverInfo3 struct
4977 ********************************************************************/
4979 static WERROR fill_printer_driver_info3(TALLOC_CTX *mem_ctx,
4980 struct spoolss_DriverInfo3 *r,
4981 const struct spoolss_DriverInfo8 *driver,
4982 const char *servername)
4984 const char *cservername = canon_servername(servername);
4986 r->version = driver->version;
4988 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
4989 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
4990 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
4991 W_ERROR_HAVE_NO_MEMORY(r->architecture);
4993 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
4994 driver->architecture,
4996 driver->driver_path,
4999 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5000 driver->architecture,
5005 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5006 driver->architecture,
5008 driver->config_file,
5011 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5012 driver->architecture,
5017 FILL_DRIVER_STRING(mem_ctx,
5018 driver->monitor_name,
5021 FILL_DRIVER_STRING(mem_ctx,
5022 driver->default_datatype,
5023 r->default_datatype);
5025 return string_array_from_driver_info(mem_ctx,
5026 driver->dependent_files,
5027 &r->dependent_files,
5029 driver->architecture,
5033 /********************************************************************
5034 * fill a spoolss_DriverInfo4 struct
5035 ********************************************************************/
5037 static WERROR fill_printer_driver_info4(TALLOC_CTX *mem_ctx,
5038 struct spoolss_DriverInfo4 *r,
5039 const struct spoolss_DriverInfo8 *driver,
5040 const char *servername)
5042 const char *cservername = canon_servername(servername);
5045 r->version = driver->version;
5047 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5048 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5049 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5050 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5052 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5053 driver->architecture,
5055 driver->driver_path,
5058 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5059 driver->architecture,
5064 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5065 driver->architecture,
5067 driver->config_file,
5070 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5071 driver->architecture,
5076 result = string_array_from_driver_info(mem_ctx,
5077 driver->dependent_files,
5078 &r->dependent_files,
5080 driver->architecture,
5082 if (!W_ERROR_IS_OK(result)) {
5086 FILL_DRIVER_STRING(mem_ctx,
5087 driver->monitor_name,
5090 FILL_DRIVER_STRING(mem_ctx,
5091 driver->default_datatype,
5092 r->default_datatype);
5095 result = string_array_from_driver_info(mem_ctx,
5096 driver->previous_names,
5103 /********************************************************************
5104 * fill a spoolss_DriverInfo5 struct
5105 ********************************************************************/
5107 static WERROR fill_printer_driver_info5(TALLOC_CTX *mem_ctx,
5108 struct spoolss_DriverInfo5 *r,
5109 const struct spoolss_DriverInfo8 *driver,
5110 const char *servername)
5112 const char *cservername = canon_servername(servername);
5114 r->version = driver->version;
5116 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5117 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5118 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5119 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5121 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5122 driver->architecture,
5124 driver->driver_path,
5127 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5128 driver->architecture,
5133 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5134 driver->architecture,
5136 driver->config_file,
5139 r->driver_attributes = 0;
5140 r->config_version = 0;
5141 r->driver_version = 0;
5145 /********************************************************************
5146 * fill a spoolss_DriverInfo6 struct
5147 ********************************************************************/
5149 static WERROR fill_printer_driver_info6(TALLOC_CTX *mem_ctx,
5150 struct spoolss_DriverInfo6 *r,
5151 const struct spoolss_DriverInfo8 *driver,
5152 const char *servername)
5154 const char *cservername = canon_servername(servername);
5157 r->version = driver->version;
5159 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5160 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5161 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5162 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5164 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5165 driver->architecture,
5167 driver->driver_path,
5170 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5171 driver->architecture,
5176 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5177 driver->architecture,
5179 driver->config_file,
5182 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5183 driver->architecture,
5188 FILL_DRIVER_STRING(mem_ctx,
5189 driver->monitor_name,
5192 FILL_DRIVER_STRING(mem_ctx,
5193 driver->default_datatype,
5194 r->default_datatype);
5196 result = string_array_from_driver_info(mem_ctx,
5197 driver->dependent_files,
5198 &r->dependent_files,
5200 driver->architecture,
5202 if (!W_ERROR_IS_OK(result)) {
5206 result = string_array_from_driver_info(mem_ctx,
5207 driver->previous_names,
5210 if (!W_ERROR_IS_OK(result)) {
5214 r->driver_date = driver->driver_date;
5215 r->driver_version = driver->driver_version;
5217 FILL_DRIVER_STRING(mem_ctx,
5218 driver->manufacturer_name,
5219 r->manufacturer_name);
5220 FILL_DRIVER_STRING(mem_ctx,
5221 driver->manufacturer_url,
5222 r->manufacturer_url);
5223 FILL_DRIVER_STRING(mem_ctx,
5224 driver->hardware_id,
5226 FILL_DRIVER_STRING(mem_ctx,
5233 /********************************************************************
5234 * fill a spoolss_DriverInfo8 struct
5235 ********************************************************************/
5237 static WERROR fill_printer_driver_info8(TALLOC_CTX *mem_ctx,
5238 struct spoolss_DriverInfo8 *r,
5239 const struct spoolss_DriverInfo8 *driver,
5240 const char *servername)
5242 const char *cservername = canon_servername(servername);
5245 r->version = driver->version;
5247 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5248 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5249 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5250 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5252 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5253 driver->architecture,
5255 driver->driver_path,
5258 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5259 driver->architecture,
5264 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5265 driver->architecture,
5267 driver->config_file,
5270 FILL_DRIVER_UNC_STRING(mem_ctx, cservername,
5271 driver->architecture,
5276 FILL_DRIVER_STRING(mem_ctx,
5277 driver->monitor_name,
5280 FILL_DRIVER_STRING(mem_ctx,
5281 driver->default_datatype,
5282 r->default_datatype);
5284 result = string_array_from_driver_info(mem_ctx,
5285 driver->dependent_files,
5286 &r->dependent_files,
5288 driver->architecture,
5290 if (!W_ERROR_IS_OK(result)) {
5294 result = string_array_from_driver_info(mem_ctx,
5295 driver->previous_names,
5298 if (!W_ERROR_IS_OK(result)) {
5302 r->driver_date = driver->driver_date;
5303 r->driver_version = driver->driver_version;
5305 FILL_DRIVER_STRING(mem_ctx,
5306 driver->manufacturer_name,
5307 r->manufacturer_name);
5308 FILL_DRIVER_STRING(mem_ctx,
5309 driver->manufacturer_url,
5310 r->manufacturer_url);
5311 FILL_DRIVER_STRING(mem_ctx,
5312 driver->hardware_id,
5314 FILL_DRIVER_STRING(mem_ctx,
5318 FILL_DRIVER_STRING(mem_ctx,
5319 driver->print_processor,
5320 r->print_processor);
5321 FILL_DRIVER_STRING(mem_ctx,
5322 driver->vendor_setup,
5325 result = string_array_from_driver_info(mem_ctx,
5326 driver->color_profiles,
5329 if (!W_ERROR_IS_OK(result)) {
5333 FILL_DRIVER_STRING(mem_ctx,
5337 r->printer_driver_attributes = driver->printer_driver_attributes;
5339 result = string_array_from_driver_info(mem_ctx,
5340 driver->core_driver_dependencies,
5341 &r->core_driver_dependencies,
5343 if (!W_ERROR_IS_OK(result)) {
5347 r->min_inbox_driver_ver_date = driver->min_inbox_driver_ver_date;
5348 r->min_inbox_driver_ver_version = driver->min_inbox_driver_ver_version;
5353 #if 0 /* disabled until marshalling issues are resolved - gd */
5354 /********************************************************************
5355 ********************************************************************/
5357 static WERROR fill_spoolss_DriverFileInfo(TALLOC_CTX *mem_ctx,
5358 struct spoolss_DriverFileInfo *r,
5359 const char *cservername,
5360 const char *file_name,
5361 enum spoolss_DriverFileType file_type,
5362 uint32_t file_version)
5364 r->file_name = talloc_asprintf(mem_ctx, "\\\\%s%s",
5365 cservername, file_name);
5366 W_ERROR_HAVE_NO_MEMORY(r->file_name);
5367 r->file_type = file_type;
5368 r->file_version = file_version;
5373 /********************************************************************
5374 ********************************************************************/
5376 static WERROR spoolss_DriverFileInfo_from_driver(TALLOC_CTX *mem_ctx,
5377 const struct spoolss_DriverInfo8 *driver,
5378 const char *cservername,
5379 struct spoolss_DriverFileInfo **info_p,
5382 struct spoolss_DriverFileInfo *info = NULL;
5390 if (strlen(driver->driver_path)) {
5391 info = talloc_realloc(mem_ctx, info,
5392 struct spoolss_DriverFileInfo,
5394 W_ERROR_HAVE_NO_MEMORY(info);
5395 result = fill_spoolss_DriverFileInfo(info,
5398 driver->driver_path,
5399 SPOOLSS_DRIVER_FILE_TYPE_RENDERING,
5401 W_ERROR_NOT_OK_RETURN(result);
5405 if (strlen(driver->config_file)) {
5406 info = talloc_realloc(mem_ctx, info,
5407 struct spoolss_DriverFileInfo,
5409 W_ERROR_HAVE_NO_MEMORY(info);
5410 result = fill_spoolss_DriverFileInfo(info,
5413 driver->config_file,
5414 SPOOLSS_DRIVER_FILE_TYPE_CONFIGURATION,
5416 W_ERROR_NOT_OK_RETURN(result);
5420 if (strlen(driver->data_file)) {
5421 info = talloc_realloc(mem_ctx, info,
5422 struct spoolss_DriverFileInfo,
5424 W_ERROR_HAVE_NO_MEMORY(info);
5425 result = fill_spoolss_DriverFileInfo(info,
5429 SPOOLSS_DRIVER_FILE_TYPE_DATA,
5431 W_ERROR_NOT_OK_RETURN(result);
5435 if (strlen(driver->help_file)) {
5436 info = talloc_realloc(mem_ctx, info,
5437 struct spoolss_DriverFileInfo,
5439 W_ERROR_HAVE_NO_MEMORY(info);
5440 result = fill_spoolss_DriverFileInfo(info,
5444 SPOOLSS_DRIVER_FILE_TYPE_HELP,
5446 W_ERROR_NOT_OK_RETURN(result);
5450 for (i=0; driver->dependent_files[i] && driver->dependent_files[i][0] != '\0'; i++) {
5451 info = talloc_realloc(mem_ctx, info,
5452 struct spoolss_DriverFileInfo,
5454 W_ERROR_HAVE_NO_MEMORY(info);
5455 result = fill_spoolss_DriverFileInfo(info,
5458 driver->dependent_files[i],
5459 SPOOLSS_DRIVER_FILE_TYPE_OTHER,
5461 W_ERROR_NOT_OK_RETURN(result);
5471 /********************************************************************
5472 * fill a spoolss_DriverInfo101 struct
5473 ********************************************************************/
5475 static WERROR fill_printer_driver_info101(TALLOC_CTX *mem_ctx,
5476 struct spoolss_DriverInfo101 *r,
5477 const struct spoolss_DriverInfo8 *driver,
5478 const char *servername)
5480 const char *cservername = canon_servername(servername);
5483 r->version = driver->version;
5485 r->driver_name = talloc_strdup(mem_ctx, driver->driver_name);
5486 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
5487 r->architecture = talloc_strdup(mem_ctx, driver->architecture);
5488 W_ERROR_HAVE_NO_MEMORY(r->architecture);
5490 result = spoolss_DriverFileInfo_from_driver(mem_ctx, driver,
5494 if (!W_ERROR_IS_OK(result)) {
5498 FILL_DRIVER_STRING(mem_ctx,
5499 driver->monitor_name,
5502 FILL_DRIVER_STRING(mem_ctx,
5503 driver->default_datatype,
5504 r->default_datatype);
5506 result = string_array_from_driver_info(mem_ctx,
5507 driver->previous_names,
5510 if (!W_ERROR_IS_OK(result)) {
5514 r->driver_date = driver->driver_date;
5515 r->driver_version = driver->driver_version;
5517 FILL_DRIVER_STRING(mem_ctx,
5518 driver->manufacturer_name,
5519 r->manufacturer_name);
5520 FILL_DRIVER_STRING(mem_ctx,
5521 driver->manufacturer_url,
5522 r->manufacturer_url);
5523 FILL_DRIVER_STRING(mem_ctx,
5524 driver->hardware_id,
5526 FILL_DRIVER_STRING(mem_ctx,
5533 /********************************************************************
5534 ********************************************************************/
5536 static WERROR construct_printer_driver_info_level(TALLOC_CTX *mem_ctx,
5537 const struct auth_session_info *session_info,
5538 struct messaging_context *msg_ctx,
5540 union spoolss_DriverInfo *r,
5542 const char *servername,
5543 const char *architecture,
5546 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
5547 struct spoolss_DriverInfo8 *driver;
5549 struct dcerpc_binding_handle *b;
5550 TALLOC_CTX *tmp_ctx = NULL;
5553 return WERR_UNKNOWN_LEVEL;
5556 tmp_ctx = talloc_new(mem_ctx);
5561 result = winreg_printer_binding_handle(tmp_ctx,
5565 if (!W_ERROR_IS_OK(result)) {
5569 result = winreg_get_printer(tmp_ctx, b,
5570 lp_const_servicename(snum),
5573 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5574 win_errstr(result)));
5576 if (!W_ERROR_IS_OK(result)) {
5577 result = WERR_INVALID_PRINTER_NAME;
5581 result = winreg_get_driver(tmp_ctx, b,
5583 pinfo2->drivername, version, &driver);
5585 DEBUG(8,("construct_printer_driver_info_level: status: %s\n",
5586 win_errstr(result)));
5588 if (!W_ERROR_IS_OK(result)) {
5590 * Is this a W2k client ?
5594 result = WERR_UNKNOWN_PRINTER_DRIVER;
5598 /* Yes - try again with a WinNT driver. */
5600 result = winreg_get_driver(tmp_ctx, b,
5604 DEBUG(8,("construct_printer_driver_level: status: %s\n",
5605 win_errstr(result)));
5606 if (!W_ERROR_IS_OK(result)) {
5607 result = WERR_UNKNOWN_PRINTER_DRIVER;
5612 /* these are allocated on mem_ctx and not tmp_ctx because they are
5613 * the 'return value' and need to utlive this call */
5616 result = fill_printer_driver_info1(mem_ctx, &r->info1, driver, servername);
5619 result = fill_printer_driver_info2(mem_ctx, &r->info2, driver, servername);
5622 result = fill_printer_driver_info3(mem_ctx, &r->info3, driver, servername);
5625 result = fill_printer_driver_info4(mem_ctx, &r->info4, driver, servername);
5628 result = fill_printer_driver_info5(mem_ctx, &r->info5, driver, servername);
5631 result = fill_printer_driver_info6(mem_ctx, &r->info6, driver, servername);
5634 result = fill_printer_driver_info8(mem_ctx, &r->info8, driver, servername);
5636 #if 0 /* disabled until marshalling issues are resolved - gd */
5638 result = fill_printer_driver_info101(mem_ctx, &r->info101, driver, servername);
5642 result = WERR_UNKNOWN_LEVEL;
5647 talloc_free(tmp_ctx);
5651 /****************************************************************
5652 _spoolss_GetPrinterDriver2
5653 ****************************************************************/
5655 WERROR _spoolss_GetPrinterDriver2(struct pipes_struct *p,
5656 struct spoolss_GetPrinterDriver2 *r)
5658 struct printer_handle *printer;
5663 /* that's an [in out] buffer */
5665 if (!r->in.buffer && (r->in.offered != 0)) {
5666 return WERR_INVALID_PARAM;
5669 DEBUG(4,("_spoolss_GetPrinterDriver2\n"));
5671 if (!(printer = find_printer_index_by_hnd(p, r->in.handle))) {
5672 DEBUG(0,("_spoolss_GetPrinterDriver2: invalid printer handle!\n"));
5673 return WERR_INVALID_PRINTER_NAME;
5677 *r->out.server_major_version = 0;
5678 *r->out.server_minor_version = 0;
5680 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5684 result = construct_printer_driver_info_level(p->mem_ctx,
5685 get_session_info_system(),
5687 r->in.level, r->out.info,
5688 snum, printer->servername,
5690 r->in.client_major_version);
5691 if (!W_ERROR_IS_OK(result)) {
5692 TALLOC_FREE(r->out.info);
5696 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverInfo,
5697 r->out.info, r->in.level);
5698 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
5700 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
5704 /****************************************************************
5705 _spoolss_StartPagePrinter
5706 ****************************************************************/
5708 WERROR _spoolss_StartPagePrinter(struct pipes_struct *p,
5709 struct spoolss_StartPagePrinter *r)
5711 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5714 DEBUG(3,("_spoolss_StartPagePrinter: "
5715 "Error in startpageprinter printer handle\n"));
5719 Printer->page_started = true;
5723 /****************************************************************
5724 _spoolss_EndPagePrinter
5725 ****************************************************************/
5727 WERROR _spoolss_EndPagePrinter(struct pipes_struct *p,
5728 struct spoolss_EndPagePrinter *r)
5732 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5735 DEBUG(2,("_spoolss_EndPagePrinter: Invalid handle (%s:%u:%u).\n",
5736 OUR_HANDLE(r->in.handle)));
5740 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5743 Printer->page_started = false;
5744 print_job_endpage(p->msg_ctx, snum, Printer->jobid);
5749 /****************************************************************
5750 _spoolss_StartDocPrinter
5751 ****************************************************************/
5753 WERROR _spoolss_StartDocPrinter(struct pipes_struct *p,
5754 struct spoolss_StartDocPrinter *r)
5756 struct spoolss_DocumentInfo1 *info_1;
5758 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5764 DEBUG(2,("_spoolss_StartDocPrinter: "
5765 "Invalid handle (%s:%u:%u)\n",
5766 OUR_HANDLE(r->in.handle)));
5770 if (Printer->jobid) {
5771 DEBUG(2, ("_spoolss_StartDocPrinter: "
5772 "StartDocPrinter called twice! "
5773 "(existing jobid = %d)\n", Printer->jobid));
5774 return WERR_INVALID_HANDLE;
5777 if (r->in.level != 1) {
5778 return WERR_UNKNOWN_LEVEL;
5781 info_1 = r->in.info.info1;
5784 * a nice thing with NT is it doesn't listen to what you tell it.
5785 * when asked to send _only_ RAW datas, it tries to send datas
5788 * So I add checks like in NT Server ...
5791 if (info_1->datatype) {
5792 if (strcmp(info_1->datatype, "RAW") != 0) {
5794 return WERR_INVALID_DATATYPE;
5798 /* get the share number of the printer */
5799 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5803 rc = get_remote_hostname(p->remote_address,
5809 if (strequal(rhost,"UNKNOWN")) {
5810 rhost = tsocket_address_inet_addr_string(p->remote_address,
5812 if (rhost == NULL) {
5817 werr = print_job_start(p->session_info,
5821 info_1->document_name,
5822 info_1->output_file,
5826 /* An error occured in print_job_start() so return an appropriate
5829 if (!W_ERROR_IS_OK(werr)) {
5833 Printer->document_started = true;
5834 *r->out.job_id = Printer->jobid;
5839 /****************************************************************
5840 _spoolss_EndDocPrinter
5841 ****************************************************************/
5843 WERROR _spoolss_EndDocPrinter(struct pipes_struct *p,
5844 struct spoolss_EndDocPrinter *r)
5846 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5851 DEBUG(2,("_spoolss_EndDocPrinter: Invalid handle (%s:%u:%u)\n",
5852 OUR_HANDLE(r->in.handle)));
5856 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
5860 Printer->document_started = false;
5861 status = print_job_end(p->msg_ctx, snum, Printer->jobid, NORMAL_CLOSE);
5862 if (!NT_STATUS_IS_OK(status)) {
5863 DEBUG(2, ("_spoolss_EndDocPrinter: "
5864 "print_job_end failed [%s]\n",
5865 nt_errstr(status)));
5869 return ntstatus_to_werror(status);
5872 /****************************************************************
5873 _spoolss_WritePrinter
5874 ****************************************************************/
5876 WERROR _spoolss_WritePrinter(struct pipes_struct *p,
5877 struct spoolss_WritePrinter *r)
5879 ssize_t buffer_written;
5881 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5884 DEBUG(2,("_spoolss_WritePrinter: Invalid handle (%s:%u:%u)\n",
5885 OUR_HANDLE(r->in.handle)));
5886 *r->out.num_written = r->in._data_size;
5890 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5893 /* print_job_write takes care of checking for PJOB_SMBD_SPOOLING */
5894 buffer_written = print_job_write(server_event_context(),p->msg_ctx,
5895 snum, Printer->jobid,
5896 (const char *)r->in.data.data,
5897 (size_t)r->in._data_size);
5898 if (buffer_written == (ssize_t)-1) {
5899 *r->out.num_written = 0;
5900 if (errno == ENOSPC)
5901 return WERR_NO_SPOOL_SPACE;
5903 return WERR_ACCESS_DENIED;
5906 *r->out.num_written = r->in._data_size;
5911 /********************************************************************
5912 * api_spoolss_getprinter
5913 * called from the spoolss dispatcher
5915 ********************************************************************/
5917 static WERROR control_printer(struct policy_handle *handle, uint32_t command,
5918 struct pipes_struct *p)
5920 const struct auth_session_info *session_info = p->session_info;
5922 WERROR errcode = WERR_BADFUNC;
5923 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
5926 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n",
5927 OUR_HANDLE(handle)));
5931 if (!get_printer_snum(p, handle, &snum, NULL))
5935 case SPOOLSS_PRINTER_CONTROL_PAUSE:
5936 errcode = print_queue_pause(session_info, p->msg_ctx, snum);
5938 case SPOOLSS_PRINTER_CONTROL_RESUME:
5939 case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
5940 errcode = print_queue_resume(session_info, p->msg_ctx, snum);
5942 case SPOOLSS_PRINTER_CONTROL_PURGE:
5943 errcode = print_queue_purge(session_info, p->msg_ctx, snum);
5946 return WERR_UNKNOWN_LEVEL;
5953 /****************************************************************
5954 _spoolss_AbortPrinter
5955 * From MSDN: "Deletes printer's spool file if printer is configured
5957 ****************************************************************/
5959 WERROR _spoolss_AbortPrinter(struct pipes_struct *p,
5960 struct spoolss_AbortPrinter *r)
5962 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
5964 WERROR errcode = WERR_OK;
5967 DEBUG(2,("_spoolss_AbortPrinter: Invalid handle (%s:%u:%u)\n",
5968 OUR_HANDLE(r->in.handle)));
5972 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
5975 if (!Printer->document_started) {
5976 return WERR_SPL_NO_STARTDOC;
5979 errcode = print_job_delete(p->session_info,
5987 /********************************************************************
5988 * called by spoolss_api_setprinter
5989 * when updating a printer description
5990 ********************************************************************/
5992 static WERROR update_printer_sec(struct policy_handle *handle,
5993 struct pipes_struct *p,
5994 struct sec_desc_buf *secdesc_ctr)
5996 struct spoolss_security_descriptor *new_secdesc = NULL;
5997 struct spoolss_security_descriptor *old_secdesc = NULL;
5998 const char *printer;
6001 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6002 struct dcerpc_binding_handle *b;
6003 TALLOC_CTX *tmp_ctx = NULL;
6005 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6006 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6007 OUR_HANDLE(handle)));
6009 result = WERR_BADFID;
6013 if (secdesc_ctr == NULL) {
6014 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6015 result = WERR_INVALID_PARAM;
6018 printer = lp_const_servicename(snum);
6020 /* Check the user has permissions to change the security
6021 descriptor. By experimentation with two NT machines, the user
6022 requires Full Access to the printer to change security
6025 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6026 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6027 result = WERR_ACCESS_DENIED;
6031 tmp_ctx = talloc_new(p->mem_ctx);
6036 result = winreg_printer_binding_handle(tmp_ctx,
6037 get_session_info_system(),
6040 if (!W_ERROR_IS_OK(result)) {
6044 /* NT seems to like setting the security descriptor even though
6045 nothing may have actually changed. */
6046 result = winreg_get_printer_secdesc(tmp_ctx, b,
6049 if (!W_ERROR_IS_OK(result)) {
6050 DEBUG(2,("update_printer_sec: winreg_get_printer_secdesc_internal() failed\n"));
6051 result = WERR_BADFID;
6055 if (DEBUGLEVEL >= 10) {
6056 struct security_acl *the_acl;
6059 the_acl = old_secdesc->dacl;
6060 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6061 printer, the_acl->num_aces));
6063 for (i = 0; i < the_acl->num_aces; i++) {
6064 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6065 &the_acl->aces[i].trustee),
6066 the_acl->aces[i].access_mask));
6069 the_acl = secdesc_ctr->sd->dacl;
6072 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6073 printer, the_acl->num_aces));
6075 for (i = 0; i < the_acl->num_aces; i++) {
6076 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6077 &the_acl->aces[i].trustee),
6078 the_acl->aces[i].access_mask));
6081 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6085 new_secdesc = sec_desc_merge(tmp_ctx, secdesc_ctr->sd, old_secdesc);
6086 if (new_secdesc == NULL) {
6087 result = WERR_NOMEM;
6091 if (security_descriptor_equal(new_secdesc, old_secdesc)) {
6096 result = winreg_set_printer_secdesc(tmp_ctx, b,
6101 talloc_free(tmp_ctx);
6105 /********************************************************************
6106 Canonicalize printer info from a client
6107 ********************************************************************/
6109 static bool check_printer_ok(TALLOC_CTX *mem_ctx,
6110 struct spoolss_SetPrinterInfo2 *info2,
6113 fstring printername;
6116 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6117 "portname=%s drivername=%s comment=%s location=%s\n",
6118 info2->servername, info2->printername, info2->sharename,
6119 info2->portname, info2->drivername, info2->comment,
6122 /* we force some elements to "correct" values */
6123 info2->servername = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
6124 if (info2->servername == NULL) {
6127 info2->sharename = talloc_strdup(mem_ctx, lp_const_servicename(snum));
6128 if (info2->sharename == NULL) {
6132 /* check to see if we allow printername != sharename */
6133 if (lp_force_printername(snum)) {
6134 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6135 lp_netbios_name(), info2->sharename);
6137 /* make sure printername is in \\server\printername format */
6138 fstrcpy(printername, info2->printername);
6140 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6141 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6145 info2->printername = talloc_asprintf(mem_ctx, "\\\\%s\\%s",
6146 lp_netbios_name(), p);
6148 if (info2->printername == NULL) {
6152 info2->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6153 info2->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6158 /****************************************************************************
6159 ****************************************************************************/
6161 static WERROR add_port_hook(TALLOC_CTX *ctx, struct security_token *token, const char *portname, const char *uri)
6163 char *cmd = lp_addport_cmd();
6164 char *command = NULL;
6166 bool is_print_op = false;
6169 return WERR_ACCESS_DENIED;
6172 command = talloc_asprintf(ctx,
6173 "%s \"%s\" \"%s\"", cmd, portname, uri );
6179 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6181 DEBUG(10,("Running [%s]\n", command));
6183 /********* BEGIN SePrintOperatorPrivilege **********/
6188 ret = smbrun(command, NULL);
6193 /********* END SePrintOperatorPrivilege **********/
6195 DEBUGADD(10,("returned [%d]\n", ret));
6197 TALLOC_FREE(command);
6200 return WERR_ACCESS_DENIED;
6206 /****************************************************************************
6207 ****************************************************************************/
6209 static bool add_printer_hook(TALLOC_CTX *ctx, struct security_token *token,
6210 struct spoolss_SetPrinterInfo2 *info2,
6211 const char *remote_machine,
6212 struct messaging_context *msg_ctx)
6214 char *cmd = lp_addprinter_cmd();
6216 char *command = NULL;
6220 bool is_print_op = false;
6222 if (!remote_machine) {
6226 command = talloc_asprintf(ctx,
6227 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6228 cmd, info2->printername, info2->sharename,
6229 info2->portname, info2->drivername,
6230 info2->location, info2->comment, remote_machine);
6236 is_print_op = security_token_has_privilege(token, SEC_PRIV_PRINT_OPERATOR);
6238 DEBUG(10,("Running [%s]\n", command));
6240 /********* BEGIN SePrintOperatorPrivilege **********/
6245 if ( (ret = smbrun(command, &fd)) == 0 ) {
6246 /* Tell everyone we updated smb.conf. */
6247 message_send_all(msg_ctx, MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6253 /********* END SePrintOperatorPrivilege **********/
6255 DEBUGADD(10,("returned [%d]\n", ret));
6257 TALLOC_FREE(command);
6265 /* reload our services immediately */
6267 reload_services(msg_ctx, -1, false);
6271 /* Get lines and convert them back to dos-codepage */
6272 qlines = fd_lines_load(fd, &numlines, 0, NULL);
6273 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6276 /* Set the portname to what the script says the portname should be. */
6277 /* but don't require anything to be return from the script exit a good error code */
6280 /* Set the portname to what the script says the portname should be. */
6281 info2->portname = talloc_strdup(ctx, qlines[0]);
6282 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6285 TALLOC_FREE(qlines);
6289 static WERROR update_dsspooler(TALLOC_CTX *mem_ctx,
6290 const struct auth_session_info *session_info,
6291 struct messaging_context *msg_ctx,
6293 struct spoolss_SetPrinterInfo2 *printer,
6294 struct spoolss_PrinterInfo2 *old_printer)
6296 bool force_update = (old_printer == NULL);
6297 const char *dnsdomname;
6298 const char *longname;
6299 const char *uncname;
6300 const char *spooling;
6302 WERROR result = WERR_OK;
6303 struct dcerpc_binding_handle *b;
6304 TALLOC_CTX *tmp_ctx;
6306 tmp_ctx = talloc_new(mem_ctx);
6311 result = winreg_printer_binding_handle(tmp_ctx,
6315 if (!W_ERROR_IS_OK(result)) {
6319 if (force_update || !strequal(printer->drivername, old_printer->drivername)) {
6320 push_reg_sz(tmp_ctx, &buffer, printer->drivername);
6321 winreg_set_printer_dataex(tmp_ctx, b,
6323 SPOOL_DSSPOOLER_KEY,
6324 SPOOL_REG_DRIVERNAME,
6329 if (!force_update) {
6330 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6331 printer->drivername));
6333 notify_printer_driver(server_event_context(), msg_ctx,
6334 snum, printer->drivername ?
6335 printer->drivername : "");
6339 if (force_update || !strequal(printer->comment, old_printer->comment)) {
6340 push_reg_sz(tmp_ctx, &buffer, printer->comment);
6341 winreg_set_printer_dataex(tmp_ctx, b,
6343 SPOOL_DSSPOOLER_KEY,
6344 SPOOL_REG_DESCRIPTION,
6349 if (!force_update) {
6350 notify_printer_comment(server_event_context(), msg_ctx,
6351 snum, printer->comment ?
6352 printer->comment : "");
6356 if (force_update || !strequal(printer->sharename, old_printer->sharename)) {
6357 push_reg_sz(tmp_ctx, &buffer, printer->sharename);
6358 winreg_set_printer_dataex(tmp_ctx, b,
6360 SPOOL_DSSPOOLER_KEY,
6361 SPOOL_REG_PRINTSHARENAME,
6366 if (!force_update) {
6367 notify_printer_sharename(server_event_context(),
6369 snum, printer->sharename ?
6370 printer->sharename : "");
6374 if (force_update || !strequal(printer->printername, old_printer->printername)) {
6377 p = strrchr(printer->printername, '\\' );
6381 p = printer->printername;
6384 push_reg_sz(tmp_ctx, &buffer, p);
6385 winreg_set_printer_dataex(tmp_ctx, b,
6387 SPOOL_DSSPOOLER_KEY,
6388 SPOOL_REG_PRINTERNAME,
6393 if (!force_update) {
6394 notify_printer_printername(server_event_context(),
6395 msg_ctx, snum, p ? p : "");
6399 if (force_update || !strequal(printer->portname, old_printer->portname)) {
6400 push_reg_sz(tmp_ctx, &buffer, printer->portname);
6401 winreg_set_printer_dataex(tmp_ctx, b,
6403 SPOOL_DSSPOOLER_KEY,
6409 if (!force_update) {
6410 notify_printer_port(server_event_context(),
6411 msg_ctx, snum, printer->portname ?
6412 printer->portname : "");
6416 if (force_update || !strequal(printer->location, old_printer->location)) {
6417 push_reg_sz(tmp_ctx, &buffer, printer->location);
6418 winreg_set_printer_dataex(tmp_ctx, b,
6420 SPOOL_DSSPOOLER_KEY,
6426 if (!force_update) {
6427 notify_printer_location(server_event_context(),
6430 printer->location : "");
6434 if (force_update || !strequal(printer->sepfile, old_printer->sepfile)) {
6435 push_reg_sz(tmp_ctx, &buffer, printer->sepfile);
6436 winreg_set_printer_dataex(tmp_ctx, b,
6438 SPOOL_DSSPOOLER_KEY,
6439 SPOOL_REG_PRINTSEPARATORFILE,
6444 if (!force_update) {
6445 notify_printer_sepfile(server_event_context(),
6448 printer->sepfile : "");
6452 if (force_update || printer->starttime != old_printer->starttime) {
6453 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6454 SIVAL(buffer.data, 0, printer->starttime);
6455 winreg_set_printer_dataex(tmp_ctx, b,
6457 SPOOL_DSSPOOLER_KEY,
6458 SPOOL_REG_PRINTSTARTTIME,
6464 if (force_update || printer->untiltime != old_printer->untiltime) {
6465 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6466 SIVAL(buffer.data, 0, printer->untiltime);
6467 winreg_set_printer_dataex(tmp_ctx, b,
6469 SPOOL_DSSPOOLER_KEY,
6470 SPOOL_REG_PRINTENDTIME,
6476 if (force_update || printer->priority != old_printer->priority) {
6477 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6478 SIVAL(buffer.data, 0, printer->priority);
6479 winreg_set_printer_dataex(tmp_ctx, b,
6481 SPOOL_DSSPOOLER_KEY,
6488 if (force_update || printer->attributes != old_printer->attributes) {
6489 buffer = data_blob_talloc(tmp_ctx, NULL, 4);
6490 SIVAL(buffer.data, 0, (printer->attributes &
6491 PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
6492 winreg_set_printer_dataex(tmp_ctx, b,
6494 SPOOL_DSSPOOLER_KEY,
6495 SPOOL_REG_PRINTKEEPPRINTEDJOBS,
6500 switch (printer->attributes & 0x3) {
6502 spooling = SPOOL_REGVAL_PRINTWHILESPOOLING;
6505 spooling = SPOOL_REGVAL_PRINTAFTERSPOOLED;
6508 spooling = SPOOL_REGVAL_PRINTDIRECT;
6511 spooling = "unknown";
6513 push_reg_sz(tmp_ctx, &buffer, spooling);
6514 winreg_set_printer_dataex(tmp_ctx, b,
6516 SPOOL_DSSPOOLER_KEY,
6517 SPOOL_REG_PRINTSPOOLING,
6523 push_reg_sz(tmp_ctx, &buffer, lp_netbios_name());
6524 winreg_set_printer_dataex(tmp_ctx, b,
6526 SPOOL_DSSPOOLER_KEY,
6527 SPOOL_REG_SHORTSERVERNAME,
6532 dnsdomname = get_mydnsfullname();
6533 if (dnsdomname != NULL && dnsdomname[0] != '\0') {
6534 longname = talloc_strdup(tmp_ctx, dnsdomname);
6536 longname = talloc_strdup(tmp_ctx, lp_netbios_name());
6538 if (longname == NULL) {
6539 result = WERR_NOMEM;
6543 push_reg_sz(tmp_ctx, &buffer, longname);
6544 winreg_set_printer_dataex(tmp_ctx, b,
6546 SPOOL_DSSPOOLER_KEY,
6547 SPOOL_REG_SERVERNAME,
6552 uncname = talloc_asprintf(tmp_ctx, "\\\\%s\\%s",
6553 lp_netbios_name(), printer->sharename);
6554 push_reg_sz(tmp_ctx, &buffer, uncname);
6555 winreg_set_printer_dataex(tmp_ctx, b,
6557 SPOOL_DSSPOOLER_KEY,
6564 talloc_free(tmp_ctx);
6568 /********************************************************************
6569 * Called by spoolss_api_setprinter
6570 * when updating a printer description.
6571 ********************************************************************/
6573 static WERROR update_printer(struct pipes_struct *p,
6574 struct policy_handle *handle,
6575 struct spoolss_SetPrinterInfoCtr *info_ctr,
6576 struct spoolss_DeviceMode *devmode)
6578 uint32_t printer_mask = SPOOLSS_PRINTER_INFO_ALL;
6579 struct spoolss_SetPrinterInfo2 *printer = info_ctr->info.info2;
6580 struct spoolss_PrinterInfo2 *old_printer;
6581 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6583 WERROR result = WERR_OK;
6584 TALLOC_CTX *tmp_ctx;
6585 struct dcerpc_binding_handle *b;
6587 DEBUG(8,("update_printer\n"));
6589 tmp_ctx = talloc_new(p->mem_ctx);
6590 if (tmp_ctx == NULL) {
6595 result = WERR_BADFID;
6599 if (!get_printer_snum(p, handle, &snum, NULL)) {
6600 result = WERR_BADFID;
6604 result = winreg_printer_binding_handle(tmp_ctx,
6605 get_session_info_system(),
6608 if (!W_ERROR_IS_OK(result)) {
6612 result = winreg_get_printer(tmp_ctx, b,
6613 lp_const_servicename(snum),
6615 if (!W_ERROR_IS_OK(result)) {
6616 result = WERR_BADFID;
6620 /* Do sanity check on the requested changes for Samba */
6621 if (!check_printer_ok(tmp_ctx, printer, snum)) {
6622 result = WERR_INVALID_PARAM;
6626 /* FIXME!!! If the driver has changed we really should verify that
6627 it is installed before doing much else --jerry */
6629 /* Check calling user has permission to update printer description */
6630 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6631 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6632 result = WERR_ACCESS_DENIED;
6636 /* Call addprinter hook */
6637 /* Check changes to see if this is really needed */
6639 if (*lp_addprinter_cmd() &&
6640 (!strequal(printer->drivername, old_printer->drivername) ||
6641 !strequal(printer->comment, old_printer->comment) ||
6642 !strequal(printer->portname, old_printer->portname) ||
6643 !strequal(printer->location, old_printer->location)) )
6647 raddr = tsocket_address_inet_addr_string(p->remote_address,
6649 if (raddr == NULL) {
6653 /* add_printer_hook() will call reload_services() */
6654 if (!add_printer_hook(tmp_ctx, p->session_info->security_token,
6657 result = WERR_ACCESS_DENIED;
6662 update_dsspooler(tmp_ctx,
6663 get_session_info_system(),
6669 printer_mask &= ~SPOOLSS_PRINTER_INFO_SECDESC;
6671 if (devmode == NULL) {
6672 printer_mask &= ~SPOOLSS_PRINTER_INFO_DEVMODE;
6674 result = winreg_update_printer(tmp_ctx, b,
6682 talloc_free(tmp_ctx);
6687 /****************************************************************************
6688 ****************************************************************************/
6689 static WERROR publish_or_unpublish_printer(struct pipes_struct *p,
6690 struct policy_handle *handle,
6691 struct spoolss_SetPrinterInfo7 *info7)
6694 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
6697 struct printer_handle *Printer;
6699 if ( lp_security() != SEC_ADS ) {
6700 return WERR_UNKNOWN_LEVEL;
6703 Printer = find_printer_index_by_hnd(p, handle);
6705 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6710 if (!get_printer_snum(p, handle, &snum, NULL))
6713 result = winreg_get_printer_internal(p->mem_ctx,
6714 get_session_info_system(),
6716 lp_servicename(snum),
6718 if (!W_ERROR_IS_OK(result)) {
6722 nt_printer_publish(pinfo2,
6723 get_session_info_system(),
6728 TALLOC_FREE(pinfo2);
6731 return WERR_UNKNOWN_LEVEL;
6735 /********************************************************************
6736 ********************************************************************/
6738 static WERROR update_printer_devmode(struct pipes_struct *p,
6739 struct policy_handle *handle,
6740 struct spoolss_DeviceMode *devmode)
6743 struct printer_handle *Printer = find_printer_index_by_hnd(p, handle);
6744 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_DEVMODE;
6746 DEBUG(8,("update_printer_devmode\n"));
6752 if (!get_printer_snum(p, handle, &snum, NULL)) {
6756 /* Check calling user has permission to update printer description */
6757 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6758 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6759 return WERR_ACCESS_DENIED;
6762 return winreg_update_printer_internal(p->mem_ctx,
6763 get_session_info_system(),
6765 lp_const_servicename(snum),
6773 /****************************************************************
6775 ****************************************************************/
6777 WERROR _spoolss_SetPrinter(struct pipes_struct *p,
6778 struct spoolss_SetPrinter *r)
6782 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6785 DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
6786 OUR_HANDLE(r->in.handle)));
6790 /* check the level */
6791 switch (r->in.info_ctr->level) {
6793 return control_printer(r->in.handle, r->in.command, p);
6795 result = update_printer(p, r->in.handle,
6797 r->in.devmode_ctr->devmode);
6798 if (!W_ERROR_IS_OK(result))
6800 if (r->in.secdesc_ctr->sd)
6801 result = update_printer_sec(r->in.handle, p,
6805 return update_printer_sec(r->in.handle, p,
6808 return publish_or_unpublish_printer(p, r->in.handle,
6809 r->in.info_ctr->info.info7);
6811 return update_printer_devmode(p, r->in.handle,
6812 r->in.devmode_ctr->devmode);
6814 return WERR_UNKNOWN_LEVEL;
6818 /****************************************************************
6819 _spoolss_FindClosePrinterNotify
6820 ****************************************************************/
6822 WERROR _spoolss_FindClosePrinterNotify(struct pipes_struct *p,
6823 struct spoolss_FindClosePrinterNotify *r)
6825 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
6828 DEBUG(2,("_spoolss_FindClosePrinterNotify: "
6829 "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(r->in.handle)));
6833 if (Printer->notify.cli_chan != NULL &&
6834 Printer->notify.cli_chan->active_connections > 0) {
6837 if (Printer->printer_type == SPLHND_PRINTER) {
6838 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
6843 srv_spoolss_replycloseprinter(snum, Printer);
6846 Printer->notify.flags=0;
6847 Printer->notify.options=0;
6848 Printer->notify.localmachine[0]='\0';
6849 Printer->notify.printerlocal=0;
6850 TALLOC_FREE(Printer->notify.option);
6855 /****************************************************************
6857 ****************************************************************/
6859 WERROR _spoolss_AddJob(struct pipes_struct *p,
6860 struct spoolss_AddJob *r)
6862 if (!r->in.buffer && (r->in.offered != 0)) {
6863 return WERR_INVALID_PARAM;
6866 /* this is what a NT server returns for AddJob. AddJob must fail on
6867 * non-local printers */
6869 if (r->in.level != 1) {
6870 return WERR_UNKNOWN_LEVEL;
6873 return WERR_INVALID_PARAM;
6876 /****************************************************************************
6878 ****************************************************************************/
6880 static WERROR fill_job_info1(TALLOC_CTX *mem_ctx,
6881 struct spoolss_JobInfo1 *r,
6882 const print_queue_struct *queue,
6883 int position, int snum,
6884 struct spoolss_PrinterInfo2 *pinfo2)
6888 t = gmtime(&queue->time);
6890 r->job_id = queue->job;
6892 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6893 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6894 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6895 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6896 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6897 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6898 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6899 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6900 r->data_type = talloc_strdup(mem_ctx, "RAW");
6901 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6902 r->text_status = talloc_strdup(mem_ctx, "");
6903 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6905 r->status = nt_printj_status(queue->status);
6906 r->priority = queue->priority;
6907 r->position = position;
6908 r->total_pages = queue->page_count;
6909 r->pages_printed = 0; /* ??? */
6911 init_systemtime(&r->submitted, t);
6916 /****************************************************************************
6918 ****************************************************************************/
6920 static WERROR fill_job_info2(TALLOC_CTX *mem_ctx,
6921 struct spoolss_JobInfo2 *r,
6922 const print_queue_struct *queue,
6923 int position, int snum,
6924 struct spoolss_PrinterInfo2 *pinfo2,
6925 struct spoolss_DeviceMode *devmode)
6929 t = gmtime(&queue->time);
6931 r->job_id = queue->job;
6933 r->printer_name = talloc_strdup(mem_ctx, lp_servicename(snum));
6934 W_ERROR_HAVE_NO_MEMORY(r->printer_name);
6935 r->server_name = talloc_strdup(mem_ctx, pinfo2->servername);
6936 W_ERROR_HAVE_NO_MEMORY(r->server_name);
6937 r->user_name = talloc_strdup(mem_ctx, queue->fs_user);
6938 W_ERROR_HAVE_NO_MEMORY(r->user_name);
6939 r->document_name = talloc_strdup(mem_ctx, queue->fs_file);
6940 W_ERROR_HAVE_NO_MEMORY(r->document_name);
6941 r->notify_name = talloc_strdup(mem_ctx, queue->fs_user);
6942 W_ERROR_HAVE_NO_MEMORY(r->notify_name);
6943 r->data_type = talloc_strdup(mem_ctx, "RAW");
6944 W_ERROR_HAVE_NO_MEMORY(r->data_type);
6945 r->print_processor = talloc_strdup(mem_ctx, "winprint");
6946 W_ERROR_HAVE_NO_MEMORY(r->print_processor);
6947 r->parameters = talloc_strdup(mem_ctx, "");
6948 W_ERROR_HAVE_NO_MEMORY(r->parameters);
6949 r->driver_name = talloc_strdup(mem_ctx, pinfo2->drivername);
6950 W_ERROR_HAVE_NO_MEMORY(r->driver_name);
6952 r->devmode = devmode;
6954 r->text_status = talloc_strdup(mem_ctx, "");
6955 W_ERROR_HAVE_NO_MEMORY(r->text_status);
6959 r->status = nt_printj_status(queue->status);
6960 r->priority = queue->priority;
6961 r->position = position;
6964 r->total_pages = queue->page_count;
6965 r->size = queue->size;
6966 init_systemtime(&r->submitted, t);
6968 r->pages_printed = 0; /* ??? */
6973 /****************************************************************************
6975 ****************************************************************************/
6977 static WERROR fill_job_info3(TALLOC_CTX *mem_ctx,
6978 struct spoolss_JobInfo3 *r,
6979 const print_queue_struct *queue,
6980 const print_queue_struct *next_queue,
6981 int position, int snum,
6982 struct spoolss_PrinterInfo2 *pinfo2)
6984 r->job_id = queue->job;
6987 r->next_job_id = next_queue->job;
6994 /****************************************************************************
6995 Enumjobs at level 1.
6996 ****************************************************************************/
6998 static WERROR enumjobs_level1(TALLOC_CTX *mem_ctx,
6999 const print_queue_struct *queue,
7000 uint32_t num_queues, int snum,
7001 struct spoolss_PrinterInfo2 *pinfo2,
7002 union spoolss_JobInfo **info_p,
7005 union spoolss_JobInfo *info;
7007 WERROR result = WERR_OK;
7009 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7010 W_ERROR_HAVE_NO_MEMORY(info);
7012 *count = num_queues;
7014 for (i=0; i<*count; i++) {
7015 result = fill_job_info1(info,
7021 if (!W_ERROR_IS_OK(result)) {
7027 if (!W_ERROR_IS_OK(result)) {
7038 /****************************************************************************
7039 Enumjobs at level 2.
7040 ****************************************************************************/
7042 static WERROR enumjobs_level2(TALLOC_CTX *mem_ctx,
7043 const print_queue_struct *queue,
7044 uint32_t num_queues, int snum,
7045 struct spoolss_PrinterInfo2 *pinfo2,
7046 union spoolss_JobInfo **info_p,
7049 union spoolss_JobInfo *info;
7051 WERROR result = WERR_OK;
7053 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7054 W_ERROR_HAVE_NO_MEMORY(info);
7056 *count = num_queues;
7058 for (i=0; i<*count; i++) {
7059 struct spoolss_DeviceMode *devmode;
7061 result = spoolss_create_default_devmode(info,
7062 pinfo2->printername,
7064 if (!W_ERROR_IS_OK(result)) {
7065 DEBUG(3, ("Can't proceed w/o a devmode!"));
7069 result = fill_job_info2(info,
7076 if (!W_ERROR_IS_OK(result)) {
7082 if (!W_ERROR_IS_OK(result)) {
7093 /****************************************************************************
7094 Enumjobs at level 3.
7095 ****************************************************************************/
7097 static WERROR enumjobs_level3(TALLOC_CTX *mem_ctx,
7098 const print_queue_struct *queue,
7099 uint32_t num_queues, int snum,
7100 struct spoolss_PrinterInfo2 *pinfo2,
7101 union spoolss_JobInfo **info_p,
7104 union spoolss_JobInfo *info;
7106 WERROR result = WERR_OK;
7108 info = talloc_array(mem_ctx, union spoolss_JobInfo, num_queues);
7109 W_ERROR_HAVE_NO_MEMORY(info);
7111 *count = num_queues;
7113 for (i=0; i<*count; i++) {
7114 const print_queue_struct *next_queue = NULL;
7117 next_queue = &queue[i+1];
7120 result = fill_job_info3(info,
7127 if (!W_ERROR_IS_OK(result)) {
7133 if (!W_ERROR_IS_OK(result)) {
7144 /****************************************************************
7146 ****************************************************************/
7148 WERROR _spoolss_EnumJobs(struct pipes_struct *p,
7149 struct spoolss_EnumJobs *r)
7152 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
7154 print_status_struct prt_status;
7155 print_queue_struct *queue = NULL;
7158 /* that's an [in out] buffer */
7160 if (!r->in.buffer && (r->in.offered != 0)) {
7161 return WERR_INVALID_PARAM;
7164 DEBUG(4,("_spoolss_EnumJobs\n"));
7168 *r->out.info = NULL;
7170 /* lookup the printer snum and tdb entry */
7172 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7176 result = winreg_get_printer_internal(p->mem_ctx,
7177 get_session_info_system(),
7179 lp_const_servicename(snum),
7181 if (!W_ERROR_IS_OK(result)) {
7185 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
7186 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n",
7187 count, prt_status.status, prt_status.message));
7191 TALLOC_FREE(pinfo2);
7195 switch (r->in.level) {
7197 result = enumjobs_level1(p->mem_ctx, queue, count, snum,
7198 pinfo2, r->out.info, r->out.count);
7201 result = enumjobs_level2(p->mem_ctx, queue, count, snum,
7202 pinfo2, r->out.info, r->out.count);
7205 result = enumjobs_level3(p->mem_ctx, queue, count, snum,
7206 pinfo2, r->out.info, r->out.count);
7209 result = WERR_UNKNOWN_LEVEL;
7214 TALLOC_FREE(pinfo2);
7216 if (!W_ERROR_IS_OK(result)) {
7220 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7222 *r->out.info, r->in.level,
7224 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7225 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7227 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7230 /****************************************************************
7231 _spoolss_ScheduleJob
7232 ****************************************************************/
7234 WERROR _spoolss_ScheduleJob(struct pipes_struct *p,
7235 struct spoolss_ScheduleJob *r)
7240 /****************************************************************
7241 ****************************************************************/
7243 static WERROR spoolss_setjob_1(TALLOC_CTX *mem_ctx,
7244 struct messaging_context *msg_ctx,
7245 const char *printer_name,
7247 struct spoolss_SetJobInfo1 *r)
7251 if (!print_job_get_name(mem_ctx, printer_name, job_id, &old_doc_name)) {
7255 if (strequal(old_doc_name, r->document_name)) {
7259 if (!print_job_set_name(server_event_context(), msg_ctx,
7260 printer_name, job_id, r->document_name)) {
7267 /****************************************************************
7269 ****************************************************************/
7271 WERROR _spoolss_SetJob(struct pipes_struct *p,
7272 struct spoolss_SetJob *r)
7274 const struct auth_session_info *session_info = p->session_info;
7276 WERROR errcode = WERR_BADFUNC;
7278 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
7282 if (!print_job_exists(lp_const_servicename(snum), r->in.job_id)) {
7283 return WERR_INVALID_PRINTER_NAME;
7286 switch (r->in.command) {
7287 case SPOOLSS_JOB_CONTROL_CANCEL:
7288 case SPOOLSS_JOB_CONTROL_DELETE:
7289 errcode = print_job_delete(session_info, p->msg_ctx,
7290 snum, r->in.job_id);
7291 if (W_ERROR_EQUAL(errcode, WERR_PRINTER_HAS_JOBS_QUEUED)) {
7295 case SPOOLSS_JOB_CONTROL_PAUSE:
7296 if (print_job_pause(session_info, p->msg_ctx,
7297 snum, r->in.job_id, &errcode)) {
7301 case SPOOLSS_JOB_CONTROL_RESTART:
7302 case SPOOLSS_JOB_CONTROL_RESUME:
7303 if (print_job_resume(session_info, p->msg_ctx,
7304 snum, r->in.job_id, &errcode)) {
7312 return WERR_UNKNOWN_LEVEL;
7315 if (!W_ERROR_IS_OK(errcode)) {
7319 if (r->in.ctr == NULL) {
7323 switch (r->in.ctr->level) {
7325 errcode = spoolss_setjob_1(p->mem_ctx, p->msg_ctx,
7326 lp_const_servicename(snum),
7328 r->in.ctr->info.info1);
7334 return WERR_UNKNOWN_LEVEL;
7340 /****************************************************************************
7341 Enumerates all printer drivers by level and architecture.
7342 ****************************************************************************/
7344 static WERROR enumprinterdrivers_level_by_architecture(TALLOC_CTX *mem_ctx,
7345 const struct auth_session_info *session_info,
7346 struct messaging_context *msg_ctx,
7347 const char *servername,
7348 const char *architecture,
7350 union spoolss_DriverInfo **info_p,
7355 struct spoolss_DriverInfo8 *driver;
7356 union spoolss_DriverInfo *info = NULL;
7358 WERROR result = WERR_OK;
7359 uint32_t num_drivers;
7360 const char **drivers;
7361 struct dcerpc_binding_handle *b;
7362 TALLOC_CTX *tmp_ctx = NULL;
7367 tmp_ctx = talloc_new(mem_ctx);
7372 result = winreg_printer_binding_handle(tmp_ctx,
7376 if (!W_ERROR_IS_OK(result)) {
7380 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7381 result = winreg_get_driver_list(tmp_ctx, b,
7382 architecture, version,
7383 &num_drivers, &drivers);
7384 if (!W_ERROR_IS_OK(result)) {
7387 DEBUG(4, ("we have:[%d] drivers in environment"
7388 " [%s] and version [%d]\n",
7389 num_drivers, architecture, version));
7391 if (num_drivers != 0) {
7392 info = talloc_realloc(tmp_ctx, info,
7393 union spoolss_DriverInfo,
7394 count + num_drivers);
7396 DEBUG(0,("enumprinterdrivers_level_by_architecture: "
7397 "failed to enlarge driver info buffer!\n"));
7398 result = WERR_NOMEM;
7403 for (i = 0; i < num_drivers; i++) {
7404 DEBUG(5, ("\tdriver: [%s]\n", drivers[i]));
7406 result = winreg_get_driver(tmp_ctx, b,
7407 architecture, drivers[i],
7409 if (!W_ERROR_IS_OK(result)) {
7415 result = fill_printer_driver_info1(info, &info[count+i].info1,
7416 driver, servername);
7419 result = fill_printer_driver_info2(info, &info[count+i].info2,
7420 driver, servername);
7423 result = fill_printer_driver_info3(info, &info[count+i].info3,
7424 driver, servername);
7427 result = fill_printer_driver_info4(info, &info[count+i].info4,
7428 driver, servername);
7431 result = fill_printer_driver_info5(info, &info[count+i].info5,
7432 driver, servername);
7435 result = fill_printer_driver_info6(info, &info[count+i].info6,
7436 driver, servername);
7439 result = fill_printer_driver_info8(info, &info[count+i].info8,
7440 driver, servername);
7443 result = WERR_UNKNOWN_LEVEL;
7447 TALLOC_FREE(driver);
7449 if (!W_ERROR_IS_OK(result)) {
7454 count += num_drivers;
7455 TALLOC_FREE(drivers);
7459 if (W_ERROR_IS_OK(result)) {
7460 *info_p = talloc_move(mem_ctx, &info);
7464 talloc_free(tmp_ctx);
7468 /****************************************************************************
7469 Enumerates all printer drivers by level.
7470 ****************************************************************************/
7472 static WERROR enumprinterdrivers_level(TALLOC_CTX *mem_ctx,
7473 const struct auth_session_info *session_info,
7474 struct messaging_context *msg_ctx,
7475 const char *servername,
7476 const char *architecture,
7478 union spoolss_DriverInfo **info_p,
7482 WERROR result = WERR_OK;
7484 if (strequal(architecture, SPOOLSS_ARCHITECTURE_ALL)) {
7486 for (a=0; archi_table[a].long_archi != NULL; a++) {
7488 union spoolss_DriverInfo *info = NULL;
7491 result = enumprinterdrivers_level_by_architecture(mem_ctx,
7495 archi_table[a].long_archi,
7499 if (!W_ERROR_IS_OK(result)) {
7503 for (i=0; i < count; i++) {
7504 ADD_TO_ARRAY(mem_ctx, union spoolss_DriverInfo,
7505 info[i], info_p, count_p);
7512 return enumprinterdrivers_level_by_architecture(mem_ctx,
7522 /****************************************************************
7523 _spoolss_EnumPrinterDrivers
7524 ****************************************************************/
7526 WERROR _spoolss_EnumPrinterDrivers(struct pipes_struct *p,
7527 struct spoolss_EnumPrinterDrivers *r)
7529 const char *cservername;
7532 /* that's an [in out] buffer */
7534 if (!r->in.buffer && (r->in.offered != 0)) {
7535 return WERR_INVALID_PARAM;
7538 DEBUG(4,("_spoolss_EnumPrinterDrivers\n"));
7542 *r->out.info = NULL;
7544 cservername = canon_servername(r->in.server);
7546 if (!is_myname_or_ipaddr(cservername)) {
7547 return WERR_UNKNOWN_PRINTER_DRIVER;
7550 result = enumprinterdrivers_level(p->mem_ctx,
7551 get_session_info_system(),
7558 if (!W_ERROR_IS_OK(result)) {
7562 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7563 spoolss_EnumPrinterDrivers,
7564 *r->out.info, r->in.level,
7566 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7567 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7569 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7572 /****************************************************************
7574 ****************************************************************/
7576 WERROR _spoolss_EnumForms(struct pipes_struct *p,
7577 struct spoolss_EnumForms *r)
7583 *r->out.info = NULL;
7585 /* that's an [in out] buffer */
7587 if (!r->in.buffer && (r->in.offered != 0) ) {
7588 return WERR_INVALID_PARAM;
7591 DEBUG(4,("_spoolss_EnumForms\n"));
7592 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7593 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7595 switch (r->in.level) {
7597 result = winreg_printer_enumforms1_internal(p->mem_ctx,
7598 get_session_info_system(),
7604 result = WERR_UNKNOWN_LEVEL;
7608 if (!W_ERROR_IS_OK(result)) {
7612 if (*r->out.count == 0) {
7613 return WERR_NO_MORE_ITEMS;
7616 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7618 *r->out.info, r->in.level,
7620 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7621 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7623 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7626 /****************************************************************
7628 ****************************************************************/
7630 WERROR _spoolss_GetForm(struct pipes_struct *p,
7631 struct spoolss_GetForm *r)
7635 /* that's an [in out] buffer */
7637 if (!r->in.buffer && (r->in.offered != 0)) {
7638 return WERR_INVALID_PARAM;
7641 DEBUG(4,("_spoolss_GetForm\n"));
7642 DEBUGADD(5,("Offered buffer size [%d]\n", r->in.offered));
7643 DEBUGADD(5,("Info level [%d]\n", r->in.level));
7645 switch (r->in.level) {
7647 result = winreg_printer_getform1_internal(p->mem_ctx,
7648 get_session_info_system(),
7651 &r->out.info->info1);
7654 result = WERR_UNKNOWN_LEVEL;
7658 if (!W_ERROR_IS_OK(result)) {
7659 TALLOC_FREE(r->out.info);
7663 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_FormInfo,
7664 r->out.info, r->in.level);
7665 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
7667 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7670 /****************************************************************************
7671 ****************************************************************************/
7673 static WERROR fill_port_1(TALLOC_CTX *mem_ctx,
7674 struct spoolss_PortInfo1 *r,
7677 r->port_name = talloc_strdup(mem_ctx, name);
7678 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7683 /****************************************************************************
7684 TODO: This probably needs distinguish between TCP/IP and Local ports
7686 ****************************************************************************/
7688 static WERROR fill_port_2(TALLOC_CTX *mem_ctx,
7689 struct spoolss_PortInfo2 *r,
7692 r->port_name = talloc_strdup(mem_ctx, name);
7693 W_ERROR_HAVE_NO_MEMORY(r->port_name);
7695 r->monitor_name = talloc_strdup(mem_ctx, "Local Monitor");
7696 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
7698 r->description = talloc_strdup(mem_ctx, SPL_LOCAL_PORT);
7699 W_ERROR_HAVE_NO_MEMORY(r->description);
7701 r->port_type = SPOOLSS_PORT_TYPE_WRITE;
7708 /****************************************************************************
7709 wrapper around the enumer ports command
7710 ****************************************************************************/
7712 static WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines)
7714 char *cmd = lp_enumports_cmd();
7715 char **qlines = NULL;
7716 char *command = NULL;
7724 /* if no hook then just fill in the default port */
7727 if (!(qlines = talloc_array( NULL, char*, 2 ))) {
7730 if (!(qlines[0] = talloc_strdup(qlines, SAMBA_PRINTER_PORT_NAME ))) {
7731 TALLOC_FREE(qlines);
7738 /* we have a valid enumport command */
7740 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7745 DEBUG(10,("Running [%s]\n", command));
7746 ret = smbrun(command, &fd);
7747 DEBUG(10,("Returned [%d]\n", ret));
7748 TALLOC_FREE(command);
7753 return WERR_ACCESS_DENIED;
7757 qlines = fd_lines_load(fd, &numlines, 0, NULL);
7758 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7768 /****************************************************************************
7770 ****************************************************************************/
7772 static WERROR enumports_level_1(TALLOC_CTX *mem_ctx,
7773 union spoolss_PortInfo **info_p,
7776 union spoolss_PortInfo *info = NULL;
7778 WERROR result = WERR_OK;
7779 char **qlines = NULL;
7782 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7783 if (!W_ERROR_IS_OK(result)) {
7788 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7790 DEBUG(10,("Returning WERR_NOMEM\n"));
7791 result = WERR_NOMEM;
7795 for (i=0; i<numlines; i++) {
7796 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7797 result = fill_port_1(info, &info[i].info1, qlines[i]);
7798 if (!W_ERROR_IS_OK(result)) {
7803 TALLOC_FREE(qlines);
7806 if (!W_ERROR_IS_OK(result)) {
7808 TALLOC_FREE(qlines);
7820 /****************************************************************************
7822 ****************************************************************************/
7824 static WERROR enumports_level_2(TALLOC_CTX *mem_ctx,
7825 union spoolss_PortInfo **info_p,
7828 union spoolss_PortInfo *info = NULL;
7830 WERROR result = WERR_OK;
7831 char **qlines = NULL;
7834 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7835 if (!W_ERROR_IS_OK(result)) {
7840 info = talloc_array(mem_ctx, union spoolss_PortInfo, numlines);
7842 DEBUG(10,("Returning WERR_NOMEM\n"));
7843 result = WERR_NOMEM;
7847 for (i=0; i<numlines; i++) {
7848 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7849 result = fill_port_2(info, &info[i].info2, qlines[i]);
7850 if (!W_ERROR_IS_OK(result)) {
7855 TALLOC_FREE(qlines);
7858 if (!W_ERROR_IS_OK(result)) {
7860 TALLOC_FREE(qlines);
7872 /****************************************************************
7874 ****************************************************************/
7876 WERROR _spoolss_EnumPorts(struct pipes_struct *p,
7877 struct spoolss_EnumPorts *r)
7881 /* that's an [in out] buffer */
7883 if (!r->in.buffer && (r->in.offered != 0)) {
7884 return WERR_INVALID_PARAM;
7887 DEBUG(4,("_spoolss_EnumPorts\n"));
7891 *r->out.info = NULL;
7893 switch (r->in.level) {
7895 result = enumports_level_1(p->mem_ctx, r->out.info,
7899 result = enumports_level_2(p->mem_ctx, r->out.info,
7903 return WERR_UNKNOWN_LEVEL;
7906 if (!W_ERROR_IS_OK(result)) {
7910 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
7912 *r->out.info, r->in.level,
7914 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
7915 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
7917 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
7920 /****************************************************************************
7921 ****************************************************************************/
7923 static WERROR spoolss_addprinterex_level_2(struct pipes_struct *p,
7925 struct spoolss_SetPrinterInfoCtr *info_ctr,
7926 struct spoolss_DeviceMode *devmode,
7927 struct security_descriptor *secdesc,
7928 struct spoolss_UserLevelCtr *user_ctr,
7929 struct policy_handle *handle)
7931 struct spoolss_SetPrinterInfo2 *info2 = info_ctr->info.info2;
7932 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ALL;
7934 WERROR err = WERR_OK;
7936 /* samba does not have a concept of local, non-shared printers yet, so
7937 * make sure we always setup sharename - gd */
7938 if ((info2->sharename == NULL || info2->sharename[0] == '\0') &&
7939 (info2->printername != NULL && info2->printername[0] != '\0')) {
7940 DEBUG(5, ("spoolss_addprinterex_level_2: "
7941 "no sharename has been set, setting printername %s as sharename\n",
7942 info2->printername));
7943 info2->sharename = info2->printername;
7946 /* check to see if the printer already exists */
7947 if ((snum = print_queue_snum(info2->sharename)) != -1) {
7948 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7950 return WERR_PRINTER_ALREADY_EXISTS;
7953 if (!lp_force_printername(GLOBAL_SECTION_SNUM)) {
7954 if ((snum = print_queue_snum(info2->printername)) != -1) {
7955 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7956 info2->printername));
7957 return WERR_PRINTER_ALREADY_EXISTS;
7961 /* validate printer info struct */
7962 if (!info2->printername || strlen(info2->printername) == 0) {
7963 return WERR_INVALID_PRINTER_NAME;
7965 if (!info2->portname || strlen(info2->portname) == 0) {
7966 return WERR_UNKNOWN_PORT;
7968 if (!info2->drivername || strlen(info2->drivername) == 0) {
7969 return WERR_UNKNOWN_PRINTER_DRIVER;
7971 if (!info2->printprocessor || strlen(info2->printprocessor) == 0) {
7972 return WERR_UNKNOWN_PRINTPROCESSOR;
7975 /* FIXME!!! smbd should check to see if the driver is installed before
7976 trying to add a printer like this --jerry */
7978 if (*lp_addprinter_cmd() ) {
7981 raddr = tsocket_address_inet_addr_string(p->remote_address,
7983 if (raddr == NULL) {
7987 if ( !add_printer_hook(p->mem_ctx, p->session_info->security_token,
7990 return WERR_ACCESS_DENIED;
7993 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no "
7994 "smb.conf parameter \"addprinter command\" is defined. This "
7995 "parameter must exist for this call to succeed\n",
7996 info2->sharename ));
7999 if ((snum = print_queue_snum(info2->sharename)) == -1) {
8000 return WERR_ACCESS_DENIED;
8003 /* you must be a printer admin to add a new printer */
8004 if (!print_access_check(p->session_info,
8007 PRINTER_ACCESS_ADMINISTER)) {
8008 return WERR_ACCESS_DENIED;
8012 * Do sanity check on the requested changes for Samba.
8015 if (!check_printer_ok(p->mem_ctx, info2, snum)) {
8016 return WERR_INVALID_PARAM;
8019 if (devmode == NULL) {
8020 info2_mask = ~SPOOLSS_PRINTER_INFO_DEVMODE;
8023 update_dsspooler(p->mem_ctx,
8024 get_session_info_system(),
8030 err = winreg_update_printer_internal(p->mem_ctx,
8031 get_session_info_system(),
8038 if (!W_ERROR_IS_OK(err)) {
8042 err = open_printer_hnd(p, handle, info2->printername, PRINTER_ACCESS_ADMINISTER);
8043 if (!W_ERROR_IS_OK(err)) {
8044 /* Handle open failed - remove addition. */
8045 ZERO_STRUCTP(handle);
8052 /****************************************************************
8053 _spoolss_AddPrinterEx
8054 ****************************************************************/
8056 WERROR _spoolss_AddPrinterEx(struct pipes_struct *p,
8057 struct spoolss_AddPrinterEx *r)
8059 switch (r->in.info_ctr->level) {
8061 /* we don't handle yet */
8062 /* but I know what to do ... */
8063 return WERR_UNKNOWN_LEVEL;
8065 return spoolss_addprinterex_level_2(p, r->in.server,
8067 r->in.devmode_ctr->devmode,
8068 r->in.secdesc_ctr->sd,
8069 r->in.userlevel_ctr,
8072 return WERR_UNKNOWN_LEVEL;
8076 /****************************************************************
8078 ****************************************************************/
8080 WERROR _spoolss_AddPrinter(struct pipes_struct *p,
8081 struct spoolss_AddPrinter *r)
8083 struct spoolss_AddPrinterEx a;
8084 struct spoolss_UserLevelCtr userlevel_ctr;
8086 ZERO_STRUCT(userlevel_ctr);
8088 userlevel_ctr.level = 1;
8090 a.in.server = r->in.server;
8091 a.in.info_ctr = r->in.info_ctr;
8092 a.in.devmode_ctr = r->in.devmode_ctr;
8093 a.in.secdesc_ctr = r->in.secdesc_ctr;
8094 a.in.userlevel_ctr = &userlevel_ctr;
8095 a.out.handle = r->out.handle;
8097 return _spoolss_AddPrinterEx(p, &a);
8100 /****************************************************************
8101 _spoolss_AddPrinterDriverEx
8102 ****************************************************************/
8104 WERROR _spoolss_AddPrinterDriverEx(struct pipes_struct *p,
8105 struct spoolss_AddPrinterDriverEx *r)
8107 WERROR err = WERR_OK;
8108 const char *driver_name = NULL;
8113 case NDR_SPOOLSS_ADDPRINTERDRIVER:
8114 fn = "_spoolss_AddPrinterDriver";
8116 case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
8117 fn = "_spoolss_AddPrinterDriverEx";
8120 return WERR_INVALID_PARAM;
8124 * we only support the semantics of AddPrinterDriver()
8125 * i.e. only copy files that are newer than existing ones
8128 if (r->in.flags == 0) {
8129 return WERR_INVALID_PARAM;
8132 if (r->in.flags != APD_COPY_NEW_FILES) {
8133 return WERR_ACCESS_DENIED;
8137 if (r->in.info_ctr->level != 3 && r->in.info_ctr->level != 6) {
8138 /* Clever hack from Martin Zielinski <mz@seh.de>
8139 * to allow downgrade from level 8 (Vista).
8141 DEBUG(0,("%s: level %d not yet implemented\n", fn,
8142 r->in.info_ctr->level));
8143 return WERR_UNKNOWN_LEVEL;
8146 DEBUG(5,("Cleaning driver's information\n"));
8147 err = clean_up_driver_struct(p->mem_ctx, p->session_info, r->in.info_ctr);
8148 if (!W_ERROR_IS_OK(err))
8151 DEBUG(5,("Moving driver to final destination\n"));
8152 err = move_driver_to_download_area(p->session_info, r->in.info_ctr);
8153 if (!W_ERROR_IS_OK(err)) {
8157 err = winreg_add_driver_internal(p->mem_ctx,
8158 get_session_info_system(),
8163 if (!W_ERROR_IS_OK(err)) {
8168 * I think this is where he DrvUpgradePrinter() hook would be
8169 * be called in a driver's interface DLL on a Windows NT 4.0/2k
8170 * server. Right now, we just need to send ourselves a message
8171 * to update each printer bound to this driver. --jerry
8174 if (!srv_spoolss_drv_upgrade_printer(driver_name, p->msg_ctx)) {
8175 DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
8183 /****************************************************************
8184 _spoolss_AddPrinterDriver
8185 ****************************************************************/
8187 WERROR _spoolss_AddPrinterDriver(struct pipes_struct *p,
8188 struct spoolss_AddPrinterDriver *r)
8190 struct spoolss_AddPrinterDriverEx a;
8192 switch (r->in.info_ctr->level) {
8199 return WERR_UNKNOWN_LEVEL;
8202 a.in.servername = r->in.servername;
8203 a.in.info_ctr = r->in.info_ctr;
8204 a.in.flags = APD_COPY_NEW_FILES;
8206 return _spoolss_AddPrinterDriverEx(p, &a);
8209 /****************************************************************************
8210 ****************************************************************************/
8212 struct _spoolss_paths {
8218 enum { SPOOLSS_DRIVER_PATH, SPOOLSS_PRTPROCS_PATH };
8220 static const struct _spoolss_paths spoolss_paths[]= {
8221 { SPOOLSS_DRIVER_PATH, "print$", "DRIVERS" },
8222 { SPOOLSS_PRTPROCS_PATH, "prnproc$", "PRTPROCS" }
8225 static WERROR compose_spoolss_server_path(TALLOC_CTX *mem_ctx,
8226 const char *servername,
8227 const char *environment,
8231 const char *pservername = NULL;
8232 const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
8233 const char *short_archi;
8237 /* environment may be empty */
8238 if (environment && strlen(environment)) {
8239 long_archi = environment;
8242 /* servername may be empty */
8243 if (servername && strlen(servername)) {
8244 pservername = canon_servername(servername);
8246 if (!is_myname_or_ipaddr(pservername)) {
8247 return WERR_INVALID_PARAM;
8251 if (!(short_archi = get_short_archi(long_archi))) {
8252 return WERR_INVALID_ENVIRONMENT;
8255 switch (component) {
8256 case SPOOLSS_PRTPROCS_PATH:
8257 case SPOOLSS_DRIVER_PATH:
8259 *path = talloc_asprintf(mem_ctx,
8262 spoolss_paths[component].share,
8265 *path = talloc_asprintf(mem_ctx, "%s\\%s\\%s",
8266 SPOOLSS_DEFAULT_SERVER_PATH,
8267 spoolss_paths[component].dir,
8272 return WERR_INVALID_PARAM;
8282 /****************************************************************************
8283 ****************************************************************************/
8285 static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
8286 const char *servername,
8287 const char *environment,
8288 struct spoolss_DriverDirectoryInfo1 *r)
8293 werr = compose_spoolss_server_path(mem_ctx,
8296 SPOOLSS_DRIVER_PATH,
8298 if (!W_ERROR_IS_OK(werr)) {
8302 DEBUG(4,("printer driver directory: [%s]\n", path));
8304 r->directory_name = path;
8309 /****************************************************************
8310 _spoolss_GetPrinterDriverDirectory
8311 ****************************************************************/
8313 WERROR _spoolss_GetPrinterDriverDirectory(struct pipes_struct *p,
8314 struct spoolss_GetPrinterDriverDirectory *r)
8318 /* that's an [in out] buffer */
8320 if (!r->in.buffer && (r->in.offered != 0)) {
8321 return WERR_INVALID_PARAM;
8324 DEBUG(5,("_spoolss_GetPrinterDriverDirectory: level %d\n",
8329 /* r->in.level is ignored */
8331 werror = getprinterdriverdir_level_1(p->mem_ctx,
8334 &r->out.info->info1);
8335 if (!W_ERROR_IS_OK(werror)) {
8336 TALLOC_FREE(r->out.info);
8340 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_DriverDirectoryInfo,
8341 r->out.info, r->in.level);
8342 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
8344 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8347 /****************************************************************
8348 _spoolss_EnumPrinterData
8349 ****************************************************************/
8351 WERROR _spoolss_EnumPrinterData(struct pipes_struct *p,
8352 struct spoolss_EnumPrinterData *r)
8355 struct spoolss_EnumPrinterDataEx r2;
8357 struct spoolss_PrinterEnumValues *info, *val = NULL;
8360 r2.in.handle = r->in.handle;
8361 r2.in.key_name = "PrinterDriverData";
8363 r2.out.count = &count;
8364 r2.out.info = &info;
8365 r2.out.needed = &needed;
8367 result = _spoolss_EnumPrinterDataEx(p, &r2);
8368 if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
8369 r2.in.offered = needed;
8370 result = _spoolss_EnumPrinterDataEx(p, &r2);
8372 if (!W_ERROR_IS_OK(result)) {
8377 * The NT machine wants to know the biggest size of value and data
8379 * cf: MSDN EnumPrinterData remark section
8382 if (!r->in.value_offered && !r->in.data_offered) {
8383 uint32_t biggest_valuesize = 0;
8384 uint32_t biggest_datasize = 0;
8387 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8389 for (i=0; i<count; i++) {
8391 name_length = strlen(info[i].value_name);
8392 if (strlen(info[i].value_name) > biggest_valuesize) {
8393 biggest_valuesize = name_length;
8396 if (info[i].data_length > biggest_datasize) {
8397 biggest_datasize = info[i].data_length;
8400 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8404 /* the value is an UNICODE string but real_value_size is the length
8405 in bytes including the trailing 0 */
8407 *r->out.value_needed = 2 * (1 + biggest_valuesize);
8408 *r->out.data_needed = biggest_datasize;
8410 DEBUG(6,("final values: [%d], [%d]\n",
8411 *r->out.value_needed, *r->out.data_needed));
8416 if (r->in.enum_index < count) {
8417 val = &info[r->in.enum_index];
8421 /* out_value should default to "" or else NT4 has
8422 problems unmarshalling the response */
8424 if (r->in.value_offered) {
8425 *r->out.value_needed = 1;
8426 r->out.value_name = talloc_strdup(r, "");
8427 if (!r->out.value_name) {
8431 r->out.value_name = NULL;
8432 *r->out.value_needed = 0;
8435 /* the data is counted in bytes */
8437 *r->out.data_needed = r->in.data_offered;
8439 result = WERR_NO_MORE_ITEMS;
8443 * - counted in bytes in the request
8444 * - counted in UNICODE chars in the max reply
8445 * - counted in bytes in the real size
8447 * take a pause *before* coding not *during* coding
8451 if (r->in.value_offered) {
8452 r->out.value_name = talloc_strdup(r, val->value_name);
8453 if (!r->out.value_name) {
8456 *r->out.value_needed = val->value_name_len;
8458 r->out.value_name = NULL;
8459 *r->out.value_needed = 0;
8464 *r->out.type = val->type;
8466 /* data - counted in bytes */
8469 * See the section "Dynamically Typed Query Parameters"
8473 if (r->out.data && val->data && val->data->data &&
8474 val->data_length && r->in.data_offered) {
8475 memcpy(r->out.data, val->data->data,
8476 MIN(val->data_length,r->in.data_offered));
8479 *r->out.data_needed = val->data_length;
8487 /****************************************************************
8488 _spoolss_SetPrinterData
8489 ****************************************************************/
8491 WERROR _spoolss_SetPrinterData(struct pipes_struct *p,
8492 struct spoolss_SetPrinterData *r)
8494 struct spoolss_SetPrinterDataEx r2;
8496 r2.in.handle = r->in.handle;
8497 r2.in.key_name = "PrinterDriverData";
8498 r2.in.value_name = r->in.value_name;
8499 r2.in.type = r->in.type;
8500 r2.in.data = r->in.data;
8501 r2.in.offered = r->in.offered;
8503 return _spoolss_SetPrinterDataEx(p, &r2);
8506 /****************************************************************
8507 _spoolss_ResetPrinter
8508 ****************************************************************/
8510 WERROR _spoolss_ResetPrinter(struct pipes_struct *p,
8511 struct spoolss_ResetPrinter *r)
8513 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8516 DEBUG(5,("_spoolss_ResetPrinter\n"));
8519 * All we do is to check to see if the handle and queue is valid.
8520 * This call really doesn't mean anything to us because we only
8521 * support RAW printing. --jerry
8525 DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
8526 OUR_HANDLE(r->in.handle)));
8530 if (!get_printer_snum(p, r->in.handle, &snum, NULL))
8534 /* blindly return success */
8538 /****************************************************************
8539 _spoolss_DeletePrinterData
8540 ****************************************************************/
8542 WERROR _spoolss_DeletePrinterData(struct pipes_struct *p,
8543 struct spoolss_DeletePrinterData *r)
8545 struct spoolss_DeletePrinterDataEx r2;
8547 r2.in.handle = r->in.handle;
8548 r2.in.key_name = "PrinterDriverData";
8549 r2.in.value_name = r->in.value_name;
8551 return _spoolss_DeletePrinterDataEx(p, &r2);
8554 /****************************************************************
8556 ****************************************************************/
8558 WERROR _spoolss_AddForm(struct pipes_struct *p,
8559 struct spoolss_AddForm *r)
8561 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8563 WERROR status = WERR_OK;
8564 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8565 struct dcerpc_binding_handle *b;
8566 TALLOC_CTX *tmp_ctx = NULL;
8568 DEBUG(5,("_spoolss_AddForm\n"));
8571 DEBUG(2,("_spoolss_AddForm: Invalid handle (%s:%u:%u).\n",
8572 OUR_HANDLE(r->in.handle)));
8576 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8577 and not a printer admin, then fail */
8579 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8580 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8581 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8582 p->session_info->info->domain_name,
8584 p->session_info->security_token,
8585 lp_printer_admin(snum))) {
8586 DEBUG(2,("_spoolss_Addform: denied by insufficient permissions.\n"));
8587 return WERR_ACCESS_DENIED;
8590 switch (form->flags) {
8591 case SPOOLSS_FORM_USER:
8592 case SPOOLSS_FORM_BUILTIN:
8593 case SPOOLSS_FORM_PRINTER:
8596 return WERR_INVALID_PARAM;
8599 tmp_ctx = talloc_new(p->mem_ctx);
8604 status = winreg_printer_binding_handle(tmp_ctx,
8605 get_session_info_system(),
8608 if (!W_ERROR_IS_OK(status)) {
8612 status = winreg_printer_addform1(tmp_ctx, b, form);
8613 if (!W_ERROR_IS_OK(status)) {
8618 * ChangeID must always be set if this is a printer
8620 if (Printer->printer_type == SPLHND_PRINTER) {
8621 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8622 status = WERR_BADFID;
8626 status = winreg_printer_update_changeid(tmp_ctx, b,
8627 lp_const_servicename(snum));
8631 talloc_free(tmp_ctx);
8635 /****************************************************************
8637 ****************************************************************/
8639 WERROR _spoolss_DeleteForm(struct pipes_struct *p,
8640 struct spoolss_DeleteForm *r)
8642 const char *form_name = r->in.form_name;
8643 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8645 WERROR status = WERR_OK;
8646 struct dcerpc_binding_handle *b;
8647 TALLOC_CTX *tmp_ctx = NULL;
8649 DEBUG(5,("_spoolss_DeleteForm\n"));
8652 DEBUG(2,("_spoolss_DeleteForm: Invalid handle (%s:%u:%u).\n",
8653 OUR_HANDLE(r->in.handle)));
8657 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8658 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8659 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8660 p->session_info->info->domain_name,
8662 p->session_info->security_token,
8663 lp_printer_admin(snum))) {
8664 DEBUG(2,("_spoolss_DeleteForm: denied by insufficient permissions.\n"));
8665 return WERR_ACCESS_DENIED;
8668 tmp_ctx = talloc_new(p->mem_ctx);
8673 status = winreg_printer_binding_handle(tmp_ctx,
8674 get_session_info_system(),
8677 if (!W_ERROR_IS_OK(status)) {
8681 status = winreg_printer_deleteform1(tmp_ctx, b, form_name);
8682 if (!W_ERROR_IS_OK(status)) {
8687 * ChangeID must always be set if this is a printer
8689 if (Printer->printer_type == SPLHND_PRINTER) {
8690 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8691 status = WERR_BADFID;
8695 status = winreg_printer_update_changeid(tmp_ctx, b,
8696 lp_const_servicename(snum));
8700 talloc_free(tmp_ctx);
8704 /****************************************************************
8706 ****************************************************************/
8708 WERROR _spoolss_SetForm(struct pipes_struct *p,
8709 struct spoolss_SetForm *r)
8711 struct spoolss_AddFormInfo1 *form = r->in.info.info1;
8712 const char *form_name = r->in.form_name;
8714 WERROR status = WERR_OK;
8715 struct dcerpc_binding_handle *b;
8716 TALLOC_CTX *tmp_ctx = NULL;
8718 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
8720 DEBUG(5,("_spoolss_SetForm\n"));
8723 DEBUG(2,("_spoolss_SetForm: Invalid handle (%s:%u:%u).\n",
8724 OUR_HANDLE(r->in.handle)));
8728 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
8729 and not a printer admin, then fail */
8731 if ((p->session_info->unix_token->uid != sec_initial_uid()) &&
8732 !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_PRINT_OPERATOR) &&
8733 !token_contains_name_in_list(uidtoname(p->session_info->unix_token->uid),
8734 p->session_info->info->domain_name,
8736 p->session_info->security_token,
8737 lp_printer_admin(snum))) {
8738 DEBUG(2,("_spoolss_Setform: denied by insufficient permissions.\n"));
8739 return WERR_ACCESS_DENIED;
8742 tmp_ctx = talloc_new(p->mem_ctx);
8747 status = winreg_printer_binding_handle(tmp_ctx,
8748 get_session_info_system(),
8751 if (!W_ERROR_IS_OK(status)) {
8755 status = winreg_printer_setform1(tmp_ctx, b,
8758 if (!W_ERROR_IS_OK(status)) {
8763 * ChangeID must always be set if this is a printer
8765 if (Printer->printer_type == SPLHND_PRINTER) {
8766 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
8767 status = WERR_BADFID;
8771 status = winreg_printer_update_changeid(tmp_ctx, b,
8772 lp_const_servicename(snum));
8776 talloc_free(tmp_ctx);
8780 /****************************************************************************
8781 fill_print_processor1
8782 ****************************************************************************/
8784 static WERROR fill_print_processor1(TALLOC_CTX *mem_ctx,
8785 struct spoolss_PrintProcessorInfo1 *r,
8786 const char *print_processor_name)
8788 r->print_processor_name = talloc_strdup(mem_ctx, print_processor_name);
8789 W_ERROR_HAVE_NO_MEMORY(r->print_processor_name);
8794 /****************************************************************************
8795 enumprintprocessors level 1.
8796 ****************************************************************************/
8798 static WERROR enumprintprocessors_level_1(TALLOC_CTX *mem_ctx,
8799 union spoolss_PrintProcessorInfo **info_p,
8802 union spoolss_PrintProcessorInfo *info;
8805 info = talloc_array(mem_ctx, union spoolss_PrintProcessorInfo, 1);
8806 W_ERROR_HAVE_NO_MEMORY(info);
8810 result = fill_print_processor1(info, &info[0].info1, "winprint");
8811 if (!W_ERROR_IS_OK(result)) {
8816 if (!W_ERROR_IS_OK(result)) {
8827 /****************************************************************
8828 _spoolss_EnumPrintProcessors
8829 ****************************************************************/
8831 WERROR _spoolss_EnumPrintProcessors(struct pipes_struct *p,
8832 struct spoolss_EnumPrintProcessors *r)
8836 /* that's an [in out] buffer */
8838 if (!r->in.buffer && (r->in.offered != 0)) {
8839 return WERR_INVALID_PARAM;
8842 DEBUG(5,("_spoolss_EnumPrintProcessors\n"));
8845 * Enumerate the print processors ...
8847 * Just reply with "winprint", to keep NT happy
8848 * and I can use my nice printer checker.
8853 *r->out.info = NULL;
8855 if (!get_short_archi(r->in.environment)) {
8856 return WERR_INVALID_ENVIRONMENT;
8859 switch (r->in.level) {
8861 result = enumprintprocessors_level_1(p->mem_ctx, r->out.info,
8865 return WERR_UNKNOWN_LEVEL;
8868 if (!W_ERROR_IS_OK(result)) {
8872 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8873 spoolss_EnumPrintProcessors,
8874 *r->out.info, r->in.level,
8876 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8877 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8879 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8882 /****************************************************************************
8883 fill_printprocdatatype1
8884 ****************************************************************************/
8886 static WERROR fill_printprocdatatype1(TALLOC_CTX *mem_ctx,
8887 struct spoolss_PrintProcDataTypesInfo1 *r,
8888 const char *name_array)
8890 r->name_array = talloc_strdup(mem_ctx, name_array);
8891 W_ERROR_HAVE_NO_MEMORY(r->name_array);
8896 /****************************************************************************
8897 enumprintprocdatatypes level 1.
8898 ****************************************************************************/
8900 static WERROR enumprintprocdatatypes_level_1(TALLOC_CTX *mem_ctx,
8901 union spoolss_PrintProcDataTypesInfo **info_p,
8905 union spoolss_PrintProcDataTypesInfo *info;
8907 info = talloc_array(mem_ctx, union spoolss_PrintProcDataTypesInfo, 1);
8908 W_ERROR_HAVE_NO_MEMORY(info);
8912 result = fill_printprocdatatype1(info, &info[0].info1, "RAW");
8913 if (!W_ERROR_IS_OK(result)) {
8918 if (!W_ERROR_IS_OK(result)) {
8929 /****************************************************************
8930 _spoolss_EnumPrintProcDataTypes
8931 ****************************************************************/
8933 WERROR _spoolss_EnumPrintProcDataTypes(struct pipes_struct *p,
8934 struct spoolss_EnumPrintProcDataTypes *r)
8938 /* that's an [in out] buffer */
8940 if (!r->in.buffer && (r->in.offered != 0)) {
8941 return WERR_INVALID_PARAM;
8944 DEBUG(5,("_spoolss_EnumPrintProcDataTypes\n"));
8948 *r->out.info = NULL;
8950 if (r->in.print_processor_name == NULL ||
8951 !strequal(r->in.print_processor_name, "winprint")) {
8952 return WERR_UNKNOWN_PRINTPROCESSOR;
8955 switch (r->in.level) {
8957 result = enumprintprocdatatypes_level_1(p->mem_ctx, r->out.info,
8961 return WERR_UNKNOWN_LEVEL;
8964 if (!W_ERROR_IS_OK(result)) {
8968 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
8969 spoolss_EnumPrintProcDataTypes,
8970 *r->out.info, r->in.level,
8972 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
8973 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
8975 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
8978 /****************************************************************************
8980 ****************************************************************************/
8982 static WERROR fill_monitor_1(TALLOC_CTX *mem_ctx,
8983 struct spoolss_MonitorInfo1 *r,
8984 const char *monitor_name)
8986 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
8987 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
8992 /****************************************************************************
8994 ****************************************************************************/
8996 static WERROR fill_monitor_2(TALLOC_CTX *mem_ctx,
8997 struct spoolss_MonitorInfo2 *r,
8998 const char *monitor_name,
8999 const char *environment,
9000 const char *dll_name)
9002 r->monitor_name = talloc_strdup(mem_ctx, monitor_name);
9003 W_ERROR_HAVE_NO_MEMORY(r->monitor_name);
9004 r->environment = talloc_strdup(mem_ctx, environment);
9005 W_ERROR_HAVE_NO_MEMORY(r->environment);
9006 r->dll_name = talloc_strdup(mem_ctx, dll_name);
9007 W_ERROR_HAVE_NO_MEMORY(r->dll_name);
9012 /****************************************************************************
9013 enumprintmonitors level 1.
9014 ****************************************************************************/
9016 static WERROR enumprintmonitors_level_1(TALLOC_CTX *mem_ctx,
9017 union spoolss_MonitorInfo **info_p,
9020 union spoolss_MonitorInfo *info;
9021 WERROR result = WERR_OK;
9023 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9024 W_ERROR_HAVE_NO_MEMORY(info);
9028 result = fill_monitor_1(info, &info[0].info1,
9030 if (!W_ERROR_IS_OK(result)) {
9034 result = fill_monitor_1(info, &info[1].info1,
9036 if (!W_ERROR_IS_OK(result)) {
9041 if (!W_ERROR_IS_OK(result)) {
9052 /****************************************************************************
9053 enumprintmonitors level 2.
9054 ****************************************************************************/
9056 static WERROR enumprintmonitors_level_2(TALLOC_CTX *mem_ctx,
9057 union spoolss_MonitorInfo **info_p,
9060 union spoolss_MonitorInfo *info;
9061 WERROR result = WERR_OK;
9063 info = talloc_array(mem_ctx, union spoolss_MonitorInfo, 2);
9064 W_ERROR_HAVE_NO_MEMORY(info);
9068 result = fill_monitor_2(info, &info[0].info2,
9070 "Windows NT X86", /* FIXME */
9072 if (!W_ERROR_IS_OK(result)) {
9076 result = fill_monitor_2(info, &info[1].info2,
9078 "Windows NT X86", /* FIXME */
9080 if (!W_ERROR_IS_OK(result)) {
9085 if (!W_ERROR_IS_OK(result)) {
9096 /****************************************************************
9097 _spoolss_EnumMonitors
9098 ****************************************************************/
9100 WERROR _spoolss_EnumMonitors(struct pipes_struct *p,
9101 struct spoolss_EnumMonitors *r)
9105 /* that's an [in out] buffer */
9107 if (!r->in.buffer && (r->in.offered != 0)) {
9108 return WERR_INVALID_PARAM;
9111 DEBUG(5,("_spoolss_EnumMonitors\n"));
9114 * Enumerate the print monitors ...
9116 * Just reply with "Local Port", to keep NT happy
9117 * and I can use my nice printer checker.
9122 *r->out.info = NULL;
9124 switch (r->in.level) {
9126 result = enumprintmonitors_level_1(p->mem_ctx, r->out.info,
9130 result = enumprintmonitors_level_2(p->mem_ctx, r->out.info,
9134 return WERR_UNKNOWN_LEVEL;
9137 if (!W_ERROR_IS_OK(result)) {
9141 *r->out.needed = SPOOLSS_BUFFER_UNION_ARRAY(p->mem_ctx,
9142 spoolss_EnumMonitors,
9143 *r->out.info, r->in.level,
9145 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9146 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, 0);
9148 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9151 /****************************************************************************
9152 ****************************************************************************/
9154 static WERROR getjob_level_1(TALLOC_CTX *mem_ctx,
9155 const print_queue_struct *queue,
9156 int count, int snum,
9157 struct spoolss_PrinterInfo2 *pinfo2,
9159 struct spoolss_JobInfo1 *r)
9164 for (i=0; i<count; i++) {
9165 if (queue[i].job == (int)jobid) {
9171 if (found == false) {
9172 /* NT treats not found as bad param... yet another bad choice */
9173 return WERR_INVALID_PARAM;
9176 return fill_job_info1(mem_ctx,
9184 /****************************************************************************
9185 ****************************************************************************/
9187 static WERROR getjob_level_2(TALLOC_CTX *mem_ctx,
9188 const print_queue_struct *queue,
9189 int count, int snum,
9190 struct spoolss_PrinterInfo2 *pinfo2,
9192 struct spoolss_JobInfo2 *r)
9196 struct spoolss_DeviceMode *devmode;
9199 for (i=0; i<count; i++) {
9200 if (queue[i].job == (int)jobid) {
9206 if (found == false) {
9207 /* NT treats not found as bad param... yet another bad
9209 return WERR_INVALID_PARAM;
9213 * if the print job does not have a DEVMODE associated with it,
9214 * just use the one for the printer. A NULL devicemode is not
9215 * a failure condition
9218 devmode = print_job_devmode(lp_const_servicename(snum), jobid);
9220 result = spoolss_create_default_devmode(mem_ctx,
9221 pinfo2->printername,
9223 if (!W_ERROR_IS_OK(result)) {
9224 DEBUG(3, ("Can't proceed w/o a devmode!"));
9229 return fill_job_info2(mem_ctx,
9238 /****************************************************************
9240 ****************************************************************/
9242 WERROR _spoolss_GetJob(struct pipes_struct *p,
9243 struct spoolss_GetJob *r)
9245 WERROR result = WERR_OK;
9246 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9249 print_queue_struct *queue = NULL;
9250 print_status_struct prt_status;
9252 /* that's an [in out] buffer */
9254 if (!r->in.buffer && (r->in.offered != 0)) {
9255 return WERR_INVALID_PARAM;
9258 DEBUG(5,("_spoolss_GetJob\n"));
9262 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9266 result = winreg_get_printer_internal(p->mem_ctx,
9267 get_session_info_system(),
9269 lp_const_servicename(snum),
9271 if (!W_ERROR_IS_OK(result)) {
9275 count = print_queue_status(p->msg_ctx, snum, &queue, &prt_status);
9277 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9278 count, prt_status.status, prt_status.message));
9280 switch (r->in.level) {
9282 result = getjob_level_1(p->mem_ctx,
9283 queue, count, snum, pinfo2,
9284 r->in.job_id, &r->out.info->info1);
9287 result = getjob_level_2(p->mem_ctx,
9288 queue, count, snum, pinfo2,
9289 r->in.job_id, &r->out.info->info2);
9292 result = WERR_UNKNOWN_LEVEL;
9297 TALLOC_FREE(pinfo2);
9299 if (!W_ERROR_IS_OK(result)) {
9300 TALLOC_FREE(r->out.info);
9304 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_JobInfo, r->out.info,
9306 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9308 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9311 /****************************************************************
9312 _spoolss_GetPrinterDataEx
9313 ****************************************************************/
9315 WERROR _spoolss_GetPrinterDataEx(struct pipes_struct *p,
9316 struct spoolss_GetPrinterDataEx *r)
9319 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9320 const char *printer;
9322 WERROR result = WERR_OK;
9324 enum winreg_Type val_type = REG_NONE;
9325 uint8_t *val_data = NULL;
9326 uint32_t val_size = 0;
9327 struct dcerpc_binding_handle *b;
9328 TALLOC_CTX *tmp_ctx;
9330 DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
9332 DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
9333 r->in.key_name, r->in.value_name));
9335 /* in case of problem, return some default values */
9338 *r->out.type = REG_NONE;
9340 tmp_ctx = talloc_new(p->mem_ctx);
9346 DEBUG(2,("_spoolss_GetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9347 OUR_HANDLE(r->in.handle)));
9348 result = WERR_BADFID;
9352 /* check to see if the keyname is valid */
9353 if (!strlen(r->in.key_name)) {
9354 result = WERR_INVALID_PARAM;
9358 /* Is the handle to a printer or to the server? */
9360 if (Printer->printer_type == SPLHND_SERVER) {
9362 union spoolss_PrinterData data;
9364 result = getprinterdata_printer_server(tmp_ctx,
9368 if (!W_ERROR_IS_OK(result)) {
9372 result = push_spoolss_PrinterData(tmp_ctx, &blob,
9373 *r->out.type, &data);
9374 if (!W_ERROR_IS_OK(result)) {
9378 *r->out.needed = blob.length;
9380 if (r->in.offered >= *r->out.needed) {
9381 memcpy(r->out.data, blob.data, blob.length);
9388 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9389 result = WERR_BADFID;
9392 printer = lp_const_servicename(snum);
9394 result = winreg_printer_binding_handle(tmp_ctx,
9395 get_session_info_system(),
9398 if (!W_ERROR_IS_OK(result)) {
9402 /* XP sends this and wants the ChangeID value from PRINTER_INFO_0 */
9403 if (strequal(r->in.key_name, SPOOL_PRINTERDATA_KEY) &&
9404 strequal(r->in.value_name, "ChangeId")) {
9405 *r->out.type = REG_DWORD;
9407 if (r->in.offered >= *r->out.needed) {
9408 uint32_t changeid = 0;
9410 result = winreg_printer_get_changeid(tmp_ctx, b,
9413 if (!W_ERROR_IS_OK(result)) {
9417 SIVAL(r->out.data, 0, changeid);
9423 result = winreg_get_printer_dataex(tmp_ctx, b,
9430 if (!W_ERROR_IS_OK(result)) {
9434 *r->out.needed = val_size;
9435 *r->out.type = val_type;
9437 if (r->in.offered >= *r->out.needed) {
9438 memcpy(r->out.data, val_data, val_size);
9442 /* NOTE: do not replace type when returning WERR_MORE_DATA */
9444 if (W_ERROR_IS_OK(result)) {
9445 result = SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9448 talloc_free(tmp_ctx);
9452 /****************************************************************
9453 _spoolss_SetPrinterDataEx
9454 ****************************************************************/
9456 WERROR _spoolss_SetPrinterDataEx(struct pipes_struct *p,
9457 struct spoolss_SetPrinterDataEx *r)
9459 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
9461 WERROR result = WERR_OK;
9462 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9464 struct dcerpc_binding_handle *b;
9465 TALLOC_CTX *tmp_ctx;
9467 DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
9469 /* From MSDN documentation of SetPrinterDataEx: pass request to
9470 SetPrinterData if key is "PrinterDriverData" */
9473 DEBUG(2,("_spoolss_SetPrinterDataEx: Invalid handle (%s:%u:%u).\n",
9474 OUR_HANDLE(r->in.handle)));
9478 if (Printer->printer_type == SPLHND_SERVER) {
9479 DEBUG(10,("_spoolss_SetPrinterDataEx: "
9480 "Not implemented for server handles yet\n"));
9481 return WERR_INVALID_PARAM;
9484 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9489 * Access check : NT returns "access denied" if you make a
9490 * SetPrinterData call without the necessary privildge.
9491 * we were originally returning OK if nothing changed
9492 * which made Win2k issue **a lot** of SetPrinterData
9493 * when connecting to a printer --jerry
9496 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9497 DEBUG(3, ("_spoolss_SetPrinterDataEx: "
9498 "change denied by handle access permissions\n"));
9499 return WERR_ACCESS_DENIED;
9502 tmp_ctx = talloc_new(p->mem_ctx);
9507 result = winreg_printer_binding_handle(tmp_ctx,
9508 get_session_info_system(),
9511 if (!W_ERROR_IS_OK(result)) {
9515 result = winreg_get_printer(tmp_ctx, b,
9516 lp_servicename(snum),
9518 if (!W_ERROR_IS_OK(result)) {
9522 /* check for OID in valuename */
9524 oid_string = strchr(r->in.value_name, ',');
9530 /* save the registry data */
9532 result = winreg_set_printer_dataex(tmp_ctx, b,
9540 if (W_ERROR_IS_OK(result)) {
9541 /* save the OID if one was specified */
9543 char *str = talloc_asprintf(tmp_ctx, "%s\\%s",
9544 r->in.key_name, SPOOL_OID_KEY);
9546 result = WERR_NOMEM;
9551 * I'm not checking the status here on purpose. Don't know
9552 * if this is right, but I'm returning the status from the
9553 * previous set_printer_dataex() call. I have no idea if
9554 * this is right. --jerry
9556 winreg_set_printer_dataex(tmp_ctx, b,
9561 (uint8_t *) oid_string,
9562 strlen(oid_string) + 1);
9565 result = winreg_printer_update_changeid(tmp_ctx, b,
9566 lp_const_servicename(snum));
9571 talloc_free(tmp_ctx);
9575 /****************************************************************
9576 _spoolss_DeletePrinterDataEx
9577 ****************************************************************/
9579 WERROR _spoolss_DeletePrinterDataEx(struct pipes_struct *p,
9580 struct spoolss_DeletePrinterDataEx *r)
9582 const char *printer;
9584 WERROR status = WERR_OK;
9585 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9587 DEBUG(5,("_spoolss_DeletePrinterDataEx\n"));
9590 DEBUG(2,("_spoolss_DeletePrinterDataEx: "
9591 "Invalid handle (%s:%u:%u).\n",
9592 OUR_HANDLE(r->in.handle)));
9596 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9597 DEBUG(3, ("_spoolss_DeletePrinterDataEx: "
9598 "printer properties change denied by handle\n"));
9599 return WERR_ACCESS_DENIED;
9602 if (!r->in.value_name || !r->in.key_name) {
9606 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9609 printer = lp_const_servicename(snum);
9611 status = winreg_delete_printer_dataex_internal(p->mem_ctx,
9612 get_session_info_system(),
9617 if (W_ERROR_IS_OK(status)) {
9618 status = winreg_printer_update_changeid_internal(p->mem_ctx,
9619 get_session_info_system(),
9627 /****************************************************************
9628 _spoolss_EnumPrinterKey
9629 ****************************************************************/
9631 WERROR _spoolss_EnumPrinterKey(struct pipes_struct *p,
9632 struct spoolss_EnumPrinterKey *r)
9635 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9637 WERROR result = WERR_BADFILE;
9638 const char **array = NULL;
9641 DEBUG(4,("_spoolss_EnumPrinterKey\n"));
9644 DEBUG(2,("_spoolss_EnumPrinterKey: Invalid handle (%s:%u:%u).\n",
9645 OUR_HANDLE(r->in.handle)));
9649 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9653 result = winreg_enum_printer_key_internal(p->mem_ctx,
9654 get_session_info_system(),
9656 lp_const_servicename(snum),
9660 if (!W_ERROR_IS_OK(result)) {
9664 if (!push_reg_multi_sz(p->mem_ctx, &blob, array)) {
9665 result = WERR_NOMEM;
9669 *r->out._ndr_size = r->in.offered / 2;
9670 *r->out.needed = blob.length;
9672 if (r->in.offered < *r->out.needed) {
9673 result = WERR_MORE_DATA;
9676 r->out.key_buffer->string_array = array;
9680 if (!W_ERROR_IS_OK(result)) {
9682 if (!W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
9690 /****************************************************************
9691 _spoolss_DeletePrinterKey
9692 ****************************************************************/
9694 WERROR _spoolss_DeletePrinterKey(struct pipes_struct *p,
9695 struct spoolss_DeletePrinterKey *r)
9697 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9700 const char *printer;
9701 struct dcerpc_binding_handle *b;
9702 TALLOC_CTX *tmp_ctx;
9704 DEBUG(5,("_spoolss_DeletePrinterKey\n"));
9707 DEBUG(2,("_spoolss_DeletePrinterKey: Invalid handle (%s:%u:%u).\n",
9708 OUR_HANDLE(r->in.handle)));
9712 /* if keyname == NULL, return error */
9713 if ( !r->in.key_name )
9714 return WERR_INVALID_PARAM;
9716 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9720 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9721 DEBUG(3, ("_spoolss_DeletePrinterKey: "
9722 "printer properties change denied by handle\n"));
9723 return WERR_ACCESS_DENIED;
9726 printer = lp_const_servicename(snum);
9728 tmp_ctx = talloc_new(p->mem_ctx);
9733 status = winreg_printer_binding_handle(tmp_ctx,
9734 get_session_info_system(),
9737 if (!W_ERROR_IS_OK(status)) {
9741 /* delete the key and all subkeys */
9742 status = winreg_delete_printer_key(tmp_ctx, b,
9745 if (W_ERROR_IS_OK(status)) {
9746 status = winreg_printer_update_changeid(tmp_ctx, b,
9751 talloc_free(tmp_ctx);
9755 /****************************************************************
9756 _spoolss_EnumPrinterDataEx
9757 ****************************************************************/
9759 WERROR _spoolss_EnumPrinterDataEx(struct pipes_struct *p,
9760 struct spoolss_EnumPrinterDataEx *r)
9763 struct spoolss_PrinterEnumValues *info = NULL;
9764 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
9768 DEBUG(4,("_spoolss_EnumPrinterDataEx\n"));
9772 *r->out.info = NULL;
9775 DEBUG(2,("_spoolss_EnumPrinterDataEx: Invalid handle (%s:%u:%u1<).\n",
9776 OUR_HANDLE(r->in.handle)));
9781 * first check for a keyname of NULL or "". Win2k seems to send
9782 * this a lot and we should send back WERR_INVALID_PARAM
9783 * no need to spend time looking up the printer in this case.
9787 if (!strlen(r->in.key_name)) {
9788 result = WERR_INVALID_PARAM;
9792 if (!get_printer_snum(p, r->in.handle, &snum, NULL)) {
9796 /* now look for a match on the key name */
9797 result = winreg_enum_printer_dataex_internal(p->mem_ctx,
9798 get_session_info_system(),
9800 lp_const_servicename(snum),
9804 if (!W_ERROR_IS_OK(result)) {
9808 #if 0 /* FIXME - gd */
9809 /* housekeeping information in the reply */
9811 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9812 * the hand marshalled container size is a multiple
9813 * of 4 bytes for RPC alignment.
9817 needed += 4-(needed % 4);
9820 *r->out.count = count;
9821 *r->out.info = info;
9824 if (!W_ERROR_IS_OK(result)) {
9828 *r->out.needed = SPOOLSS_BUFFER_ARRAY(p->mem_ctx,
9829 spoolss_EnumPrinterDataEx,
9832 *r->out.info = SPOOLSS_BUFFER_OK(*r->out.info, NULL);
9833 *r->out.count = SPOOLSS_BUFFER_OK(*r->out.count, *r->out.count);
9835 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA);
9838 /****************************************************************************
9839 ****************************************************************************/
9841 static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
9842 const char *servername,
9843 const char *environment,
9844 struct spoolss_PrintProcessorDirectoryInfo1 *r)
9849 werr = compose_spoolss_server_path(mem_ctx,
9852 SPOOLSS_PRTPROCS_PATH,
9854 if (!W_ERROR_IS_OK(werr)) {
9858 DEBUG(4,("print processor directory: [%s]\n", path));
9860 r->directory_name = path;
9865 /****************************************************************
9866 _spoolss_GetPrintProcessorDirectory
9867 ****************************************************************/
9869 WERROR _spoolss_GetPrintProcessorDirectory(struct pipes_struct *p,
9870 struct spoolss_GetPrintProcessorDirectory *r)
9873 char *prnproc_share = NULL;
9874 bool prnproc_share_exists = false;
9877 /* that's an [in out] buffer */
9879 if (!r->in.buffer && (r->in.offered != 0)) {
9880 return WERR_INVALID_PARAM;
9883 DEBUG(5,("_spoolss_GetPrintProcessorDirectory: level %d\n",
9888 /* r->in.level is ignored */
9890 /* We always should reply with a local print processor directory so that
9891 * users are not forced to have a [prnproc$] share on the Samba spoolss
9892 * server, if users decide to do so, lets announce it though - Guenther */
9894 snum = find_service(talloc_tos(), "prnproc$", &prnproc_share);
9895 if (!prnproc_share) {
9899 prnproc_share_exists = true;
9902 result = getprintprocessordirectory_level_1(p->mem_ctx,
9903 prnproc_share_exists ? r->in.server : NULL,
9905 &r->out.info->info1);
9906 if (!W_ERROR_IS_OK(result)) {
9907 TALLOC_FREE(r->out.info);
9911 *r->out.needed = SPOOLSS_BUFFER_UNION(spoolss_PrintProcessorDirectoryInfo,
9912 r->out.info, r->in.level);
9913 r->out.info = SPOOLSS_BUFFER_OK(r->out.info, NULL);
9915 return SPOOLSS_BUFFER_OK(WERR_OK, WERR_INSUFFICIENT_BUFFER);
9918 /*******************************************************************
9919 ********************************************************************/
9921 static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
9922 const char *dllname)
9924 enum ndr_err_code ndr_err;
9925 struct spoolss_MonitorUi ui;
9927 ui.dll_name = dllname;
9929 ndr_err = ndr_push_struct_blob(buf, mem_ctx, &ui,
9930 (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
9931 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9932 NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
9934 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9937 /*******************************************************************
9938 Streams the monitor UI DLL name in UNICODE
9939 *******************************************************************/
9941 static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
9942 struct security_token *token, DATA_BLOB *in,
9943 DATA_BLOB *out, uint32_t *needed)
9945 const char *dllname = "tcpmonui.dll";
9947 *needed = (strlen(dllname)+1) * 2;
9949 if (out->length < *needed) {
9950 return WERR_INSUFFICIENT_BUFFER;
9953 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
9960 /*******************************************************************
9961 ********************************************************************/
9963 static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
9964 struct spoolss_PortData1 *port1,
9965 const DATA_BLOB *buf)
9967 enum ndr_err_code ndr_err;
9968 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port1,
9969 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
9970 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9971 NDR_PRINT_DEBUG(spoolss_PortData1, port1);
9973 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9976 /*******************************************************************
9977 ********************************************************************/
9979 static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
9980 struct spoolss_PortData2 *port2,
9981 const DATA_BLOB *buf)
9983 enum ndr_err_code ndr_err;
9984 ndr_err = ndr_pull_struct_blob(buf, mem_ctx, port2,
9985 (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
9986 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
9987 NDR_PRINT_DEBUG(spoolss_PortData2, port2);
9989 return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
9992 /*******************************************************************
9993 Create a new TCP/IP port
9994 *******************************************************************/
9996 static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
9997 struct security_token *token, DATA_BLOB *in,
9998 DATA_BLOB *out, uint32_t *needed)
10000 struct spoolss_PortData1 port1;
10001 struct spoolss_PortData2 port2;
10002 char *device_uri = NULL;
10005 const char *portname;
10006 const char *hostaddress;
10008 uint32_t port_number;
10011 /* peek for spoolss_PortData version */
10013 if (!in || (in->length < (128 + 4))) {
10014 return WERR_GENERAL_FAILURE;
10017 version = IVAL(in->data, 128);
10021 ZERO_STRUCT(port1);
10023 if (!pull_port_data_1(mem_ctx, &port1, in)) {
10027 portname = port1.portname;
10028 hostaddress = port1.hostaddress;
10029 queue = port1.queue;
10030 protocol = port1.protocol;
10031 port_number = port1.port_number;
10035 ZERO_STRUCT(port2);
10037 if (!pull_port_data_2(mem_ctx, &port2, in)) {
10041 portname = port2.portname;
10042 hostaddress = port2.hostaddress;
10043 queue = port2.queue;
10044 protocol = port2.protocol;
10045 port_number = port2.port_number;
10049 DEBUG(1,("xcvtcp_addport: "
10050 "unknown version of port_data: %d\n", version));
10051 return WERR_UNKNOWN_PORT;
10054 /* create the device URI and call the add_port_hook() */
10056 switch (protocol) {
10057 case PROTOCOL_RAWTCP_TYPE:
10058 device_uri = talloc_asprintf(mem_ctx,
10059 "socket://%s:%d/", hostaddress,
10063 case PROTOCOL_LPR_TYPE:
10064 device_uri = talloc_asprintf(mem_ctx,
10065 "lpr://%s/%s", hostaddress, queue );
10069 return WERR_UNKNOWN_PORT;
10076 return add_port_hook(mem_ctx, token, portname, device_uri);
10079 /*******************************************************************
10080 *******************************************************************/
10082 struct xcv_api_table xcvtcp_cmds[] = {
10083 { "MonitorUI", xcvtcp_monitorui },
10084 { "AddPort", xcvtcp_addport},
10088 static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
10089 struct security_token *token, const char *command,
10096 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
10098 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
10099 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
10100 return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10103 return WERR_BADFUNC;
10106 /*******************************************************************
10107 *******************************************************************/
10108 #if 0 /* don't support management using the "Local Port" monitor */
10110 static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
10111 struct security_token *token, DATA_BLOB *in,
10112 DATA_BLOB *out, uint32_t *needed)
10114 const char *dllname = "localui.dll";
10116 *needed = (strlen(dllname)+1) * 2;
10118 if (out->length < *needed) {
10119 return WERR_INSUFFICIENT_BUFFER;
10122 if (!push_monitorui_buf(mem_ctx, out, dllname)) {
10129 /*******************************************************************
10130 *******************************************************************/
10132 struct xcv_api_table xcvlocal_cmds[] = {
10133 { "MonitorUI", xcvlocal_monitorui },
10137 struct xcv_api_table xcvlocal_cmds[] = {
10144 /*******************************************************************
10145 *******************************************************************/
10147 static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
10148 struct security_token *token, const char *command,
10149 DATA_BLOB *inbuf, DATA_BLOB *outbuf,
10154 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
10156 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
10157 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
10158 return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
10160 return WERR_BADFUNC;
10163 /****************************************************************
10165 ****************************************************************/
10167 WERROR _spoolss_XcvData(struct pipes_struct *p,
10168 struct spoolss_XcvData *r)
10170 struct printer_handle *Printer = find_printer_index_by_hnd(p, r->in.handle);
10171 DATA_BLOB out_data = data_blob_null;
10175 DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
10176 OUR_HANDLE(r->in.handle)));
10177 return WERR_BADFID;
10180 /* Has to be a handle to the TCP/IP port monitor */
10182 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
10183 DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
10184 return WERR_BADFID;
10187 /* requires administrative access to the server */
10189 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
10190 DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
10191 return WERR_ACCESS_DENIED;
10194 /* Allocate the outgoing buffer */
10196 if (r->in.out_data_size) {
10197 out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
10198 if (out_data.data == NULL) {
10203 switch ( Printer->printer_type ) {
10204 case SPLHND_PORTMON_TCP:
10205 werror = process_xcvtcp_command(p->mem_ctx,
10206 p->session_info->security_token,
10207 r->in.function_name,
10208 &r->in.in_data, &out_data,
10211 case SPLHND_PORTMON_LOCAL:
10212 werror = process_xcvlocal_command(p->mem_ctx,
10213 p->session_info->security_token,
10214 r->in.function_name,
10215 &r->in.in_data, &out_data,
10219 werror = WERR_INVALID_PRINT_MONITOR;
10222 if (!W_ERROR_IS_OK(werror)) {
10226 *r->out.status_code = 0;
10228 if (r->out.out_data && out_data.data && r->in.out_data_size && out_data.length) {
10229 memcpy(r->out.out_data, out_data.data,
10230 MIN(r->in.out_data_size, out_data.length));
10236 /****************************************************************
10237 _spoolss_AddPrintProcessor
10238 ****************************************************************/
10240 WERROR _spoolss_AddPrintProcessor(struct pipes_struct *p,
10241 struct spoolss_AddPrintProcessor *r)
10243 /* for now, just indicate success and ignore the add. We'll
10244 automatically set the winprint processor for printer
10245 entries later. Used to debug the LexMark Optra S 1855 PCL
10251 /****************************************************************
10253 ****************************************************************/
10255 WERROR _spoolss_AddPort(struct pipes_struct *p,
10256 struct spoolss_AddPort *r)
10258 /* do what w2k3 does */
10260 return WERR_NOT_SUPPORTED;
10263 /****************************************************************
10264 _spoolss_GetPrinterDriver
10265 ****************************************************************/
10267 WERROR _spoolss_GetPrinterDriver(struct pipes_struct *p,
10268 struct spoolss_GetPrinterDriver *r)
10270 p->rng_fault_state = true;
10271 return WERR_NOT_SUPPORTED;
10274 /****************************************************************
10275 _spoolss_ReadPrinter
10276 ****************************************************************/
10278 WERROR _spoolss_ReadPrinter(struct pipes_struct *p,
10279 struct spoolss_ReadPrinter *r)
10281 p->rng_fault_state = true;
10282 return WERR_NOT_SUPPORTED;
10285 /****************************************************************
10286 _spoolss_WaitForPrinterChange
10287 ****************************************************************/
10289 WERROR _spoolss_WaitForPrinterChange(struct pipes_struct *p,
10290 struct spoolss_WaitForPrinterChange *r)
10292 p->rng_fault_state = true;
10293 return WERR_NOT_SUPPORTED;
10296 /****************************************************************
10297 _spoolss_ConfigurePort
10298 ****************************************************************/
10300 WERROR _spoolss_ConfigurePort(struct pipes_struct *p,
10301 struct spoolss_ConfigurePort *r)
10303 p->rng_fault_state = true;
10304 return WERR_NOT_SUPPORTED;
10307 /****************************************************************
10308 _spoolss_DeletePort
10309 ****************************************************************/
10311 WERROR _spoolss_DeletePort(struct pipes_struct *p,
10312 struct spoolss_DeletePort *r)
10314 p->rng_fault_state = true;
10315 return WERR_NOT_SUPPORTED;
10318 /****************************************************************
10319 _spoolss_CreatePrinterIC
10320 ****************************************************************/
10322 WERROR _spoolss_CreatePrinterIC(struct pipes_struct *p,
10323 struct spoolss_CreatePrinterIC *r)
10325 p->rng_fault_state = true;
10326 return WERR_NOT_SUPPORTED;
10329 /****************************************************************
10330 _spoolss_PlayGDIScriptOnPrinterIC
10331 ****************************************************************/
10333 WERROR _spoolss_PlayGDIScriptOnPrinterIC(struct pipes_struct *p,
10334 struct spoolss_PlayGDIScriptOnPrinterIC *r)
10336 p->rng_fault_state = true;
10337 return WERR_NOT_SUPPORTED;
10340 /****************************************************************
10341 _spoolss_DeletePrinterIC
10342 ****************************************************************/
10344 WERROR _spoolss_DeletePrinterIC(struct pipes_struct *p,
10345 struct spoolss_DeletePrinterIC *r)
10347 p->rng_fault_state = true;
10348 return WERR_NOT_SUPPORTED;
10351 /****************************************************************
10352 _spoolss_AddPrinterConnection
10353 ****************************************************************/
10355 WERROR _spoolss_AddPrinterConnection(struct pipes_struct *p,
10356 struct spoolss_AddPrinterConnection *r)
10358 p->rng_fault_state = true;
10359 return WERR_NOT_SUPPORTED;
10362 /****************************************************************
10363 _spoolss_DeletePrinterConnection
10364 ****************************************************************/
10366 WERROR _spoolss_DeletePrinterConnection(struct pipes_struct *p,
10367 struct spoolss_DeletePrinterConnection *r)
10369 p->rng_fault_state = true;
10370 return WERR_NOT_SUPPORTED;
10373 /****************************************************************
10374 _spoolss_PrinterMessageBox
10375 ****************************************************************/
10377 WERROR _spoolss_PrinterMessageBox(struct pipes_struct *p,
10378 struct spoolss_PrinterMessageBox *r)
10380 p->rng_fault_state = true;
10381 return WERR_NOT_SUPPORTED;
10384 /****************************************************************
10385 _spoolss_AddMonitor
10386 ****************************************************************/
10388 WERROR _spoolss_AddMonitor(struct pipes_struct *p,
10389 struct spoolss_AddMonitor *r)
10391 p->rng_fault_state = true;
10392 return WERR_NOT_SUPPORTED;
10395 /****************************************************************
10396 _spoolss_DeleteMonitor
10397 ****************************************************************/
10399 WERROR _spoolss_DeleteMonitor(struct pipes_struct *p,
10400 struct spoolss_DeleteMonitor *r)
10402 p->rng_fault_state = true;
10403 return WERR_NOT_SUPPORTED;
10406 /****************************************************************
10407 _spoolss_DeletePrintProcessor
10408 ****************************************************************/
10410 WERROR _spoolss_DeletePrintProcessor(struct pipes_struct *p,
10411 struct spoolss_DeletePrintProcessor *r)
10413 p->rng_fault_state = true;
10414 return WERR_NOT_SUPPORTED;
10417 /****************************************************************
10418 _spoolss_AddPrintProvidor
10419 ****************************************************************/
10421 WERROR _spoolss_AddPrintProvidor(struct pipes_struct *p,
10422 struct spoolss_AddPrintProvidor *r)
10424 p->rng_fault_state = true;
10425 return WERR_NOT_SUPPORTED;
10428 /****************************************************************
10429 _spoolss_DeletePrintProvidor
10430 ****************************************************************/
10432 WERROR _spoolss_DeletePrintProvidor(struct pipes_struct *p,
10433 struct spoolss_DeletePrintProvidor *r)
10435 p->rng_fault_state = true;
10436 return WERR_NOT_SUPPORTED;
10439 /****************************************************************
10440 _spoolss_FindFirstPrinterChangeNotification
10441 ****************************************************************/
10443 WERROR _spoolss_FindFirstPrinterChangeNotification(struct pipes_struct *p,
10444 struct spoolss_FindFirstPrinterChangeNotification *r)
10446 p->rng_fault_state = true;
10447 return WERR_NOT_SUPPORTED;
10450 /****************************************************************
10451 _spoolss_FindNextPrinterChangeNotification
10452 ****************************************************************/
10454 WERROR _spoolss_FindNextPrinterChangeNotification(struct pipes_struct *p,
10455 struct spoolss_FindNextPrinterChangeNotification *r)
10457 p->rng_fault_state = true;
10458 return WERR_NOT_SUPPORTED;
10461 /****************************************************************
10462 _spoolss_RouterFindFirstPrinterChangeNotificationOld
10463 ****************************************************************/
10465 WERROR _spoolss_RouterFindFirstPrinterChangeNotificationOld(struct pipes_struct *p,
10466 struct spoolss_RouterFindFirstPrinterChangeNotificationOld *r)
10468 p->rng_fault_state = true;
10469 return WERR_NOT_SUPPORTED;
10472 /****************************************************************
10473 _spoolss_ReplyOpenPrinter
10474 ****************************************************************/
10476 WERROR _spoolss_ReplyOpenPrinter(struct pipes_struct *p,
10477 struct spoolss_ReplyOpenPrinter *r)
10479 p->rng_fault_state = true;
10480 return WERR_NOT_SUPPORTED;
10483 /****************************************************************
10484 _spoolss_RouterReplyPrinter
10485 ****************************************************************/
10487 WERROR _spoolss_RouterReplyPrinter(struct pipes_struct *p,
10488 struct spoolss_RouterReplyPrinter *r)
10490 p->rng_fault_state = true;
10491 return WERR_NOT_SUPPORTED;
10494 /****************************************************************
10495 _spoolss_ReplyClosePrinter
10496 ****************************************************************/
10498 WERROR _spoolss_ReplyClosePrinter(struct pipes_struct *p,
10499 struct spoolss_ReplyClosePrinter *r)
10501 p->rng_fault_state = true;
10502 return WERR_NOT_SUPPORTED;
10505 /****************************************************************
10507 ****************************************************************/
10509 WERROR _spoolss_AddPortEx(struct pipes_struct *p,
10510 struct spoolss_AddPortEx *r)
10512 p->rng_fault_state = true;
10513 return WERR_NOT_SUPPORTED;
10516 /****************************************************************
10517 _spoolss_RouterFindFirstPrinterChangeNotification
10518 ****************************************************************/
10520 WERROR _spoolss_RouterFindFirstPrinterChangeNotification(struct pipes_struct *p,
10521 struct spoolss_RouterFindFirstPrinterChangeNotification *r)
10523 p->rng_fault_state = true;
10524 return WERR_NOT_SUPPORTED;
10527 /****************************************************************
10528 _spoolss_SpoolerInit
10529 ****************************************************************/
10531 WERROR _spoolss_SpoolerInit(struct pipes_struct *p,
10532 struct spoolss_SpoolerInit *r)
10534 p->rng_fault_state = true;
10535 return WERR_NOT_SUPPORTED;
10538 /****************************************************************
10539 _spoolss_ResetPrinterEx
10540 ****************************************************************/
10542 WERROR _spoolss_ResetPrinterEx(struct pipes_struct *p,
10543 struct spoolss_ResetPrinterEx *r)
10545 p->rng_fault_state = true;
10546 return WERR_NOT_SUPPORTED;
10549 /****************************************************************
10550 _spoolss_RouterReplyPrinterEx
10551 ****************************************************************/
10553 WERROR _spoolss_RouterReplyPrinterEx(struct pipes_struct *p,
10554 struct spoolss_RouterReplyPrinterEx *r)
10556 p->rng_fault_state = true;
10557 return WERR_NOT_SUPPORTED;
10560 /****************************************************************
10562 ****************************************************************/
10564 WERROR _spoolss_44(struct pipes_struct *p,
10565 struct spoolss_44 *r)
10567 p->rng_fault_state = true;
10568 return WERR_NOT_SUPPORTED;
10571 /****************************************************************
10573 ****************************************************************/
10575 WERROR _spoolss_SetPort(struct pipes_struct *p,
10576 struct spoolss_SetPort *r)
10578 p->rng_fault_state = true;
10579 return WERR_NOT_SUPPORTED;
10582 /****************************************************************
10584 ****************************************************************/
10586 WERROR _spoolss_4a(struct pipes_struct *p,
10587 struct spoolss_4a *r)
10589 p->rng_fault_state = true;
10590 return WERR_NOT_SUPPORTED;
10593 /****************************************************************
10595 ****************************************************************/
10597 WERROR _spoolss_4b(struct pipes_struct *p,
10598 struct spoolss_4b *r)
10600 p->rng_fault_state = true;
10601 return WERR_NOT_SUPPORTED;
10604 /****************************************************************
10606 ****************************************************************/
10608 WERROR _spoolss_4c(struct pipes_struct *p,
10609 struct spoolss_4c *r)
10611 p->rng_fault_state = true;
10612 return WERR_NOT_SUPPORTED;
10615 /****************************************************************
10617 ****************************************************************/
10619 WERROR _spoolss_53(struct pipes_struct *p,
10620 struct spoolss_53 *r)
10622 p->rng_fault_state = true;
10623 return WERR_NOT_SUPPORTED;
10626 /****************************************************************
10627 _spoolss_AddPerMachineConnection
10628 ****************************************************************/
10630 WERROR _spoolss_AddPerMachineConnection(struct pipes_struct *p,
10631 struct spoolss_AddPerMachineConnection *r)
10633 p->rng_fault_state = true;
10634 return WERR_NOT_SUPPORTED;
10637 /****************************************************************
10638 _spoolss_DeletePerMachineConnection
10639 ****************************************************************/
10641 WERROR _spoolss_DeletePerMachineConnection(struct pipes_struct *p,
10642 struct spoolss_DeletePerMachineConnection *r)
10644 p->rng_fault_state = true;
10645 return WERR_NOT_SUPPORTED;
10648 /****************************************************************
10649 _spoolss_EnumPerMachineConnections
10650 ****************************************************************/
10652 WERROR _spoolss_EnumPerMachineConnections(struct pipes_struct *p,
10653 struct spoolss_EnumPerMachineConnections *r)
10655 p->rng_fault_state = true;
10656 return WERR_NOT_SUPPORTED;
10659 /****************************************************************
10661 ****************************************************************/
10663 WERROR _spoolss_5a(struct pipes_struct *p,
10664 struct spoolss_5a *r)
10666 p->rng_fault_state = true;
10667 return WERR_NOT_SUPPORTED;
10670 /****************************************************************
10672 ****************************************************************/
10674 WERROR _spoolss_5b(struct pipes_struct *p,
10675 struct spoolss_5b *r)
10677 p->rng_fault_state = true;
10678 return WERR_NOT_SUPPORTED;
10681 /****************************************************************
10683 ****************************************************************/
10685 WERROR _spoolss_5c(struct pipes_struct *p,
10686 struct spoolss_5c *r)
10688 p->rng_fault_state = true;
10689 return WERR_NOT_SUPPORTED;
10692 /****************************************************************
10694 ****************************************************************/
10696 WERROR _spoolss_5d(struct pipes_struct *p,
10697 struct spoolss_5d *r)
10699 p->rng_fault_state = true;
10700 return WERR_NOT_SUPPORTED;
10703 /****************************************************************
10705 ****************************************************************/
10707 WERROR _spoolss_5e(struct pipes_struct *p,
10708 struct spoolss_5e *r)
10710 p->rng_fault_state = true;
10711 return WERR_NOT_SUPPORTED;
10714 /****************************************************************
10716 ****************************************************************/
10718 WERROR _spoolss_5f(struct pipes_struct *p,
10719 struct spoolss_5f *r)
10721 p->rng_fault_state = true;
10722 return WERR_NOT_SUPPORTED;
10725 /****************************************************************
10727 ****************************************************************/
10729 WERROR _spoolss_60(struct pipes_struct *p,
10730 struct spoolss_60 *r)
10732 p->rng_fault_state = true;
10733 return WERR_NOT_SUPPORTED;
10736 /****************************************************************
10738 ****************************************************************/
10740 WERROR _spoolss_61(struct pipes_struct *p,
10741 struct spoolss_61 *r)
10743 p->rng_fault_state = true;
10744 return WERR_NOT_SUPPORTED;
10747 /****************************************************************
10749 ****************************************************************/
10751 WERROR _spoolss_62(struct pipes_struct *p,
10752 struct spoolss_62 *r)
10754 p->rng_fault_state = true;
10755 return WERR_NOT_SUPPORTED;
10758 /****************************************************************
10760 ****************************************************************/
10762 WERROR _spoolss_63(struct pipes_struct *p,
10763 struct spoolss_63 *r)
10765 p->rng_fault_state = true;
10766 return WERR_NOT_SUPPORTED;
10769 /****************************************************************
10771 ****************************************************************/
10773 WERROR _spoolss_64(struct pipes_struct *p,
10774 struct spoolss_64 *r)
10776 p->rng_fault_state = true;
10777 return WERR_NOT_SUPPORTED;
10780 /****************************************************************
10782 ****************************************************************/
10784 WERROR _spoolss_65(struct pipes_struct *p,
10785 struct spoolss_65 *r)
10787 p->rng_fault_state = true;
10788 return WERR_NOT_SUPPORTED;
10791 /****************************************************************
10792 _spoolss_GetCorePrinterDrivers
10793 ****************************************************************/
10795 WERROR _spoolss_GetCorePrinterDrivers(struct pipes_struct *p,
10796 struct spoolss_GetCorePrinterDrivers *r)
10798 p->rng_fault_state = true;
10799 return WERR_NOT_SUPPORTED;
10802 /****************************************************************
10804 ****************************************************************/
10806 WERROR _spoolss_67(struct pipes_struct *p,
10807 struct spoolss_67 *r)
10809 p->rng_fault_state = true;
10810 return WERR_NOT_SUPPORTED;
10813 /****************************************************************
10814 _spoolss_GetPrinterDriverPackagePath
10815 ****************************************************************/
10817 WERROR _spoolss_GetPrinterDriverPackagePath(struct pipes_struct *p,
10818 struct spoolss_GetPrinterDriverPackagePath *r)
10820 p->rng_fault_state = true;
10821 return WERR_NOT_SUPPORTED;
10824 /****************************************************************
10826 ****************************************************************/
10828 WERROR _spoolss_69(struct pipes_struct *p,
10829 struct spoolss_69 *r)
10831 p->rng_fault_state = true;
10832 return WERR_NOT_SUPPORTED;
10835 /****************************************************************
10837 ****************************************************************/
10839 WERROR _spoolss_6a(struct pipes_struct *p,
10840 struct spoolss_6a *r)
10842 p->rng_fault_state = true;
10843 return WERR_NOT_SUPPORTED;
10846 /****************************************************************
10848 ****************************************************************/
10850 WERROR _spoolss_6b(struct pipes_struct *p,
10851 struct spoolss_6b *r)
10853 p->rng_fault_state = true;
10854 return WERR_NOT_SUPPORTED;
10857 /****************************************************************
10859 ****************************************************************/
10861 WERROR _spoolss_6c(struct pipes_struct *p,
10862 struct spoolss_6c *r)
10864 p->rng_fault_state = true;
10865 return WERR_NOT_SUPPORTED;
10868 /****************************************************************
10870 ****************************************************************/
10872 WERROR _spoolss_6d(struct pipes_struct *p,
10873 struct spoolss_6d *r)
10875 p->rng_fault_state = true;
10876 return WERR_NOT_SUPPORTED;